SharePoint Experts, Information Architects, Expert Witness

We provide consulting in a broad array of business and technology from architecture to design to deployment of global systems with a focus on surfacing data in the enterprise. Specialists in Microsoft, we are a premier provider of SharePoint Expertise (including 2016 and Office 365). We also provide Expert Witness/Legal Expert in eDiscovery, source discovery, patent infringement, piracy and more! We also have established SICG DLDS s.a. - our counterpart in Costa Rica that specializes in water systems (http://www.crwatersolutions.com) - Contact me direct: david_sterling@sterling-consulting.com or call 704-873-8846 x704.

Search This Blog

Monday, November 29, 2010

Binding within Silverlight DataGrids and Controls

When trying to bind to controls and cells within DataGrids (particularly when using DataTemplates), it can be hard to figure out when you are not getting a value when you have a properly formed control as in:

<TextBlock Text="{Binding MyTextField}"...

If the value is not appearing (and you are not getting an error), this could mean that you have to preface the binding so Silverlight can 'find it' - this is done using either CellValue or RowValue as in:

<TextBlock Text="{Binding CellValue.MyTextField}"...

or

<TextBlock Text="{Binding RowValue.MyTextField}"...

Have fun...

Troubles using Dialog Boxes in Silverlight

I've often come across this but after working on a long project, often forget the basics - as in using Dialog boxes for File operations. The stanard error is "Dialogs must be user-initiated" which is a little off from the point - you'd expect that a click event could also open a dialog however it is because the threading (context) of the Dialog would be lost in the event.

The solution is simple - simply put all of the Dialog logic in its own method and call the method from the click event:

private void ExportFile_Click(object sender, RoutedEventArgs e)
{
              ExportTheFile();
}

private void ExportTheFile();
{
     SaveFileDialog SFD = new SaveFileDialog();
     SFD.DefaultExt = "*.txt";
     SFD.Filter = "Text (*.txt) | *.txt|All files (*.*)|*.*";
     if (SFD.ShowDialog())
     {
            StreamWriter OutStream = new StreamWriter(SFD.OpenFile());
            ...
      }
}

Thursday, November 18, 2010

Using Properties in Silverlight User Controls

When you are using Silverlight User Controls (or custom controls) you may have a need to pass properties between the main control and the user control (i.e. Main.xaml to MyCustom.xaml). If you are used to traditional SharePoint development, you are familiar with defining properties as so:
//// Resource Start Date:
private string _resrcStartDate = "";
public string ResourceStartDateIn
{
    get
    {
         return _resrcStartDate;
    }
    set    
    {
        _resrcStartDate = value;
    }
}

You will find that this works fine when you create a control via code or even if passing a 'hard coded' value to it - for example:
<local:MyCustomControl x:Name="CustControl" ResourceStartDateIn="01/01/2011" />

However, if you want to use this control for binding, for example using it in a DataGrid (or AgDataGrid), you'll find this does NOT work - in fact, in most cases, the project will simply crash without any indication of what is what. For example:

<local:MyCustomControl x:Name="CustControl" ResourceStartDateIn="{Binding Path=ResStartDate}" />

OR:

<local:MyCustomControl x:Name="CustControl" ResourceStartDateIn="{Binding Path=ResStartDate, Converter={StaticResource dateConverter}}" />

Note: the use of the dateConverter simply returns the date as a string - the first one assumes a true date.
The fix is really quite simple - Silverlight objects can pass values back and forth, but binding is another matter; in order to do this, Silverlight needs a "Dependency Property" it can use to maintain the information. To do this, simply change the way you define the property as so:

//
// Resource Start Date:
public static readonly DependencyProperty ResourceStartDateInProperty = DependencyProperty.Register("ResourceStartDateIn", typeof(string), typeof(MyCustomControl), null);
public string ResourceStartDateIn
{
    get { return (string)GetValue(ResourceStartDateInProperty); }
    set { SetValue(ResourceStartDateInProperty, value); }
}
//

NOTE: There is much more to the dependency property - this example is simply a quick and dirty for the SharePoint folks doing development.

Sunday, November 7, 2010

Debugging Silverlight and SharePoint

If you are like me, you've had lots of fun trying to debug Silverlight projects combined with WCF and SharePoint. The problem is that unless Silverlight is 'hosted' from the SharePoint site itself, you cannot debug it if you directly access the SharePoint API in the WCF code (it fails because you are not authenticated, alal the double hop issue). Errors include "No Cross Domain policy found" or failing on returning data (the Async call fails).

After much screwing around, I finally came up with a short way to do it reliably:

SIDE NOTE: Look into the Winsmarts tool for enabling Silverlight - I didn't need it for this but have used in the past - see : http://spwcfsupport.codeplex.com/ - as it turns out, that is only required for WCF. I found that using SharePoint web services gives you a big bang for the buck; in most cases you don't have to worry about authentication (users usually have the rights needed to run SP Web services) and you get great access (not as much as the API granted) to SharePoint lists, files, etc.

1) First off, create a new folder in the SharePoint site - i.e. c:\inetpub\wwwroot\wss\VirtualDirectories\70 (I'm using 70 as the sample port - this is whatever port you are using); name is not important but I use "SilverLtApps" (you can alternately use a SharePoint library but for debug, that requires you to upload changes each time). In practice, I've started out using the directory but when complete, simply deleted the direcotry and created a library of the same name (thus not having to change the URL in the content editor web part as you will see below).

2) Next, create your Silverlight Application using the standard setup (sellect Host the Silverlight application in a new Web Site).

