
At Info Support we work with a multi-solution philosophy . The reason for doing so lies in the fact that Visual Studio isn’t the brightest one on the block when it comes to working with solutions. When you create a solution with 20 projects or more performance will reduce to a rather famous “Coffee moment”. Sometimes I wonder why didn’t put a health warning on screen when you load solutions that big.
So to prevent any problems with developers drinking too much coffee, we work with the following setup. For each service we create there will be a Visual Studio Solution in Team Foundation Server (TFS). This works great for the current state of technology, because the services we create share nothing more than a bunch of XML schemas and service contracts in the form of WSDL files. Sometimes we have infrastructural components that need to be shared between services, but that’s it.
Change is coming, because Microsoft has created a new piece of technology called WCF RIA services. I wrote about it in SDN magazine earlier this year and explained how you can use this technology to eliminate a lot of the work needed to get a working service and a agent to communicate with that service.
In this article I will show you how RIA services also works in an environment where you have a solution for every web service you create.
The scenario used in this article
For this article I will be using OneWayAir, the fictional airline company that we (Edwin, Sander and I) introduced back in December in .NET magazine. It’s sort of the rather cheesy sample that makes it easier for me to talk about certain aspects of the technology without having to think to hard about a model to use.
Instead of building a check-in process however (We already got that, don’t we?) I will be taking a closer look at the customer management aspects of OneWayAir. The company isn’t really big and the economy isn’t really helping either, so the model is still pretty basic.
This model will be exposed using a WCF RIA service. A Silverlight client will be linking this service at the end of the article.
To make the scenario a bit more interesting there is also a FlightCatalog involved in this sample. The model for this service is shown below.
This model is also exposed using RIA services, but in a different solution.
Creating the RIA services
Both the FlightCatalog and the CustomerManagement service will be build using so-called RIA services libraries. This is a special type of RIA services project that works pretty much like a Silverlight application that is RIA services enabled.
However instead of a Silverlight application a RIA services library is a Silverlight class library. You can create multiple RIA services libraries and add references to them from your Silverlight frontend. The Silverlight frontend doesn’t need to be in the same solution.
When you create a new RIA services library you will get a new solution folder with two projects in that folder. One project is named <ProjectName>.csproj and the other will be named <ProjectName>.Web.csproj. When you use VB.NET it will be <ProjectName>.vbproj and <ProjectName>.Web.vbproj.
Every domain service you create inside your <ProjectName>.Web.csproj will be available as a proxy inside the <ProjectName>.csproj. This works in the same way as it would when creating domain services inside a web project of a RIA services enabled Silverlight application.
The CustomerManagement service solution looks like this after I have created the required entity framework model for it and added a domain service class to it.
What’s interesting here is that nothing is visible in the CustomerManagement project. Don’t worry, there’s plenty there. If you click the Show all files button at the top of the solution explorer, Visual Studio will show you what’s hidden from you normally.
The RIA link that exists between the web project and the class library generated a new Generated_Code folder. When you build the solution the CustomerManagement project will contain everything that is need to communicate with the RIA service.
The FlightCatalog is created in a separate solution, but follows the same procedure as was used to create the CustomerManagement service.
Hosting the RIA services
After you have create a couple of RIA services you will need to host them inside a web project to make use of them. Not everything is hosted, only the <ProjectName>.Web projects will need to be hosted.
There are several scenarios that you can follow for hosting the RIA services created in the previous section. As an example I will be demonstrating how you can host the CustomerManagement service. For this you will need to add an empty web project to the CustomerManagement solution and call it CustomerManagement.Host.
After you have created the new web application you will need to add a reference to the System.ServiceModel.DomainServices.Hosting assembly. Additionally a reference to the CustomerManagement.Web project is required to get the actual domain service.
Hosting RIA services is done using a specialized HTTP module which will take care of all the greasy, technical bits that are involved in the process. Add the following XML fragment to your web.config file to get the hosting up and running in IIS 7.
1: <system.webServer>
2: <modules runAllManagedModulesForAllRequests="true">
3: <add name="DomainServiceModule" type="System.ServiceModel.DomainServices.Hosting.DomainServiceHttpModule, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
4: </modules>
5: </system.webServer>
If you’re testing this on a web development server you will need to add the HTTP module to the system.web section of the configuration like so.
1: <system.web>
2: <compilation debug="true" targetFramework="4.0" />
3: <httpModules>
4: <add name="DomainServiceModule" type="System.ServiceModel.DomainServices.Hosting.DomainServiceHttpModule, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
5: </httpModules>
6: </system.web>
You will also need ASP.NET compatibility for the services to work. This is required since WCF RIA services allows developers to use ASP.NET membership in combination with the Authentication Domain Service to setup authentication scenarios. Add the following fragment to enable ASP.NET compatibility for WCF.
1: <system.serviceModel>
2: <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
3: </system.serviceModel>
After setting up the configuration you can request the domain service by entering http://localhost/CustomerManagement.Host/CustomerManagement-Web-CustomerRelations.svc in your favorite webbrowser to access the service.
Note: Make sure you copy other configuration needed by the domain service as well. Otherwise you will be looking at a rather dead service.
Creating the client
The final step needed to complete the solution is to create the client. For this step I have deployed both RIA services needed by the client to my local IIS 7 installation. The services can will be available to the client on the following addresses:
- http://localhost/CustomerManagement/CustomerManagement-Web-CustomerRelations.svc
- http://localhost/FlightCatalog/FlightCatalog-Web-FlightCatalog.svc
You will need these addresses, since the services will not be hosted inside the host project of the Silverlight client. If you do host them inside the host project, you will notice that the client will work without specifying the endpoint address of the domain services explicitly.
To get the client up and running you will need to create a new solution containing a Silverlight application. Make sure you activate the “Enable RIA services” checkbox before clicking the OK button.
After you have created the Silverlight application you can add references to the FlightCatalog project and the CustomerManagement project. This will make the CustomerRelations domain context and the FlightCatalog domain context available in the Silverlight client.
Using the domain context types is a little different from what you would do when creating a basic Silverlight RIA services enabled application. Instead of using the default constructor you will need to supply the domain context with an explicit endpoint address of the domain service. An example of this is shown below.
1: CustomerRelations customerRelationsDomainContext = new CustomerRelations(new Uri(
2: "http://localhost/CustomerManagement/CustomerManagement-Web-CustomerRelations.svc",UriKind.Absolute));
3:
4: //TODO: Interesting stuff with the customer relations domain context
Note: Some people will start jump by now. Yes, I know, you want a service locator to lookup the correct address for you. You can either implement a service locator yourself, or use the Endeavour service locator to lookup the address for you.
Conclusion
Not only does RIA services make it cheaper to build a service oriented application, but it also works in a more complex environment where you have separate solutions for each of the services.
If you have any questions, don’t hesitate to leave a comment or drop me an e-mail. You can also contact me on twitter using the handle @wmeints.
4 comments
Excellent Post.
kibria
Awsome post. This clarified some faults out i made before. Most valuable post in this questions.
robert
Very nice post! Going to use it in our blog:
http://www.prismforsilverlight.com/
Micclo
This is a very helpful post, i hope this really helps me to complete my project.
Grignolino