Tag Archives: WCF

Silverlight Polling Duplex Slowness / Queuing

In a previous post I mentioned that you should probably just give up the idea of using Polling Duplex Communication endpoints in your Silverlight application if you’re going to host your WCF services from SharePoint 2007.

The main reason I cited was that hosting the service(s) in SharePoint 2007 meant you probably wanted access to the SPContext which meant you must force your WCF services to run in ASP.NET Compatibility mode. This alone doesn’t cause the problem and I did mention the issue stems from contention trying to access session state data. I dumped the whole idea of using Polling Duplex for my needs since access to the session state was necessary. It occurs to me now that not everyone needs it.

Check out this article which provided me a good deal of information when I was debugging my issue. It provides a different approach for resolving this slowness. Simply put your Polling Duplex stuff in its own service with session state disabled. That should keep things quick and happy and prevent your session-needing service calls from getting blocked.

Hope this helps,
-Erik

Pro Tip: Return the same object for WCF service methods

In a previous post I made reference to a consistent return type from my WCF services for Silverlight to consume. Here’s what it is and why I think it’s useful.

WebServiceVoidWrapper
{
    public string ExceptionMessage { get; set; }
    public DateTime LastUpdated { get; set; }
    public bool IsGroupActive { get; set; }
}

WebServiceWrapper<T> : WebServiceVoidWrapper
{
    public T Results { get; set; }
}

Each of our calls, regardless of what they’re returning, need to let the client know about certain conditions. At first we only cared to grab the exception message. Then we added the LastUpdated to be populated when working with data pieces so we could query the server to see if any changes had occurred since. Using the structure above, we could expect all our methods to at least have those members. (The VoidWrapper version is for those times we’re not returning an data from the service but we still want those fields.)

When this was our approach, we had methods scattered in various XAML pages to check for and react to these conditions and this was fine if not anemic since we were short on time and didn’t really implement nice UI interaction to deal with errors.

At some point the business requirements changed and a user could now be part of multiple groups and could be added and removed at any time. We needed a way to react to that. We easily added the field to the base response class and use exception catching on the server side to populate the field. This also meant we were going to need to handle this case all over our Silverlight application because any call could signal the IsGroupActive as false which means the user shouldn’t be able to work with local data they already have.

Rather than peppering checks for this field, popping a child window to prompt the user for a new Organization and then react to the new data we decided to handle this a little more generically. I had constructed a singleton class to act as the interface for the Silverlight application’s communication to the server. Since this singleton is active for the life of the user’s interaction with the application we used this as our starting point.

With this layer in place, we could easily wire up listeners to all our WCF service events and attach a delegate to check for the field and react to it. A quick glance shows 42 methods we’re interested in and these methods grow and shrink and change names constantly during our development cycle. Rather than putting in 42 calls to SomethingCompleted += … I wrote a bit of code to wire up the listener automatically. See previous post for info on that: Dynamically Attach Delegates to WCF Service in Silverlight.

Now with a generic listener in place to catch the user org becoming invalid, we can deal with the UI aspect. Continuing the theme of least-amount-of-code-change we targeted the MainPage object as the best place to handle the interaction with the user. MainPage is available as our Application.Current.RootVisual and can pop child windows and control other UI aspects. It also has access to the NavigationService which we’ll be using as well.

To let the MainPage know the user org has become invalid, I decided to fire a custom event from the service where we detected the error.

[In ConnectionService.cs]
public event EventHandler OnUserOrganizationNotValid;

And subscribe to that event in MainPage.

[In MainPage.xaml.cs]
public MainPage()
{
    InitializeComponent();
    ConnectionService.GetInstance().OnUserOrganizationNotValid +=
        new EventHandler(MainPage_OnUserOrganizationNotValid);
}

void MainPage_OnUserOrganizationNotValid(object sender, EventArgs e)
{
    PopUserOrganizationPicker();
}

From the event delegate we’re calling out to another function. This is because we also have the ability to allow the user to choose a new organization whenever they wish. Rather than have a duplication of code somewhere else, we made a public method that can be accessed from other views.