3) After the project loads, create a new HTML file in the Silverlight that does a redirect to the SharePoint Site where Silverlight is to be used:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<meta HTTP-EQUIV="REFRESH" content="0; url=http://myspsite:70/Pages/default.aspx">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Untitled Page</title>
</head>
<body>
</body>
</html>
4) Next, right click on the Solution and Set Startup Projects. Change the Startup Project to 'Single startup project' to the Silverlight project (not the .Web project).

5) Next, right click on the Silverlight Project and select Properties; on the Debug tab under Start Action, click Specific Page and select the HTML page you created in step 3. ALTERNATELY - Right click on the HTML file and select "Set as Start page".

6) Still in properties, click the Build tab - set the Output path to the folder created in Step 1.

7) Now create a clientaccesspolicy.xml file for the site - this can be generic (wide open) as so:

<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain url="*" />
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true" />
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

OR You can set it specific to the domain/site:

<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain url="http://MySPSite" />
      </allow-from>
      <allow-from http-request-headers="SOAPAction">
        <domain uri="http://MySPSite" />
        <domain uri="https://MySPSite" />
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true" />
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>
If you want to use a CrossDomain.xml file as well (this is a fall back to Adobe Flash time), it looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-http-request-headers-from domain="*" headers="*" />
</cross-domain-policy>
8) VERY IMPORTANT: Using SharePoint Designer, open the site and upload the file(s) to the ROOT of the site - you can add the files to the actual file root as well but this depends on if you have access to the file system or not - if you can use Designer, do so.

9) Next, upload the Silverlight.js file that is included in the .WEB project (or copy to the root folder if you have access).

10) If you hit F5 or Debug > Start Debugging, the site should come up as expected.

11) Now, to test your Silverlight, edit the page in SharePoint and add a Content Editor Web Part - in the Source simply put in the required settings for the control (note that the Script inclusion is optional but I generally use it - it also allows you to point to the Silverlight.js file if you have to upload it to a SharePoint Library instead of using the file system):

    <script type="text/javascript" src="Silverlight.js"></script>
    <script type="text/javascript">
        function onSilverlightError(sender, args) {
            var appSource = "";
            if (sender != null && sender != 0) {
              appSource = sender.getHost().Source;
            }
           
            var errorType = args.ErrorType;
            var iErrorCode = args.ErrorCode;
            if (errorType == "ImageError" || errorType == "MediaError") {
              return;
            }
            var errMsg = "Unhandled Error in Silverlight Application " +  appSource + "\n" ;
            errMsg += "Code: "+ iErrorCode + "    \n";
            errMsg += "Category: " + errorType + "       \n";
            errMsg += "Message: " + args.ErrorMessage + "     \n";
            if (errorType == "ParserError") {
                errMsg += "File: " + args.xamlFile + "     \n";
                errMsg += "Line: " + args.lineNumber + "     \n";
                errMsg += "Position: " + args.charPosition + "     \n";
            }
            else if (errorType == "RuntimeError") {          
                if (args.lineNumber != 0) {
                    errMsg += "Line: " + args.lineNumber + "     \n";
                    errMsg += "Position: " +  args.charPosition + "     \n";
                }
                errMsg += "MethodName: " + args.methodName + "     \n";
            }
            throw new Error(errMsg);
        }
    </script>

    <div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="800" height="320">
    <param name="source" value="/SilverLtApps/TestSPService.xap"/>
    <param name="onError" value="onSilverlightError" />
    <param name="background" value="white" />
    <param name="minRuntimeVersion" value="3.0.40624.0" />
    <param name="autoUpgrade" value="true" />

    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
      <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
    </a>
     </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>

