(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Leveraging the ASP.NET Membership in Silverlight

(6 votes)
Gill Cleeren
>
Gill Cleeren
Joined Apr 02, 2010
Articles:   63
Comments:   6
More Articles
11 comments   /   posted on Apr 06, 2010
Categories:   Line-of-Business , General

This article is compatible with the latest version of Silverlight.

Most developers working today in Silverlight probably have an ASP.NET background. I personally started with ASP.NET development way back in 2001 with the very first version of the platform. Over time, the ASP.NET platform evolved immensely and gathered some great features. One of these nice additions to the platform is the ASP.NET Membership API, introduced with ASP.NET 2.0. This API allows us to manage user authentication, role management and user profiling with ease. With ASP.NET 3.5, Microsoft added the so-called ASP.NET Application Services to make it possible to use this API from client-side technologies.

Why am I telling you all this, we’re here to learn something new about Silverlight?! In this article, I’ll show you how you can take advantage of the ASP.NET Membership API from within your Silverlight applications. We can use the authentication to allow or deny users access to a Silverlight application, block certain features if a user is not part of a particular role or use profile information.

The small application we’ll build inside this article, SilverlightSecureBank, is shown in the screenshot below. The code can be downloaded here.

image

As explained, we can leverage the authentication, role and profile mechanisms. Let’s start by looking at how we can authenticate from Silverlight.

Logging in with Silverlight

Let’s assume you’re the developer of an online banking application. The application was built a few years back with ASP.NET 2.0. Because of this, all user information is managed using the ASP.NET Membership API: the database contains usernames, passwords etc. managed by this API. Now the day has come that your bosses have decided they want to move part of the application to Silverlight. One of the requirements is of course that existing user accounts should keep working, so that the transition to this new application is smooth for the end users.

Luckily, you’re a developer who read this article and you know this requirement is easy to fulfill! The sample application already contains a SQL Server Express database with an existing regular user (john/password&1). Creating this database can be done using the ASP.NET Web Administration Tool (more info on this can be found here: http://msdn.microsoft.com/en-us/library/yy40ytx0.aspx).

In order to make it possible for a user to log on in the Silverlight applications using his existing credentials, we need to expose the ASP.NET Membership functionality as a service. However, we don’t need to create this service ourselves, since it already exists in the form of the before mentioned Application Services. The only thing that’s left for us is creating an endpoint for this service and enabling it via configuration.

Creating the endpoint is nothing more than creating an empty *.svc file (without code-behind, since the code is already available within ASP.NET). In this file, named AuthenticationService.svc here, the following code should be pasted:

<%@ ServiceHost Language="C#" Service="System.Web.ApplicationServices.AuthenticationService" %>

As can be seen, the service’s functionality is referenced here. This service needs to be configured just like a normal WCF service. To do so, inside the web.config file, the following code should be placed between the <configuration></configuration> tags.

<system.serviceModel>
  <services>
    <service name="System.Web.ApplicationServices.AuthenticationService" 
       behaviorConfiguration="AuthenticationServiceBehaviors">
      <endpoint contract="System.Web.ApplicationServices.AuthenticationService" 
          binding="basicHttpBinding" />
    </service>
  </services>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
  <behaviors>
    <serviceBehaviors>
      <behavior name="AuthenticationServiceBehaviors">
        <serviceMetadata httpGetEnabled="true"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

We still need to enable this application service though, since this is not done by default for every application. This can be done by adding the following configuration code, again between <configuration></configuration> tags.

<system.web.extensions>
  <scripting>
    <webServices>
      <authenticationService enabled="true" requireSSL="false"/>
    </webServices>
  </scripting>
</system.web.extensions>

Also, check that the authentication mode is set to Forms:

<system.web>
    <roleManager enabled="true" />
    <authentication mode="Forms" />
    <compilation debug="true" targetFramework="4.0" />
</system.web>

The service is now ready to be used by the Silverlight application. Like with regular services, we can add a service reference to it, resulting in Silverlight creating a proxy class. The service can then be used just like any other service. In the sample solution, a ChildWindow is shown to allow the user to log in, as shown in the screenshot below.

image

More importantly, let’s take a look at the code to log in the user. Upon clicking on the OK Button, the service is invoked asynchronously. We use the Login method here, which was exposed on the ASP.NET Application service.

private void OKButton_Click(object sender, RoutedEventArgs e)
{
    Authentication.AuthenticationServiceClient proxy = new Authentication.AuthenticationServiceClient();
    proxy.LoginCompleted += new EventHandler<Authentication.LoginCompletedEventArgs>(proxy_LoginCompleted);
    proxy.LoginAsync(UserNameTextBox.Text, UserPasswordBox.Password, "", true); 
}

When the service call is complete, we can check if the login was successful or not using the following simple lines of code:

void proxy_LoginCompleted(object sender, Authentication.LoginCompletedEventArgs e)
{
    if (e.Error != null)
        ErrorTextBlock.Text = e.Error.ToString();
    else if(e.Result == false)
    {
        ErrorTextBlock.Text = "Error with login, try again";
    }
    else
    {
        this.DialogResult = true;
    }
}

Apart from the Login method, several other operations of the ASP.NET Membership API are available, such as Logout, ValidateUser and IsLoggedIn. The latter comes in handy to allow us to check if the user has previously already logged in successfully. The ASP.NET Membership API uses authentication cookies on the client machine to perform this check and these are created in the exact same way when using these services from Silverlight. The code below performs this check upon initial loading of the application:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    Authentication.AuthenticationServiceClient proxy = new Authentication.AuthenticationServiceClient();
    proxy.IsLoggedInCompleted += new EventHandler<Authentication.IsLoggedInCompletedEventArgs>(proxy_IsLoggedInCompleted);
    proxy.IsLoggedInAsync();
}
 
void proxy_IsLoggedInCompleted(object sender, Authentication.IsLoggedInCompletedEventArgs e)
{
    if (e.Result)
    {
        //Set up the UI for logged in access
        UserLoginSuccess();
    }
    else
    {
        //user is already logged in
        var loginWindow = new LoginWindow();
        loginWindow.Closed += new EventHandler(loginWindow_Closed);
        loginWindow.Show();
    }
}

Because authentication cookies are used, once we’re logged in, we’ll remain so between requests, even if we close the browser.

We can now go a step further and check from Silverlight if the user is member of a specific role.

Checking the user’s role

Roles are also managed by the ASP.NET Membership API. Using roles, we have the ability to group users and more easily manage the permissions within an application. Silverlight can take advantage of the role management just like it did with the authentication.

Similarly with the authentication service, we need an *.svc endpoint (in the sample this endpoint is called RoleService.svc). The code for this *.svc file is shown below:

<%@ ServiceHost Language="C#" Service="System.Web.ApplicationServices.RoleService" %>

Also similar are the changes we need to do in the web.config. These are shown below:

<system.web.extensions>
    <scripting>
      <webServices>
        ...
        <roleService enabled="true"/>
      </webServices>
    </scripting>
  </system.web.extensions>
 
  <system.serviceModel>
    <services>
      ...
      <service name="System.Web.ApplicationServices.RoleService" behaviorConfiguration="RoleServiceBehaviors">
        <endpoint contract="System.Web.ApplicationServices.RoleService" binding="basicHttpBinding" />
      </service>
    </services>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <behaviors>
      <serviceBehaviors>
        ...
        <behavior name="RoleServiceBehaviors">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

With the role management now exposed on the service, we can use it from within a Silverlight application. In the database that comes with the download for this article, an “Administrators” role was created. One user (administrator/password&1) is added to this role. When a user from this role logs in, the application will add additional functionality to the screen in the form of a button called ChangeBalanceButton (giving each and every user access to this button would not be beneficial in a real world bank!).

On completion of a successful login attempt, the application will perform a second service call to check if the logged-in user is part of this role. In the below code, the service call is launched and when the callback is invoked, the Result property of the GetRolesForCurrentUserCompletedEventArgs parameter contains an array of strings, representing the roles the logged-in user is part of. If this array contains the string Administrators, the button’s visibility is set to true.

void loginWindow_Closed(object sender, EventArgs e)
{
    ...
    RoleService.RoleServiceClient roleProxy = new RoleService.RoleServiceClient();
    roleProxy.GetRolesForCurrentUserCompleted += 
        new EventHandler<RoleService.GetRolesForCurrentUserCompletedEventArgs>(roleProxy_GetRolesForCurrentUserCompleted);
    roleProxy.GetRolesForCurrentUserAsync();
    ...
}
 
void roleProxy_GetRolesForCurrentUserCompleted(object sender, RoleService.GetRolesForCurrentUserCompletedEventArgs e)
{
    if (e.Result.Contains("Administrators"))
    {
               ChangeBalanceButton.Visibility = System.Windows.Visibility.Visible;
    }
}

We’ll finish this article by looking at how we can leverage the profiles from ASP.NET within our Silverlight applications as well.

Changing the application based on the user’s profile

Profiles in the ASP.NET Membership API are used to store user specific information over several requests. For example, we could build a website where the user can change the theme (forums quite often offer this functionality). Of course, this is a per-user setting. Based on the logged-in user, we can retrieve this information. ASP.NET Membership takes care of storing this information and retrieving it.

As you could expect, Silverlight can take advantage of profile information as well. For example, we can change the application so that the user can select his preferred background color. This preference we will then store as profile information.

To get profiles working within our application, let’s first perform the necessary changes within the hosting site. Similarly, we need again an *.svc endpoint. In the sample, this is called ProfileService.svc.

<%@ ServiceHost Language="C#" Service="System.Web.ApplicationServices.ProfileService" %>
 
<configuration>
  <system.web>
   ...
    <profile>
      <properties>
        <add name="Color" type="string" defaultValue="LightGray" />
      </properties>
    </profile>
  </system.web>
 
<system.web.extensions>
    <scripting>
      <webServices>
        ...
        <profileService enabled="true" readAccessProperties="Color" writeAccessProperties="Color"/>
      </webServices>
    </scripting>
  </system.web.extensions>
 
  <system.serviceModel>
    <services>
      ...
      <service name="System.Web.ApplicationServices.ProfileService" behaviorConfiguration="ProfileServiceBehaviors">
        <endpoint contract="System.Web.ApplicationServices.ProfileService" binding="basicHttpBinding" />
      </service>
    </services>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <behaviors>
      <serviceBehaviors>
        ...
        <behavior name="ProfileServiceBehaviors">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

We can now use the profile information in our application by first adding a service reference to the service from within the Silverlight application. In the application, two buttons were added so that the user can select his preferred background color once logged in. If a color, stored as string, is found in the profile information, this is then used to set the background color. That means that there are actually two parts here: setting the information and retrieving it.

Let’s first look at the code to retrieve the profile information. The service sends back a Dictionary<string, object>, where the key is “Color” and the value the stored string.

private void CheckProfileInformation()
{
    ProfileService.ProfileServiceClient profileProxy = new ProfileService.ProfileServiceClient();
    profileProxy.GetAllPropertiesForCurrentUserCompleted += 
        new EventHandler<ProfileService.GetAllPropertiesForCurrentUserCompletedEventArgs>
        (profileProxy_GetAllPropertiesForCurrentUserCompleted);
    profileProxy.GetAllPropertiesForCurrentUserAsync(true);
}
 
void profileProxy_GetAllPropertiesForCurrentUserCompleted(object sender, ProfileService.GetAllPropertiesForCurrentUserCompletedEventArgs e)
{
    if (e.Error == null)
    {
        string color = e.Result["Color"].ToString();
 
        switch (color)
        {
            case "LightGray": LayoutRoot.Background = new SolidColorBrush(Colors.LightGray);
                              break;
            case "Red": LayoutRoot.Background = new SolidColorBrush(Colors.Red);
                        break;
            case "Blue": LayoutRoot.Background = new SolidColorBrush(Colors.Blue);
                         break;
            default: LayoutRoot.Background = new SolidColorBrush(Colors.LightGray);
                     break;
        }
    }
}

When the user clicks on a button, his or her new selection is stored. To do so, we have to create the Dictionary<string,object> ourselves and pass this along to the service. This is done in the code below:

private void ChangeColorForUser(string color)
{
    ProfileService.ProfileServiceClient profileProxy = new ProfileService.ProfileServiceClient();
    Dictionary<string, object> profileInfos = new Dictionary<string, object>();
    profileInfos.Add("Color", color);
    profileProxy.SetPropertiesForCurrentUserAsync(profileInfos, false, profileInfos);
    profileProxy.SetPropertiesForCurrentUserCompleted += 
        new EventHandler<ProfileService.SetPropertiesForCurrentUserCompletedEventArgs>(profileProxy_SetPropertiesForCurrentUserCompleted);
}
 
void profileProxy_SetPropertiesForCurrentUserCompleted(object sender, ProfileService.SetPropertiesForCurrentUserCompletedEventArgs e)
{
    CheckProfileInformation();
}

Summary

Using the power of the ASP.NET Membership API, we can easily use authentication in our Silverlight applications. This integration makes it possible to easily migrate existing ASP.NET applications to Silverlight, since the authentication mechanism can be leveraged. This way, when migrating, users don’t even need to change their user accounts.

Bio

Gill Cleeren is Microsoft Regional Director (www.theregion.com), MVP ASP.NET, INETA speaker bureau member and Silverlight Insider. He lives in Belgium where he works as .NET architect at Ordina. Passionate about .NET, he’s always playing with the newest bits. In his role as Regional Director, Gill has given many sessions, webcasts and trainings on new as well as existing technologies, such as Silverlight, ASP.NET and WPF. He also leads Visug (www.visug.be), the largest .NET user group in Belgium. He’s the author of the upcoming book called Silverlight 4 Data and Services Cookbook. You can find his blog at www.snowball.be.


Subscribe

Comments

  • -_-

    RE: Leveraging the ASP.NET Membership in Silverlight


    posted by rical on Apr 24, 2010 13:58

    Great article! thanks..

    I've a question, is the communication secure enough when passing the membership sensitive data via WCF?

  • -_-

    RE: Leveraging the ASP.NET Membership in Silverlight


    posted by Zafar on Apr 25, 2010 15:23
    Very Nice, It is very helpful.
  • -_-

    RE: Leveraging the ASP.NET Membership in Silverlight


    posted by Zeus79 on Jun 09, 2010 00:59

    Thanks a lot.

    If I wanted to use

    Authentication.AuthenticationServiceClient proxy = new Authentication.AuthenticationServiceClient();

    txtUser.Text = proxy.ClientCredentials.UserName.UserName;

     

    , as could do that?

  • -_-

    RE: Leveraging the ASP.NET Membership in Silverlight


    posted by sridhar on Jun 18, 2010 15:02

    Thanks for sharing your knowledge.

    -Sridhar

  • adefwebserver

    RE: Leveraging the ASP.NET Membership in Silverlight


    posted by adefwebserver on Jun 27, 2010 22:18
    Very well done. Clear and complete.
  • -_-

    RE: Leveraging the ASP.NET Membership in Silverlight


    posted by Shimmy on Dec 25, 2010 23:52

    How would you create a custom membership provider with Silverlight 4 & RIA Services against a simple Username/Password User table that is exposed with EF 4?

    View: http://forums.silverlight.net/forums/p/208348/489645.aspx#489645

  • -_-

    RE: Leveraging the ASP.NET Membership in Silverlight


    posted by Brent on Feb 23, 2011 00:31
    I'm able to use the authentication service to login, but when  roleProxy.GetRolesForCurrentUserAsync() calls back, the roles are always null even though I have several set up for this user. Any idea why this would be? How does GetRolesForCurrentUserAsync() know who the current user is?
  • paul3654

    Re: Leveraging the ASP.NET Membership in Silverlight


    posted by paul3654 on Jul 13, 2011 17:52

    Hi

    I know this is an old article but could you tell me how this app knows where the membership database is as i've checked the code and config files from the sample and there's no sign of it anywhere.

    Thanks

    Paul

  • IvanL1234

    Re: Leveraging the ASP.NET Membership in Silverlight


    posted by IvanL1234 on Aug 06, 2011 19:06
    Great article - do you have any examples of this using VB.NET. I am just moving from VB6 to VB.NET and I am trying to learn how to program examples like this using tutorials such as this one: From VB6 to VB.NET. Seeing your example here in VB.NET would be very helpful. Thanks!
  • ImageTrail

    Re: Leveraging the ASP.NET Membership in Silverlight


    posted by ImageTrail on Nov 24, 2011 07:45
    I am working on integrating a Silverlight application into my stock photography website. I am wondering if the client side authentication is shared with the server side. Meaning, do I have to have them login again to the Silverlight application like shown here, if the user has already logged in using classic asp.net login controls. Thanks.
  • Param

    Re: Leveraging the ASP.NET Membership in Silverlight


    posted by Param on May 23, 2012 07:46

    Thanks

    Thats really helpful. But I would like to ask if there is any alternate for this?

Add Comment

Login to comment:
  *      *