private OrganizationDialogActive = false;
public void PopUserOrganizationPicker()
{
    if (!OrganizationDialogActive)
    {
        OrganizationDialogActive = true;
        Dispatcher.BeginInvoke(() =>
        {
            OrganizationPicker.InitializeForm();
            OrganizationPicker.Show();
        });
    }
}

void OrganizationDialogClosed(object sender, EventArgs e)
{
    OrganizationDialogActive = false;
    ContentFrame.Refresh();
}

I’m using a property for the org dialog window which wires up the callback event on Closed event. This is nice since the window is late loaded on first use instead of at load time and since nothing really changes, we just keep it in memory.

private SelectOrganizationDialog _OrganizationPickerBackingField;
private SelectOrganizationDialog
{
    get
    {
        if (null == _OrganizationPickerBackingField)
        {
            _OrganizationPickerBackingField =
            new SelectOrganizationDialog(OrganizationDialogClosed);
        }
        return _OrganizationPickerBackingField;
    }
}

To get the user’s screen to update, we could place code to navigate in the MainPage but we’ve stuck it in the org picker child window instead. This is because our service method returns a new URL if the newly chosen org makes the user a power user which will need to send them to a new page. From the service callback in the org picker child window we call a helper method NavigateToPage.

//DefaultPage holds a relative url string for the destination page.
public static void NavigateToPage()
{
    MainPage mp = Application.Current.RootVisual as MainPage;
    Uri defaultUri = new Uri(DefaultPage, UriKind.Relative);

    if (mp.ContentFrame.Source.OriginalString.Equals(DefaultPage))
        mp.ContentFrame.Refresh();
    else
        if (!mp.ContentFrame.Navigate(defaultUri))
            mp.ContentFrame.Refresh();
}

Faleminderit!
-Erik

Creating Silverlight + WCF Apps in SharePoint 2007

I’ve seen people asking how to create WCF services from within SharePoint 2007. It’s actually really easy – much easier than ASMX web services. I could go into a lot of detail but here’s the basic steps:

  1. Create or get a package to modify the SharePoint 2007 web.config to understand WCF URL requests.
    • WCF Service requests start with ‘~’ which SharePoint doesn’t like. You need a custom HTTPModule you can add to SharePoint’s web.config to provide a virtual path provider to strip this character from the request. This is easy to find.
  2. Create a solution that contains your projects.
    • WCF Service Project. You can only target up to .NET 3.5 because SharePoint can’t run in the .NET 4 runtime and if you want your service hosted in SharePoint (to get the nifty SPContext stuff) your service will have to run in the same runtime. See notes below about specific web.config settings.
    • Web Project. This is typically a very simple project and is likely just a simple ASP.NET page with the SharePoint master page instructions and basic layout with the Silverlight app referenced.
    • Silverlight Project. The meat of your application. Create a Web Service reference to your WCF service and watch the magic. Oh, it’s not working? Yeah, there’s a few things you need to do here.

The above is pretty straight forward but won’t work until you sprinkle in some magic.

Decorate your service method with the AspNetCompatibilityRequirementsMode.Required attribute:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

WCF Services can run in an optimized pipeline to speed them up. Unfortunately this means they will run outside the traditional pipeline for ASP.NET applications. Decorating your service method this way forces your service to run in the ASP.NET pipeline. This is necessary in order for IIS to give the request an HTTPContext and for SharePoint to make an SPContext available.

The downside to this is that you can just forget about using polling duplex communication mode. (Well, you don’t have to forget about it but you’re on your own for solving this problem…) Why? Long story short the session state manager locks access on each request. The polling duplex communication works by initiating long-timeout requests to the server. If the server has nothing to say, the request eventually times out and a new request is initiated. This timeout isn’t super long in order to ensure you haven’t lost connection rather than the server has nothing to say but it is long enough to cause a slight problem. When the request is active, all other service calls are queued up because they can’t access the session state! As soon as the polling connection times out, the other requests can try their hand at executing while the polling connection reconnects and starts blocking again.