Note the location of the .XAP file points to the relative folder created in step 1 - be aware that if you are using subsites, the url may need to be the full URL less the http://<site> part - example: http://site/subsite/subsite/ would be /subsite/subsite/. Close the content editor part and save/publish the page.

12) Add a button or some code and set a few brakepoints in your Silverlight app and happy debugging!!!!

Setting Service Reference URL in Silverlight

Like I'm sure some of you have, I spent a good half day trying to find out the best way to dynamically assign a service reference in Silverlight. In my case, it happened to be using the SharePoint Lists service wherein, the URL to the service will change in every environment. In addition, this is a production system with no access.

After much searching (and weeding through every WCF explaination that was of no help), I discovered a comment in a post that answers the problem. When you establish the service, you simply need to specify the proper URL (I pass it to the code using Silverlight Initparams) - PROBLEM SOLVED!!

NOTE: Notice that I enabled it to pull the actual Service Path in the event I just want to change the primary URL.

//
// SETUP THE SOAP CLIENT:
//
SPListsRef.ListsSoapClient ListRefSoapClient = null;
//
bool FullServiceURLPassed = true;
string ServiceOrSiteURL = "http://paspdev1x64:70/_vti_bin/Lists.asmx";

if (FullServiceURLPassed)
{
string url = new Uri(Application.Current.Host.Source, ServiceOrSiteURL).AbsoluteUri;
ListRefSoapClient = new SPListsRef.ListsSoapClient("ListsSoap", url);
}
else
{
string SetServiceURL = "http://paspdev1x64:70/";
//
// Get the existing service URL:
//
SPListsRef.ListsSoapClient sr = new SPListsRef.ListsSoapClient();
//
// Fix the channel:
//
string ServiceURL = sr.InnerChannel.Via.ToString();
sr = null;
//
int LocOf = ServiceURL.IndexOf("/", 8);
string SvcURLOnly = ServiceURL.Substring(LocOf, ServiceURL.Length - LocOf);
if (SetServiceURL.LastIndexOf("/") == (SetServiceURL.Length - 1))
{
SetServiceURL = SetServiceURL.Substring(0, SetServiceURL.Length - 1);
}
//
SetServiceURL = SetServiceURL + SvcURLOnly;
string url = new Uri(Application.Current.Host.Source, ServiceOrSiteURL).AbsoluteUri;
ListRefSoapClient = new SPListsRef.ListsSoapClient("ListsSoap", url);
}

Saturday, November 6, 2010

Publishing Error in SharePoint 2010 - The form cannot be rendered

I've found this around in various forms - How to correct Publishing Error in SharePoint 2010:

The form cannot be rendered. This may be due to a misconfiguration of the Microsoft SharePoint Server State Service. For more information, contact your server administrator.

To fix this, login to the server running Central Administration, click Start > Microsoft SharePoint 2010 Products > SharePoint 2010 Management Shell OR Start > Administrative Tools > Windows Powershell Modules

In the Powershell, type in the following to create a new Service Application:

$serviceApp = New-SPStateServiceApplication -Name “State Service”

Next, create the State Service Database and associate it with a service application:

New-SPStateServiceDatabase -Name ”StateServiceDatabase” -ServiceApplication $serviceApp

Last, create a State Service Application Proxy and associate it with the service application:

New-SPStateServiceApplicationProxy -Name ”State Service” -ServiceApplication $serviceApp -DefaultProxyGroup
Exit the Powershell and run reset IIS - Start > Run > IISReset /noforce

Thursday, November 4, 2010

Setting Script, Execute Folder Permissions in IIS 7.5

Was working on an issue with Silverlight the other day and wanted to verify the folder settings in IIS 7.5 and it occurred to me I'd forgotten. I checked around and it took a few minutes to find - but too long so here's the short of it:

Open Internet Information Services Manager (IIS)
Expand the web site in the left hand panel
Locate the folder and click on it to select it
Double click 'Handler Mappings' in the middle panel
On the right hand panel, click 'Edit Feature Permissions...'
Set permissions as desired

Was simple, but they've made it a four step process in 7/7.5...