Freigeben über


Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 9: POCO and Authentication Provider

I have gotten lots of good comments on my series updating my Mix09 talk “building business applications with Silverlight 3”.  Some customers have asked about the “live” version I have running on one of Scott Haneslman’s servers (thanks Scott!)

The demo requires (all 100% free and always free):

  1. VS2008 SP1 (Which includes Sql Express 2008)
  2. Silverlight 3 RTM
  3. .NET RIA Services July '09 Preview

Also, download the full demo files and, of course, check out the running application.

Scott gave me a FTP access and a web server, but I didn’t want to hassle with setting up a database (though he did offer).  So I thought I'd use the POCO support in RIA Services to just get data from plain old CLR objects.  Personally, I think far too many of our samples show only Entity Framework… So this is a good excuse to show that off. 

So, back to your application diagram, i want to use this post to focus on POCO as a data source.

image

First, my goal was to make the minimum changes.  I didn’t want to touch the client at all, nor did I want to change any of my business logic.  I just wanted to move the app from EF\SQL to a POCO data source. 

Turns out this was simple enough to do.  First I deleted the northwind.mdf file from App_Data then I deleted the EF model.  

Then I added a SuperEmployee class.. I went ahead and added the metadata directly. 

 public class SuperEmployee
 {
  
     [Key]
     [ReadOnly(true)]
     public int EmployeeID { get; set; }
  
     public DateTime LastEdit {get;set;}
  
     [Display(Name = "Name")]
     [Required(
         ErrorMessage = "Super hero's require names!!")]
     public string Name { get; set; }
  
     [Display(Name = "Gender")]
     [RegularExpression("^(?:m|M|male|Male|f|F|female|Female)$",
         ErrorMessage = "Even super heros are  M\\F or Male\\Female!")]
     public string Gender { get; set; }

Then I created SuperEmployeeList class that has all the data

 List<SuperEmployee> list = new List<SuperEmployee>()
 {       
          
         new SuperEmployee() {
         EmployeeID=1,
         Gender="Male",
         Issues=982,
         Name = "Alfred",
         Origin="Human",
         Publishers="DC",
         Sites="first appears in Batman #16"},
                 
  
         new SuperEmployee() {
         EmployeeID=2,
         Gender="Male",
         Issues=518,
         Name = "Alfred E. Neuman",
         Origin="Human",
         Publishers="Ec",
         Sites="first appears in MAD #21"},

 

Then I added a couple of simple methods to make encapsulate access.

 public IEnumerable<SuperEmployee> GetEmployees()
 {
     return list.ToArray();
 }
  
 public void Add(SuperEmployee emp)
 {
     list.Add(emp);
 }

Then some small tweaks to my DomainService implementation.  Notice here I derive directly from DomainService directly rather than using the LinqToSqlDomainService or EntityFrameworkDomainService classes.    I think this will be reasonably common..

 [EnableClientAccess()]
 public class SuperEmployeeDomainService : DomainService
 {
     SuperEmployeeList Context = new SuperEmployeeList();
     public IQueryable<SuperEmployee> GetSuperEmployees()
     {
         return Context.GetEmployees().AsQueryable();
     }
  
     public IQueryable<SuperEmployee> GetSuperEmployee(int employeeID)
     {
         return Context.GetEmployees().ToList()
             .Where(emp => emp.EmployeeID == employeeID).AsQueryable();
             
     }
  
     public void InsertSuperEmployee(SuperEmployee superEmployee)
     {
         Context.Add(superEmployee);
     }
 public override void Submit(ChangeSet changeSet)
 {
     base.Submit(changeSet); 
     //todo: Submit changes to the store.. (for example, save to a file, etc
 }

I should also override Submit to save off the changes (say to a file or some sort of backing store).. but for the demo I wanted to keep them static so no one puts in bad data into my site.

Hit F5 and everything else works.. No changes to the Silverlight client or the ASP.NET client (for SEO)..  This same flexibility allows you to move from one data access technology to another without all your clients having to be updated. 

Authentication

As you saw my earlier post, we have a very cool new template that gives you log in and create new user support. 

image

I *had* to enable that in the demo..  At least so folks could play around with it.  By default we use the aspnetdb.mdb and SQLExpress… so this needed to be updated just like the above example. 

Because we simply plug into the ASP.NET Membership system that shipped in ASP.NET 3.0 this is a pretty well explored and documented area.     But here is the brief on it. 

In web.config in the server project, under the system.web section add:

  
     <membership defaultProvider="SimpleMembershipProvider">
       <providers>
         <add name="SimpleMembershipProvider"
              type="MyApp.Web.SimpleMembershipProvider"
              minRequiredPasswordLength="2"
              minRequiredNonalphanumericCharacters="0" />
       </providers>
     </membership>

Then just implement the SimpleMembershipProvider… Here I did a demo-only model that accepts any user id and password. 

 public class SimpleMembershipProvider : MembershipProvider
    {
       public override bool ValidateUser(string username, string password)
       {
         return true;
       }
       public class MyUser : MembershipUser
       {
  
       }
       public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
       {
         status = MembershipCreateStatus.Success;
         return new MyUser();
        }

Clearly in a real application you will want to plug into your user management system.  But, again because ASP.NET’s system has been around for so long there is support out there for just about any system.  Also check out a great book on the subject Stefan Schackow's Professional ASP.NET 2.0 Security, Membership, and Role Management.

Comments

  • Anonymous
    July 22, 2009
    The comment has been removed

  • Anonymous
    July 22, 2009
    Stefan -- It is full trust right now... I am told the next update will work partial trust..  

  • Anonymous
    July 22, 2009
    Our poco/custom repository/etc would have to implement IQueryable for this to be truly useful right? Say I do data access in my custom repository...I'd have to implement IQueryable in my repository to be able to filter and query the database with whatever filters I use on the client?

  • Anonymous
    July 22, 2009
    Hi, I would like to share my article on Authentication with silverlight . http://geekswithblogs.net/thanigai/archive/2009/05/20/silverlight-3-with-ria-authentication-service.aspx It uses ASPNetDB. Thanks, Thani

  • Anonymous
    July 22, 2009
    Brad, Is a step-by-step walkthrough available for the Business Apps Example for Silverlight 3 RTM and .NET RIA Services? Excellent series of blog updates! Best regards, Rob

  • Anonymous
    July 23, 2009
    The comment has been removed

  • Anonymous
    July 23, 2009
    The comment has been removed

  • Anonymous
    July 23, 2009
    This is great feedback Stefan -- we talked about this issue today and are actively looking at a solution to make it work in semi-trust on 3.5.. stay tuned!

  • Anonymous
    July 23, 2009
    VeeMat -- this is a great scenario and one that will be more clean in the next drop... There is an Include attribute that you can use to specifiy what other entities to operate on as a unit..  

  • Anonymous
    July 23, 2009
    > Our poco/custom repository/etc would have to implement IQueryable for this to be truly useful right? >Say I do data access in my custom repository...I'd have to implement IQueryable in my repository to be able to filter and query the >database with whatever filters I use on the client? That is right, you need to implement IQuerable to get all the cool composition around sorting paging filtering, etc.. But in the WCF example, I show how you can get pretty close by using parameters to your query methods http://blogs.msdn.com/brada/archive/2009/07/17/business-apps-example-for-silverlight-3-rtm-and-net-ria-services-july-update-part-8-wcf-based-data-source.aspx ..brad

  • Anonymous
    July 24, 2009
    Brad, This is a great sample.  Thank you for releasing this. I'm trying to get your MyApp.WebAdmin site working.  Is this supposed to work out of the gate?  I get the following exception what I try to view it: The base class includes the field 'DynamicDataManager1', but its type (System.Web.DynamicData.DynamicDataManager) is not compatible with the type of control (System.Web.DynamicData.DynamicDataManager). Thank you :) Michael

  • Anonymous
    July 24, 2009
    MichaelD! - Utz - Nope, that WebAdmin project is not suppose to be there..   It is some testing i did for a future post..  Stay tuned... we will do Dynamic Data soon ;-)

  • Anonymous
    July 24, 2009
    The comment has been removed

  • Anonymous
    July 30, 2009
    The comment has been removed

  • Anonymous
    July 31, 2009
    I fixed the problem using a workaround. In order to use define a System.ComponentModel.DataAnnotations.AssociationAttribute I needed a foreign key property on Category. The Product objects, however are retrieved from a WCF service and already have the Categories loaded and Category objects do not have a property ProductId. So I created a small wrapper object that wraps Category objects just after Products are retrieved from the service and adds the ProductId to it. In Products I now have: [Association("Categories", "Id", "ProductId")] [Include] Public List<Category> Categories {     ... } This works, but the solution is far from ideal. However, in the meantime the proxy class seems to solve another issue that I had as well, namely that metadata validation of WCF proxy objects (created with Service Factory Modeling edition) did not work properly with RIA Services (only the RequiredAttribute and KeyAttribute were honoured, the rest was ignored). So, that is something good coming with something bad, it seems ;)

  • Anonymous
    July 31, 2009
    BTW, I didn't say this yet, but I really appreciate the long list of articles on RIA Services. Thank you, Brad!

  • Anonymous
    August 14, 2009
    hi there, I have a couple of things to add. In order to run Silverlight 3 with RIA Services on a shared server, there are several things that you need to check. The followings must be installed on the server:

  1. .NET3.5 Framework
  2. Full Trust mode must be enabled
  3. Install the Visual Web Developer 2008 tool
  4. Install the Visual Studio 2008 Service Pack 1
  5. Run the Silverlight 3 Toolkit
  6. Run the RIA Service Installation
  7. Silverlight can run on either IIS6 or IIS7 I am currently hosting my Silverlight 3 (+ RIA Service) with ASPHostCentral (http://www.asphostcentral.com) and so far, everything works smoothly.
  • Anonymous
    August 23, 2009
    How do you set up the POCO data source to handle an object that has an object as a property (we have a set of classes serialized from an XSD). For instance, we have a client object with a property of ClientTitle (which has two properties, one int (ID) and one string (Value).  How do i get Dynamic data to show me the string?

  • Anonymous
    October 03, 2009
    I just called GoDaddy and they confirmed that the shared hosting does not run in full trust and cannot be configured to run in full trust.   Am looking forward to that next update! Greg