This is almost never what you want since the biggest advantage to the forced-async programming environment of Silverlight enables highly responsive designs. You could write your own session state handler with different locking mechanisms or tweak the polling timeout at the cost of increasingly talkative connections or you can go the route I prefer: create a heartbeat method using a Timer and firing an event if the service response contains something in which you’re interested. This gives you good granularity for how often your clients should ping the server with not too much more trouble. (It took me less time to roll this in a singleton connection class than it did to figure out how to configure the service endpoints for the polling duplex connection and then debug the queued service requests until I figured out what was happening.)

Configure your endpoints to use NTLM transport. This is to enable the user authentication to be passed over the wire and for SharePoint to treat the connection as if it were a browser user. SharePoint will even return the correct user in the SPContext if you interactively sign in as a different user in SharePoint. You don’t have to maintain separate user account management in your application.

<?xml version="1.0"?>
<configuration>
   <connectionStrings>
      <add name="WRDataConnectionString" connectionString="[...];Integrated Security=True" providerName="System.Data.SqlClient"/>
   </connectionStrings>
   <system.web>
      <compilation debug="false" />
      <customErrors mode="Off"></customErrors>
   </system.web>
   <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
      <bindings>
         <basicHttpBinding>
            <binding name="customBasicHttpBinding">
               <security mode="TransportCredentialOnly">
                  <transport clientCredentialType="Ntlm" />
               </security>
            </binding>
         </basicHttpBinding>
      </bindings>
      <services>
         <service behaviorConfiguration="AppServiceBehavior" name="App.WCF.Services.AppService">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="customBasicHttpBinding" contract="App.WCF.Services.IAppService">
               <identity>
                  <dns value="localhost" />
               </identity>
            </endpoint>
         </service>
      </services>
      <behaviors>
         <serviceBehaviors>
            <behavior name="AppServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
               <serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
               <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
         </serviceBehaviors>
      </behaviors>
   </system.serviceModel>
</configuration>

One thing to note in the above is no address in our endpoint. This is because we have to deploy to many environments, all of which use different naming. Instead of specifying a static address, we actually provide the service base address to the Silverlight application as part of its initial startup parameters in its hosting page using SPContext.Current to pass the current web URL. We just concatenate the service name to the end. This makes it much easier to deploy to various SharePoint environments.

If you happen to run SSL you will need to modify your web config to handle this.

<?xml version="1.0"?>
<configuration>
   <connectionStrings>
      <add name="WRDataConnectionString" connectionString="[...];Integrated Security=True" providerName="System.Data.SqlClient"/>
   </connectionStrings>
   <system.web>
      <compilation debug="false" />
      <customErrors mode="Off"></customErrors>
   </system.web>
   <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
      <bindings>
         <basicHttpBinding>
            <binding name="customBasicHttpBinding">
               <security mode="Transport">
                  <transport clientCredentialType="Ntlm" />
               </security>
            </binding>
         </basicHttpBinding>
      </bindings>
      <services>
         <service behaviorConfiguration="AppServiceBehavior" name="App.WCF.Services.AppService">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="customBasicHttpBinding" contract="App.WCF.Services.IAppService">
               <identity>
                  <dns value="localhost" />
               </identity>
            </endpoint>
         </service>
      </services>
      <behaviors>
         <serviceBehaviors>
            <behavior name="AppServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
               <serviceMetadata httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
               <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
         </serviceBehaviors>
      </behaviors>
   </system.serviceModel>
</configuration>

Your Silverlight clientconfig will need to match your endpoint to get a successful connection.

With these slight tweaks, creating SharePoint 2007 hostable WCF Services consumable by Silverlight is easy! Use a packager like WSPBuilder and building the deployment WSPs are easy too (just follow the necessary folder structure). For simplicity we deploy to subfolders in the LAYOUTS directory but you can get as creative as you like.

See you space cowboy.
-Erik

Dynamically Attach Delegates to WCF Service in Silverlight

My team has a Silverlight 4 application sitting in an ASPX page hosted from SharePoint 2007 consuming WCF Services targeting .NET 3.5 also hosted from within SharePoint. Using this setup, our service methods can access SPContext. This allows us to leverage SharePoint Groups as a way to assign roles to users to grant or deny them access to data we’re hosting in a custom database.

Through our design, we’ve been using a generic class as the response for all our methods. This lets us have fields for data we want to track during each response (an error message for instance) along with a generic field to hold specific typed data.

