Deploying a Silverlight Application and WCF Service to IIS

While deploying a Silverlight application on IIS today, I learned several new things. Let me express my observations; This post is going to describe the security settings for WCF service in web.config. To start, I assume that you are using either Windows or Forms authentication and denying all the anonymous users as described in a previous post.

First, make sure to remove the mexHttpBinding endpoint as this requires you to enable anonymous access to the website in IIS. The mexHttpBinding endpoint will look something like:

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

 
BasicHttpBinding

Typically, in your application, you will also be using some custom basicHttpBinding configuration for your WCF service endpoint, like this one:

<endpoint address="" binding="basicHttpBinding"
 contract="SilverlightApplication.Web.WCFService"
 bindingConfiguration="myCustomBasicHttpBinding" />

Using a custom binding allows you to configure buffers and quotas as described in this post. The definition of this custom binding will look something like:

<bindings>
 <basicHttpBinding>
  <binding name="myCustomBasicHttpBinding">
  <security mode="TransportCredentialOnly">
   <transport clientCredentialType="None"/>
  </security>
  </binding>
 </basicHttpBinding>
</bindings>

The <transport clientCredentialType=”None”/> is the main point of interest here. If you are using Forms Authentication, you need to allow anonymous access through IIS and set the clientCredentialType to None. If you want to run your application under Windows Authentication, you should use clientCredentialType="xxxx" where xxxx is the corresponding IIS authentication type. So, to work with Integrated Windows/Basic/Digest/NTLM Authentication, the xxxx should be replaced by Windows/Basic/Digest/Ntlm respectively.

 

Update: Custom Binary Binding

Similar change is required for custom binary binding:

<customBinding>
 <binding name="myCustomBinaryBinding">
  <binaryMessageEncoding >
   <readerQuotas ... />
  </binaryMessageEncoding>
  <httpTransport authenticationScheme="Anonymous" ... />
 </binding>
</customBinding>

Again, the point of interest is the authenticationScheme attribute in the httpTransport element that needs to match the IIS authentication setting (e.g. Anonymous for Forms Authentication, Ntlm/Basic/Digest for Windows Authentication).

This way, the WCF service should work without any problems.

Retrieving huge amount of data from WCF service in Silverlight application

Today, I was trying to figure out why my WCF service call was always throwing the generic NotFound exception when trying to retrieve large datasets. I had all the buffer limits set to 2147483647 (int.MaxValue) at Silverlight service configuration file as well as WCF service configuration section under web.config. Some more analysis revealed that I was getting a System.Net.WebException, saying: The underlying connection was closed: The connection was closed unexpectedly. After some research, I found that I need to set the maxItemsInObjectGraph for dataContractSerializer to some higher value in my web.config.

So, if you are trapped in a similar situation, here are two steps to ensure that you can retrieve large amount of data from WCF service:

1. Enable Silverlight client to retrieve huge chunks of data by enabling large buffers. You need to increase buffer and message size limits for the binding inside ServiceReferences.ClientConfig with something like:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_SilverlightWCFService"
                maxBufferSize="2147483647"
                maxReceivedMessageSize="2147483647">
                <security mode="None" />
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:1252/SilverlightWCFService.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SilverlightWCFService"
            contract="SilverlightWCFService.SilverlightWCFService" name="BasicHttpBinding_SilverlightWCFService" />
    </client>
</system.serviceModel>

2. Enable WCF service to send large amount of data. You need to set the binding buffer limits as well as tje DataContractSerializer’s maxItemsInObjectGraph value. Here’s an extract from web.config with all the limits set to maximum:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <!-- Create a custom binding for our service to enable sending large amount of data -->
            <binding name="MyBasicHttpBinding"
                maxBufferPoolSize="2147483647"
                maxReceivedMessageSize="2147483647"
                maxBufferSize="2147483647">
                <readerQuotas
                    maxArrayLength="2147483647"
                    maxBytesPerRead="2147483647"
                    maxDepth="2147483647"
                    maxNameTableCharCount="2147483647"
                    maxStringContentLength="2147483647" />
            </binding>
        </basicHttpBinding>
    </bindings>

    <behaviors>
        <serviceBehaviors>
            <!-- Enable the serializer to serialize greater number of records -->
            <behavior name="SilverlightWCFLargeDataApplication.Web.SilverlightWCFServiceBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
                <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="false"/>
    <services>
        <!-- Bind the WCF service to our custom binding -->
        <service behaviorConfiguration="SilverlightWCFLargeDataApplication.Web.SilverlightWCFServiceBehavior"
                name="SilverlightWCFLargeDataApplication.Web.SilverlightWCFService">
            <endpoint address="" binding="basicHttpBinding"
                bindingConfiguration="MyBasicHttpBinding"
                contract="SilverlightWCFLargeDataApplication.Web.SilverlightWCFService"/>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
