Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 13: The New Class Library Project
Well… this has been one of the longer blog series I have done, but there is so much meat here! Maybe someone will write a book or two? Anyway, in this post, I wanted to spend a little time looking at the project structure we have been working with and see if there is a way to improve it a bit with more clear separation of concerns.
For those of you just joining it, this is yet more updates to my Mix09 talk “building business applications with Silverlight 3”. You can watch the original video of the full session
The demo requires (all 100% free and always free):
- VS2008 SP1 (Which includes Sql Express 2008)
- Silverlight 3 RTM
- .NET RIA Services July '09 Preview
Also, download the full demo files…
The core project structure we have been using so far is a single solution with two projects in it:
MyApp – The Silverlight App
MyApp.Web – the web application
The MyApp.Web project actually has two very distinct concerns.. the first is handing the AppLogic for the entire app, the 2nd is the web and services interfaces (specifically the default.aspx down level rendering, sitemap.aspx and SuperEmployeeService.svc). Two concerns in the same project bother me at some level as I tend to like a cleaner separation for maintenance and better cross team work. Luckily, new in the July update to RIA Services is a new RIA Services Class Library project. We will look at refactoring the MyApp.Web project to pull out the appLogic concerns into a separate project.
Right click on the solution and select “Add New Project….”
This creates a pair of class library projects.. one for the client and one for the server.
First you will need to add a reference from the MyApp.Web project to the SuperEmployeeRIAServicesLibrary.Web.. We are going to want to access the DomainService defined in this library from several places in the WebApp.
Now, simply add an Entity Framework model and SuperEmployeeDomainService to the SuperEmployeeRIAServicesLibrary.Web project exactly as we way back in step 2. Once you have the SuperEmployeeDomainService class created, you can copy over the implementations we did thus far… remember to grab the cool metadata validation attributes as well.
Then you can delete the Domain services classes from the MyApp.Web project. This gives you a very clean set of concerns..
Notice that SuperEmployeesRIAServicesLibrary.Web contains the datamodel and Domain classes and the MyApp.Web project has the asp.net pages and the service. All that access the DomainModel from the class library project.
Notice if you are using the “Business Application Template” as I am in this walk through, you will notice a Services folder that includes some DomainServices for dealing with user management. In some ways, I think of this as an application wide concern, so it might make sense to leave these in the web project, but if you’d like to move them, no problem. Just add the following steps:
1. Move the entire directly to the SuperEmployeeRIAServicesLibrary.Web project. It is likely a bit cleaner to update the namespaces in these types, if you do so, you will need to update the namespaces on the client as well.
2. Break the “RIA Services Link” from the Silverlight client to the MyApp.Web project in the MyApp properties page.
3. Add a project reference from MyApp to SuperEmployeesRIAServicesLibrary
4. Add a simple RIAContext class to your application
public sealed partial class RiaContext : System.Windows.Ria.RiaContextBase { partial void OnCreated(); public RiaContext() { this.OnCreated(); } public new static RiaContext Current { get { return ((RiaContext)(System.Windows.Ria.RiaContextBase.Current)); } } public new User User { get { return ((User)(base.User)); } } }
5. Explicitly wire up the AuthDomainContext in App.xaml.cs with lines 5 and 6.
1: private void Application_Startup(object sender, StartupEventArgs e) 2: { 3: this.Resources.Add("RiaContext", RiaContext.Current); 4: 5: var auth = RiaContext.Current.Authentication as FormsAuthentication; 6: auth.DomainContext = new AuthenticationContext(); 7: 8: this.RootVisual = new MainPage(); 9: }
Again, the above steps are optional – only if you want to factor out the DomainService completely from your web application.
Now we just need to update some namespace references across the silverlight client and the web because our DomainService class is in a new namespace. And presto! The apps works great, but now the project is better factored for long term maintenance.
Notice that every aspect of the app keeps working….
The Silverlight client..
The ASP.NET view (for SEO)..
The Service…
And of course the WinForms client for that service..
Comments
Anonymous
July 28, 2009
So Brad, let my clarify this: a) Your new RIAServiceLibrary.Web is referencing the old MyApp.Web? b) And your SL Client is Referencing the new RIAServiceLibrary (client dll)? c) And what happens after you break the link “RIA Services Link” from the Silverlight client to the MyApp.Web project? Do you leave it broken? d) I think it would be great if the "Business Template" would do this automatically! Brad, this whole series have been very helpful, but this was something I needed now :-) The RIA docs is very brief on this sunject. Thanks! ..BenAnonymous
July 28, 2009
This is a great post for Silver light application. I am looking forward for your upcoming posts. Good Work SinghAnonymous
July 28, 2009
Brad, I have encountered the following errors:
- When using EF DAL, if I add an association I get a compile error that the association cannot be found when generating the client side code.
- When using LTS with a DomainService I get compile errors that all the entities are defined multiple times when generating client side code. Also, an example of using the DomainContext.Load method with callback methode would be usefull. Thanks for this great series.
Anonymous
July 29, 2009
Brad, never mind on my (a) question. So, basically the SL Client (MyApp) reference the new RIA Service client and the SL web section (MyApp.Web) references the new RIA Service Web. But I'm still puzzled about the Link breakage. Could you also explain the addition of RIAContext class. Thanks! ..BenAnonymous
July 29, 2009
Part 13? Where's the first part?Anonymous
July 29, 2009
Chris -- wow, the series has gotten long if you can't even see the first one ;-) Try this: http://blogs.msdn.com/brada/archive/tags/RIAServices/default.aspxAnonymous
July 29, 2009
OK, so I've followed this through and done exactly as you've said, but as soon as I load the application my datagrid is empty and the Activity doesn't even show. Any ideas as to why this might happen?Anonymous
August 03, 2009
Great, I suppose this will make integrating with Prism much easier!Anonymous
August 22, 2009
Hopefully I can save someone else some pain :) If you are following along with this series, the above will work just fine. HOWEVER if you never built this app with a combined library, but rather created it from scratch with a split RIA services library then remember this... YOU MUST COPY THE CONNECTION STRING from the Services library projects App.Config to the .Web projects Web.Config. I feel like such a newb :) KenAnonymous
August 22, 2009
Soulhuntre - thanks for the tip! This is a very important point... sorry I did not make that clear in the flow.Anonymous
October 17, 2009
Hi. "YOU MUST COPY THE CONNECTION STRING from the Services library projects App.Config to the .Web projects Web.Config" . - it's there a way to provide this connectionString dynamically. The main idea is: - I want to dynamically deploy service (RIAServiceLibrary.Web modules) into my running application. The only problems is this connection string - I don't want to manual add them in web.config file. Thanks! Radu