This post will show you how to create a custom RIA Authentication system that will use DotNetNuke as the store for the users we can log in as. DotNetNuke will also be used to host the Silverlight application so we need to make a few changes to the way you normally build a Silverlight Navigation Application. So lets get started:
- You will need a running instance of DNN to host the application so set one of those up.
- Create a new Silverlight Business Application and call it “DNNRIA”.
- Next add a new Web Application project and call it SilverlightShell, this will be the hosting module for the Silverlight application.
- Remove the Default.aspx page and add a new user control called Shell.ascx.
- Add a new folder called Dependencies and copy in the DotNetNuke.dll from your running instance of DNN and add a reference to it.
- Now modify the Shell.ascx.cs file so it inherits from PortalModuleBase in the DotNetNuke.dll like so
namespace SilverlightShell
{
public partial class Shell : PortalModuleBase
{
}
}
- Add a new Class Library – a normal one not a Silverlight one – to the solution and call it AuthenticationServices. This where we will add our custom authentication code.
- If you have a look in the web application added when you created the Silverlight Business Application you will see three classes. Since we need these to be loaded with DNN copy them to the new AuthenticationServices project and change the name spaces to AuthenticationServices.
- You will now need to add references to:
- System.ComponentModel.DataAnnotations – make sure you choose the SDK version
- System.Web
- System.Web.DomainServices
- System.Web.Ria
- DotNetNuke – create a dependencies folder and reference it from there.
- You should be able to build the class library now
- In the DNNRIA.Web add a reference to the AuthenticationServices project and delete the files under the Services folder.
- Now build your solution.
So by now we have a a place to put our custom Authentication code and a Silverlight app to call it with. What we need to do now is get all of this into our DNN app. To do this use an after build operation to copy the relevant files over to the target web site. To do this we will edit the proj files for each of the projects as follows:
- Right click the AuthenticationServices project and select Unload Project.
- Then right click it again and select Edit, this will show you the MSBuild file for your project.
- Now scroll down until you can see the
<Target Name="AfterBuild" DependsOnTargets="DeployModule">
Target>
<PropertyGroup>
<DNNDirectory>Physical path to the root of your portalDNNDirectory>
PropertyGroup>
<Target Name="DeployModule">
<CreateItem Include="$(MSBuildProjectDirectory)\$(OutputPath)\*.dll">
<Output TaskParameter="Include" ItemName="ModuleAssemblies" />
CreateItem>
<CreateItem Include="$(MSBuildProjectDirectory)\$(OutputPath)\*.pdb">
<Output TaskParameter="Include" ItemName="ModuleDebug" />
CreateItem>
<Copy SourceFiles="@(ModuleAssemblies);@(ModuleDebug)" DestinationFolder="$(DNNDirectory)\bin" />
Target>
- Now do the same thing for the DNNRIA Silverlight app and paste the following in
<Target Name="AfterBuild" DependsOnTargets="DeployModule" Condition=" '$(IsDesktopBuild)'!='false' ">
Target>
<PropertyGroup>
<DNNDirectory>Physical path to the portal rootlDNNDirectory>
PropertyGroup>
<Target Name="DeployModule">
<CreateItem Include="$(MSBuildProjectDirectory)\$(OutputPath)\*.xap">
<Output TaskParameter="Include" ItemName="ModuleXap" />
CreateItem>
<CreateItem Include="$(MSBuildProjectDirectory)\$(OutputPath)\*.dll">
<Output TaskParameter="Include" ItemName="ModuleAssemblies" />
CreateItem>
<CreateItem Include="$(MSBuildProjectDirectory)\$(OutputPath)\*.pdb">
<Output TaskParameter="Include" ItemName="ModuleDebug" />
CreateItem>
<Copy SourceFiles="@(ModuleAssemblies);@(ModuleDebug);@(ModuleXap)" DestinationFolder="$(DNNDirectory)\ClientBin" />
Target>
- The last project we need to do this for is the DNN Module so unload the SilverlightShell project and paste in the following
<Target Name="AfterBuild" DependsOnTargets="DeployModule">
Target>
<PropertyGroup>
<ModuleFolder>SilverlightShellModuleFolder>
<DNNDirectory>Physical path to the root of your portalDNNDirectory>
PropertyGroup>
<Target Name="DeployModule">
<CreateItem Include="$(MSBuildProjectDirectory)\$(OutputPath)\*.dll">
<Output TaskParameter="Include" ItemName="ModuleAssemblies" />
CreateItem>
<CreateItem Include="$(MSBuildProjectDirectory)\$(OutputPath)\*.pdb">
<Output TaskParameter="Include" ItemName="ModuleDebug" />
CreateItem>
<Copy SourceFiles="@(Content)" DestinationFiles="@(Content -> '$(DNNDirectory)\DesktopModules\$(ModuleFolder)\%(Identity)')" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(ModuleAssemblies);@(ModuleDebug)" DestinationFolder="$(DNNDirectory)\bin" />
Target>
- Change the web.config Build Action to none because we dont need this to be deployed to our portal.
- Reload all your projects and then do a build.
- In the LoginWindow.xaml.cs file change the DNNRIA.Web using statement to AuthenticationServices.
- Rebuild
Ok now you should have in the folder structure of your portal, the following:
- AuthenticationServices.dll & AuthenticationServices.pdb in the bin folder.
- SilverlightShell.dll & SilverlightShell.pdb in the bin folder
- DNNRIA.xap, DNNRIA.dll & DNNRIA.pdb in the ClientBin folder
the dll and pdb file are copied here so we can use Visual Studio to attach to the Silverlight process for debugging purposes
- lastly there should be a folder under DesktopModules called SilverlightShell with the Shell.ascx file.
Register the DNN module as per normal now in your portal and add it to a page. Nothing happens yet because we havent written any code!!
Lets add the Silverlight control to the ascx file
<div id="silverlightControlHost" style="position:relative; width: 100%; height: 400px; vertical-align:top; z-index:50;">
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="../../../../ClientBin/DNNRIA.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
a>
object>
<iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px">iframe>
div>
Build the solution again and refresh your page on the portal and you will see the standard Silverlight Business App.
Note: Make sure you set the browser to Always Refresh from Server with the Developer Tools
Whew! We are finally setup to have a look at the RIA Authentication stuff.
Look in the AuthenticationService.cs file down the bottom and you will see a class for User. Modify it as below
public class User : UserBase
{
public int AffiliateID { get; set; }
public string DisplayName { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public bool IsDeleted { get; set; }
}
This will be the object that we will return when the user logs in.
Next set a private variable and over ride the GetAuthenticatedUser method
private User _user;
protected override User GetAuthenticatedUser(System.Security.Principal.IPrincipal principal)
{
return _user;
}
Now for some DotNetNuke magic. Over ride the ValidateUser method as follows
protected override bool ValidateUser(string userName, string password)
{
var portalId = 0;
var loginStatus = UserLoginStatus.LOGIN_FAILURE;
var userInfo = UserController.ValidateUser(portalId, userName, password, "DNN", "", "My Web Portal", "127.0.0.1", ref loginStatus);
_user = new User()
{
AffiliateID = userInfo.AffiliateID,
DisplayName = userInfo.DisplayName,
Email = userInfo.Email,
FirstName = userInfo.FirstName,
IsDeleted = userInfo.IsDeleted,
Name = userInfo.DisplayName
};
switch (loginStatus)
{
case UserLoginStatus.LOGIN_FAILURE:
return false;
break;
default:
return true;
break;
}
}
Make sure you change the portal name to the name of your portal. I’ll use isolated storage later to store this but for now its hard coded, same for IP Address.
This code is now calling the DNN UserController class to validate the user and returning that user, then it updates the fields and returns true. The GetAuthenticatedUser method then returns our custom user object back to the Silverlight Application as the RiaContext.Current.User!
A nice extra to this is it works just as well out of the browser!!
Bit of a long post but you get the idea. You can download the code from here.