Converting the Silverlight Business Application Template to use Windows Authentication
For my first “real” attempt at creating a business application using Silverlight I decided to use WCF RIA Services, Silverlight 4.0, and Visual Studio.NET 2010. What easier way to get started than through a template provided by VS.NET 2010, right? Well, in its effort to make it easier it also create some headaches. Sometimes abstraction can add a learning curve as well. In this case it created some headache for me on this project. As an IT consultant for small to enterprise level business most of the usage of Silverlight will be in an Intranet zone and require Windows Integrated security where authentication and even authorization is centrally managed in Active Directory.
The Business Application Template generates XAML, services, and other code to support Forms Authentication and an Extranet scenario out-of-the-box. This is all great, but I now need to convert it to Windows Authentication. I ventured down what I thought was a simple path by following directions included as comments in the generated code. I made the switch in the App.xaml.cs file as depicted below.
1: public App()
2: {
3: InitializeComponent();
4:
5: // Create a WebContext and add it to the ApplicationLifetimeObjects
6: // collection. This will then be available as WebContext.Current.
7: WebContext webContext = new WebContext();
8: //webContext.Authentication = new FormsAuthentication();
9: webContext.Authentication = new WindowsAuthentication();
10: this.ApplicationLifetimeObjects.Add(webContext);
11: }
I changed the web.config file to have it use Windows authentication and I removed the Profile section.
1: <authentication mode="Windows">
2: <!--<forms name=".BusinessApplication1_ASPXAUTH" />-->
3: </authentication>
I ripped out all of the Login and Membership related XAML. Once I did all of this and start navigating and customizing the app I get a big fat error. WHAT?
InvalidDataContractException, A profile property does not exist for FriendlyName. I just removed all of the profile information why is this coming up? After doing some digging the implementation of AuthenticationBase<T> will iterate through each property in the User class unless there is a certain attribute property setting and try and pull it from the ASP.NET profile database using the membership provider. Here is what I found as part of the description when looking at it through RedGate Reflector,
By default, this domain service relies on the ASP.NET providers for
Membership, Roles, and Profile
and will reflect the customizations made in each.
Hmm, so how do I keep it from attempting to query the non-existent Profile. If you look at the code in the User class (see below). You will notice that it describes how to add a property that can be part of the profile, but it does not tell you how to keep it from being a part of it. Okay, so now what? I guess that means more digging. After looking through the Book Club demo from Nikhil Kothari I discovered it.
/// <summary>
/// Class containing information about the authenticated user.
/// </summary>
public partial class User : UserBase
{
//// NOTE: Profile properties can be added for use in Silverlight application.
//// To enable profiles, edit the appropriate section of web.config file.
////
//// public string MyProfileProperty { get; set; }
/// <summary>
/// Gets and sets the friendly name of the user.
/// </summary>
public string FriendlyName { get; set; }
}
Here is how you do it. You have to add the ProfileUsage attribute on your property with the IsExcluded property set to true. I discovered this by looking at a demo from.
[ProfileUsage(IsExcluded = true)]
Details can be found on MSDN for its usage. Here is a quote from the MSDN documentation.
This attribute is used by the AuthenticationBase<T> to determine how it should read from or write to the ASP.NET profile that backs the data. If a property with the same name exists in the profile, you do not need to use this attribute. If a property is not in the profile, you should set the IsExcluded property to true. If a property has a different name than the profile value that backs it, you should set the Alias property to the name of the backing value in the profile. The attribute can be used with user entities extending UserBase.
After applying the attribute, then you are ready to go. If you want to adding properties to the User class and want to set properties, the best place that I could find is in the AuthenticationService implementation and in an override of the GetAuthenticatedUser() method.
protected override User GetAuthenticatedUser(System.Security.Principal.IPrincipal principal)
{
User currentUser = base.GetAuthenticatedUser(principal);
//TODO: Add your logic to collect data and set properties on the User class.
return currentUser;
}
Hopefully this will aid you in your efforts of learning RIA services and SilverLight. Good luck!
Technorati Tags: RIA Service,WCF,Silverlight,.NET