</system.serviceModel>

That was all related to sending greater amount of data from WCF service to Silverlight application. However, if you want to send large amount of data from Silverlight to WCF service, you need one more step as you can reach the maximum permitted http request length limit (this is 4MB by default). This again can be solved by tweaking the web.config. E.g. to allow 10MB data, you need something like:

  <httpRuntime maxRequestLength="10240" />

That’s all. Let’s enjoy developing LOB applications with this great platform.

IEnumerable.ToObservableCollection

In WPF/Silverlight, binding UI objects such as DataGrid or ListBox to collections is typically done using an ObservableCollection instead of the generic List object. This way, our UI is automatically synchronized since the observable collection provides event notification to WPF data binding engine whenever items are added, removed, or when the whole list is refreshed. The LINQ extension methods that return a collection actually return IEnumerable<T>. The .NET framework for Silverlight provides built-in extension methods to convert IEnumerable<T> to List<T> and Array<T> but there’s no method available to convert the collection to ObservableCollection<T>(WPF developers can simply use this constructor overload) . So here’s one you may find useful:

public static class CollectionExtensions
{
    public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> enumerableList)
    {
        if (enumerableList != null)
        {
            //create an emtpy observable collection object
            var observableCollection = new ObservableCollection<T>();

            //loop through all the records and add to observable collection object
            foreach (var item in enumerableList)
                observableCollection.Add(item);

            //return the populated observable collection
            return observableCollection;
        }
        return null;
    }
}

Extension methods are very powerful and I am planning to post an example demonstrating their potential.

Securing Silverlight Application and WCF Service using ASP.NET Authentication Techniques

Security is an issue that experts are discussing since the birth of Silverlight. A typical enterprise Silverlight application will consist of one or more Silverlight pages communicating with one or more WCF services. There are three major security concerns here:

  1. Silverlight 2 supports communication with a WCF service in simple text (the basicHttpBinding), so anyone can use a packet sniffer (e.g. Fiddler) to read our data.
  2. Anyone can access our WCF service, call its methods and get our data.
  3. Anyone can download our Silverlight application (the .xap file), open it (since it is simple a zip file), extract the DLLs and use Reflector to read all our code.

The first problem can be solved by securing the transmission via transport security (using https protocol). More on this can be found at MSDN here. In this post, I will try to address the last two issues.

The good thing is that the Silverlight application and WCF service is hosted inside an ASP.NET website and luckily ASP.NET provides good tools around authentication so we can apply ASP.NET authentication techniques to secure those. The approach I like is to secure the entire ASP.NET web application using either Windows or Forms authentication and deny all anonymous users. This can be done by configuring the web.config as:

  <authentication mode="Windows"/> <!-- or Forms -->
  <authorization>
    <deny users="?"/>
  </authorization>

This way, if anyone tries to access the WCF service, or download the Silverlight .xap file, or view a page inside the ASP.NET website, the ASP.NET engine authenticates the request and only authorized users are able to view the application or use the service.

So now, if our application is configured to use Windows authentication, the ASP.NET engine authenticates the request via integrated windows authentication. If it succeeds, users are automatically redirected to the Silverlight application; otherwise they get a HTTP 401.1 – Unauthorized message.

And, if our application is configured to use Forms authentication, the ASP.NET engine takes the user to an aspx login page. Once the user is validated (we can use either ASP.NET built-in authentication or any custom implementation to authenticate the user), he/she is redirected to the Silverlight application.

To observe this, you can download this application (Be sure to first rename the file to zip; this is a WordPress requirement) and toggle its authentication technique between Windows and Forms using web.config.

Note that the application also demonstrates how to get the logged in user in Silverlight using a WCF service call. The key is that we can use System.Web.HttpContext.Current.User to get the current user principal if the WCF service is running in ASP.NET compatibility mode.


Screenshot of demo application

At this point, we have made sure that our application and WCF service is only accessible to authorized users. But the problem still exists to a small extent, although narrowed down to authorized users instead of general public. To further secure our application, we need to use some .NET obfuscater. This will ensure that no one, including authorized users, will be able to decompile our code using .NET reflector. And, to further enhance our WCF service security, we need to implement declarative or imperative security checks for our service methods. As with typical ASP.NET applications, we may need a custom implementation of IPrincipal and IIdentity for securing the WCF service using declarive security attributes.

