Accessing the Membership Provider from Silverlight

by mgordon 13. May 2009 04:50

In a particular Silverlight application, I felt it would be common for a user to have the application open for long periods, but not necessarily be interacting with it all the time.  This meant that there was always a chance the user’s session would time out.  Since the application uses the Membership and Role providers, nasty errors were being raised from web service calls depending on data from these providers if the session was not available.

To handle this situation, I tested for a valid session in my services and raised a custom exception if it wasn’t available.  Then, using the ideas in my last post I trapped that exception in my Silverlight application and showed a login box to the user so they could log back into the application and re-establish a valid session.

The next piece of this puzzle to solve was how to gain access to the Membership Provider from the Silverlight application to log the user back in.  Turns out there are two ways to go and both are equally valid for an Ajax application as well as Silverlight, though one is clearly more suitable for Ajax than Silverlight.

ASP.Net Ajax

The first solution is to use functionality built into the ASP.Net Ajax framework.  There is a javascript object in the framework, Sys.Services.AuthenticationService, that provides the needed functionality.  So, if you have all the necessary parts of the Ajax framework set up, in JavaScript you can say

var ssa = Sys.Services.AuthenticationService;

ssa.login(username,
              password,
              isPersistent,
              customInfo,
              redirectUrl,
              onLoginComplete,
              onError);

Of course you pass the username and password.  IsPersistent is a bool value indicating whether or not the user wants to be “remembered” by the application.  CustomInfo can be null as can the redirectUrl.  Of course, if you would like the user to be redirected to a certain Url after a successful log in, you’d specify that Url. The last two values are pointers to the methods to call when the login has completed or has errored out.  If you’re calling this from a web page it’s straight forward and from Silverlight, you’d need to wrap this code in a JavaScript function, and then call it from Silverlight like this.

Exposing Authentication as Web Service

Brad Abrams has an excellent tutorial on how to expose the needed functionality as a web service, here.  This was the approach I ended up using in my Silverlight application because it fit well with how the rest of the application was designed.   Once the functionality has been exposed as a web service, you could call this web service the same way you’d call any other from an Ajax application.

Tags:

.Net | Silverlight | WCF | ASP.Net

WCF Exceptions in Silverlight

by mgordon 6. May 2009 08:49

I’ve been working on a fairly substantial Silverlight 2 application and finally took on an aspect of it that I had been dreading and putting off for some time – exception handling – specifically handling exceptions being thrown from my WCF services.  I just knew this was going to be a bear.  Turns out, it wasn’t quite as bad as I had feared, but it was enough trouble that I thought a blog post sharing the experience would be a good thing.

The Problem

Silverlight doesn’t communicate directly with your web services, but rather it uses the browser API for this communication.  When calling a web service, if any exception occurs, the browser converts this into a generic 400 (Page not found) error and hands it back to Silverlight.  The result is that inside your Silverlight application, you know that an exception has occurred during your call, but have no way of knowing what it was.  This problem is supposed to be fixed in version 3.

The Research

This was certainly something I didn’t want to rush into solving so I did a bit of research on the Internet before jumping in.  Some we solving this by using out parameters on their services that contained the exception information which required checking the value of this parameter after each call.  I found a solution that was quite nice on CodeProject that used attributes on the service methods and contracts and a base class for the proxy on the client.  Since I’m still using Visual Studio generated proxies in my project, this one aspect of the solution made it unusable for my purposes.  In a discussion, here, I discovered that Microsoft’s Silverlight web service team had published a solution to the problem.  I checked it out and decided on this solution for my application.  A blog post about the solution can be found here and the code can be downloaded from code.msdn.microsoft.com.

The Code and Configuration

I found a few blog posts from folks who had implemented this solution, but none that were comprehensive and none that addressed its use with Visual Studio generated proxies.  Below, then, are the steps I took to get it all working in my application.

First, download the code the Silverlight web service team makes available and compile all the solutions.  You’ll need to set references to a few of the generated assemblies.

References

In the web project containing your WCF web services, set a reference to the assembly “SilverlightFaultBehavior.dll”.  Now, in your Silverlight project set references to the assemblies “SilverlightRawFaults.dll” and “SilverlightMessageInspector.dll”.

Code

If the web project containing your WCF web services doesn’t have a Global.asax file, add it and add the following code to it.  This code will cause any service requests that fail to return a 200 status code instead of 400.

 

protected void Application_EndRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.Request.PhysicalPath.EndsWith(".svc", StringComparison.OrdinalIgnoreCase) &&
        HttpContext.Current.Response.StatusCode == 500 &&
        !HttpContext.Current.Request.Browser.Crawler &&
        HttpContext.Current.Request.Browser.EcmaScriptVersion.Major > 0)
    {
        // Set 200 if its a faulted service request
        HttpContext.Current.Response.StatusCode = 200;
    }
}
 

In any Silverlight class that makes a call to a WCF service, add the following (C#).

using Microsoft.Silverlight.Samples;
using SilverlightRawFaults;

At the point where you’re making the WCF call, you’ll be creating an instance of the proxy for that service.  Before making the call on that proxy, replace its binding by adding a line similar to this.

proxy.Endpoint.Binding = new BasicHttpMessageInspectorBinding(new SilverlightFaultMessageInspector());

This binding will ensure that the message inspector has a chance to look at the message returned from your call.

Finally, in the completed event for your service call, you’ll need to evaluate the Error property on the passed in event argument. 

if (e.Error != null && e.Error is RawFaultException)
{
    RawFaultException exception = (RawFaultException)e.Error;
    MessageBox.Show("Service says: " + exception.FaultMessage + Environment.NewLine +
        "Exception type: " + exception.FaultType + Environment.NewLine +
        "Stack trace: " + exception.StackTrace);
}
The Bug

After making the above modifications to my code, the value of the FaultMessage was not what I was expecting.  No matter what the exception was, this property always had the same generic value.  I found that there was a bug in the code provided by the Silverlight web service team and once it was corrected, all worked as expected.

Correcting the Bug

To correct the bug, open the downloaded solution called “SilverlightRawFaults”.  In the SilverlightRawFaults project, you’ll find a class called “BasicHttpMessageInspectorBinding”.  There is a property on this class called “FaultMessage” (oddly enough, the value that was incorrect).  Change this

public string FaultMessage 
{
    get { return Message; } 
}

to this

public string FaultMessage 
{
    get { return message; } 
}

Note that all I changed was the case of the “M” in “message”.  In this class, message is a member variable where Message is a property of the base class which is never set.  In the method RawFaultException sets message to the string containing the exception’s message, which is the value that should be returned.

Tags:

.Net | Silverlight | WCF

Powered by BlogEngine.NET 1.5.0.7
Theme by Extensive SEO