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.