Application services II: configuring the client
In the first post of the series, we've configured a web app so that we can use the new application services from a client desktop app. Today we'll see how a windows forms (or other type of client desktop application) can consume those services. After creating a Windows Forms app, we need to start by adding references to the System.Web and System.Web.Extensions assemblies.
We need both because the desktop app will reuse the provider pattern (introduced by ASP.NET 2.0) to get the necessary info from the server side. What this means is that we'll need to set up the providers in the windows forms app with code similar to this one:
type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=126.96.36.199, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=188.8.131.52, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
If you're an ASP.NET developer you'll probably recognize the previous code and you'll know that it's adding two providers (one for membership and another for roles). Now, what might be strange is the type of these providers...Both of them were introduced in the latest version of the platform (take a look at the System.Web.ClientServices.Providers namespace on the System.Web.Extensions assembly) and they don't fully implement the provider interface specified by each kind of provider. For instance, the ClientFormsAuthenticationMembershipProvider won't delete or create users...In other words, these providers will only let you perform some of operations that you'd normally expect to see in a provider of each type. If you want to get a full list of the methods that each provider implements, then you'll have to go through .NET Reflector.
Now that everything is set up, we can move on and see how easy it is to validate a user. Since both providers were setup as the default providers, then we can reuse our beloved Membership and Roles classes. Let's start with authentication... If you have a login form, then you can authenticate a user by writing code similar to this:
Boolean isValid = Membership.Validate( username.Text, password.Text );
Yes, we're talking about a Windows App here :) When the previous line is executed, the ClientFormsAuthenticationMembershipProvider will call our authentication WCF service (that's why this provider expects a serviceUri attribute) which was previously configured on the server side and it will automatically set the current principal property of the current thread (ie, the Thread.CurrentPrincipal property) if the credentials are correct. If you want, after authenticating the user, you can also check if a user belongs to a specific role by calling the Roles.IsUserInRole or, if you prefer, by calling the CurrentPrincipal.IsInRole method. Now, if you think that you can use the 1st option to see if user X belongs to a role Y, then you're wrong. Unfortunately, you'll only be able to get info about the roles to which the current authenticated user has been associated (if you ask me, this sucks). In fact, you'll quickly see that this is the only thing you can do with this provider. period.
There are still some more cool things to talk about these new services, but I'll leave them for the next posts...