That’s all. Let me know what you do think in the comments section below.

Using relative URLs to access WCF services in Silverlight

If you are developing a silverlight application with a WCF service, chances are that you will encounter a Service Not Found error due to any of the following reasons:

  • The VS Development Server port changed
  • You deployed your application on IIS for testing.
  • You deployed your application on any other computer.

Now there are two apparent choices:

  • Modify the URL in ServiceReferences.ClientConfig file
  • Use “relative” URLs instead of directly instantiating the service client.

The first solution is to modify ServiceReferences.ClientConfig file and correct the URL of the service. However, this is difficult once the application is deployed since the config file is contained inside the .xap file. I will present the second solution here.

Replace you service client instantiation (the following code):

 MyServiceClient svc=new MyServiceClient();

with a method call GetMyServiceClient() as:

 MyServiceClient svc = GetMyServiceClient();

And define GetMyServiceClient() as:

private MyServiceClient GetMyServiceClient()
{
  Binding binding = new System.ServiceModel.BasicHttpBinding();
  EndpointAddress endpoint = new EndpointAddress(
	new Uri(Application.Current.Host.Source, "../MyService.svc"));
  MyServiceClient service = new MyServiceClient(binding, endpoint);
  return service;
}

The above code dynamically builds the service URL from application path. It is a good practice to have service initialization code in one place and you can also control certain other settings (e.g. max buffer size, timeout settings) for your service in that method.

If you need to use the configurations from ServiceReferences.ClientConfig file and modify just the url, you may use another overload that takes the configuration name as parameter:

private MyServiceClient GetMyServiceClient()
{
  EndpointAddress endpoint = new EndpointAddress(
	new Uri(Application.Current.Host.Source, "../MyService.svc"));
  MyServiceClient service = new MyServiceClient("CustomBinding_MyService", endpoint);
  return service;
}

More controls for Silverlight: Silverlight Toolkit Released

Microsoft has released some new controls for Silverlight 2 with full source codes. These new controls include:

  • AutoCompleteBox
  • Chart
  • DockPanel
  • Label
  • Expander
  • TreeView
  • UpDown
  • ViewBox
  • WrapPanel
  • ImplicitStyleManager
  • Themes

Check out: http://www.codeplex.com/Silverlight

Silverlight 2 RC0 Released

Finally, the first public release candidate version has been released. InshaAllah, I will have more posts on this after Ramadhan.

A few links:
Official site: http://silverlight.net/GetStarted/sl2rc0.aspx
ScottGu’s blog: http://weblogs.asp.net/scottgu/archive/2008/09/25/silverlight-2-release-candidate-now-available.aspx

Silverlight article posted at CodeProject

At last, I was able to complete and post my article: “My First Data Application in Silverlight” at CodeProject here: http://www.codeproject.com/KB/silverlight/MySilverlightDataApp.aspx
This one is a detailed article intended for beginners starting Silverlight. It discusses how data from a database can be retrieved and displayed in a silverlight application. It discusses how LINQ objects are returned using a WCF service and consumed in a silverlight application. On the layout side, it looks at the ListBox and DataGrid and provides an introduction to the data templates too. I think that most of the silverlight programmers have past experience of ASP.NET so I also discussed the similarities between ASP.NET and Silverlight. I hope people will find this article beneficial.

Silverlight-enabled WCF Service template

Before Beta 2 of silverlight 2, we needed some tweaks with the standard WCF service template to use it in our silverlight application. But luckily, the new Silverlight-enabled WCF Service template does the job lot easier for us. Now we just need to define our methods(marked with OperationContract atribute) in the service.svc.cs file and we are ready to consume it. No need to change the binding configuration to basicHttpBinding, no need to add ASP.NET compatibility support in special cases, no need to define method signatures in a separate contract file. Just use the new template and use the service in your silverlight application without any worries.

I won a Silverlight competition

I am very glad to announce that yesterday, 4th of August, I stood first in a silverlight competition held at Sir Syed University of Engineering and Technology. In the 8 hour competition, the participants were asked to make a custom control “Drag and Drop Shopping Cart” in Silverlight 2 Beta 2. Here were the prizes I got:

  • MSDN Premium Subscription for 1 Year (Total Market Value: $10, 939)
  • 10,000 Rupees cash

It was a very wonderful experience. You can download my code here. Be sure to rename the file as a zip for extraction.

Follow

Get every new post delivered to your Inbox.

Join 52 other followers