As our design progressed we discovered a need to see if a user has been removed from a SharePoint group which would signify their revocation of access to specific data. Rather than wait for the user to attempt access and throw an unfriendly message, we decided to add a field to our generic response wrapper. Now we only need to check this field and pop a picker dialog to let the user pick a new organization based on SharePoint Groups to which they belong.

The problem is we have 42 methods that can return this field. Attaching to all of them with specific callbacks for the different eventargs types that were generated by adding a Service Reference to the service in our Silverlight application would be ugly and a pain to maintain as our methods are added and removed as our application evolves.

Through an earlier design decision, I implemented a singleton instance for the communication to the service: ConnectionService. This seemed like a great place to implement the side-listener. Now I just needed to hook up to each of the methods and listen for the field. I accomplished this via reflection:

ConnectionService() //private constructor in singleton class
{
   …
   EventInfo[] events = WcfClient.GetType().GetEvents();

   events.ParallelForEach((evt) =>
   {
      if (evt.EventHandlerType.IsGenericType && null != evt.EventHandlerType.GetGenericArguments()[0].GetProperty("Result"))
      {
         Delegate handler = Delegate.CreateDelegate(
            evt.EventHandlerType,
            this,
            this.GetType().GetMethod("WcfClient_CheckForInvalidUserOrg", BindingFlags.NonPublic | BindingFlags.Instance));

         evt.AddEventHandler(WcfClient, handler);
      }
   });
   …
}

void WcfClient_CheckForInvalidUserOrg(object sender, AsyncCompletedEventArgs e)
{
   try
   {
      PropertyInfo pi = e.GetType().GetProperty("Result");
      if (null != pi)
      {
         WebServiceVoidWrapper result = pi.GetValue(e, null) as WebServiceVoidWrapper;

         if (null != result)
            if (!result.IsGroupActive)
               HandleUserOrgNotValid(sender, e);
      }
   }
   catch (TargetInvocationException exc)
   {
      Debug.WriteLine(exc.Message);
   }
}

Working backwards a bit you see I created a function to be attached to the events. Since all our WCF Service methods return Silverlight-generated EventArgs inheriting from AsyncCompletedEventArgs. The upside is that we can use one method and not have to much with any of the generated code to insert a different base class. The downside is we don’t have direct access to the field in which we’re interested. The Silverlight generated class contains a field called “Result” which is of the type we’re returning. In our case we’re returning from our service method. We reflect the object, ensure the Result field is present and then try to cast it to the base class of our response wrapper which contains the boolean flag we want. If the flag is false, the user’s org is no longer valid and we pass off to another function to handle it.

Now jumping up to the constructor for the singleton class I have code that will grab all the events contained in our service connection object. This object is what exposes the Async methods to our service methods and the events that are fired when the service calls complete. Then I iterate them. You can use a simple for loop for this but I decided to use an extension method that will execute the statements in parallel and wait for them all to complete before moving forward. Since the service connection exposes a couple built-in events that we don’t care about, we reflect the type to ensure it matches the signature we’re interested in from our callback.

Once we’re sure the event is probably one we’re interested in listening to, we create an event delegate of the type required by the event which is accessed from EventHandlerType. The remainder of the delegate is just grabbing the MethodInfo for our callback function and where it exists. We call AddEventHandler and that’s it!

Now when the singleton class is constructed (and the WcfClient object is connected to our service) we cycle through all the events it exposes and attach our generic handler. If we detect the user org is invalid we fire a custom event. This lets our UI pages listen if they want to react but for our purposes we’re using our Silverlight project’s MainPage to pop up a ChildWindow for the user. We do it this way because we actually have a heartbeat method which pulses the service to see if the user’s report data has changed and if so, pop a refresh message. Since this is done in a separate thread, we can’t interact with the UI directly. Instead we fire an event which is listened to by something already in the VisualTree. Calling Dispather.BeginInvoke() lets us marshal the UI work on the proper thread and show the ChildWindow.

I was pretty sure before I started this design that I could make it work but I didn’t expect it to be so succinct.

Happy Coding!
-Erik