Sandrino Di Mattia

Content-type: Microsoft

Social

Follow me on Twitter! LinkedIn! RSS! SilverlightShow Contributor

Recent posts

Tags

Categories

Archive

Blogroll

Things you can do with WCF RIA Services and a regular .svc file

Introduction

Let's say you create a new DomainService called TasksDomainService and host this service in an ASP.NET website.

The HttpModule DomainServiceModule will make sure you can access this service as if a physical .svc file was present on the webserver. It will take the namespace and the class name (in my case Sandworks.Silverlight.nTier.Services and TasksDomainService), combine them and append ".svc".

In my case I could access the service via: http://localhost:9346/Sandworks-Silverlight-nTier-Services-TasksDomainService.svc

Custom .svc file

But what to do when you want a cleaner url (http://localhost/Tasks.svc for example)?
This is possible, just follow these steps:

  1. In the web project containing your service, create a new file: Tasks.svc
  2. Open this file
  3. Enter the following:
     
    <%@ ServiceHost Service="Sandworks.Silverlight.nTier.Services.TasksDomainService" Factory="System.ServiceModel.DomainServices.Hosting.DomainServiceHostFactory, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>

The markup you see in step 3 tells the server what service to load (Service, this needs to include the namespace) and how to load it (Factory, the DomainServiceHostFactory will correctly host your DomainService class).
If you don't use the fully qualified assembly name this will result in the following error (thanks Luc!):

Parser Error Message: The CLR Type 'System.ServiceModel.DomainServices.Hosting.DomainServiceHostFactory' could not be loaded during service compilation. Verify that this type is either defined in a source file located in the application's \\App_Code directory, contained in a compiled assembly located in the application's \\bin directory, or present in an assembly installed in the Global Assembly Cache. Note that the type name is case-sensitive and that the directories such as \\App_Code and \\bin must be located in the application's root directory and cannot be nested in subdirectories.

Do read Rick's post if you also want to remove the .svc extension to go RESTfull: http://www.west-wind.com/weblog/posts/570695.aspx

Clean project structure

When creating a new solution I love to organize a clean project structure.
But when you're using Silverlight with WCF RIA Services this can be challenging though.

This is what we'll try to accomplish:

A little word on the projects:

  • Sandworks.Silverlight.nTier.Client: The Silverlight application.
  • Sandworks.Silverlight.nTier.Client.Model: A regular Silverlight Class Library with a WCF RIA Services link.
  • Sandworks.Silverlight.nTier.Services: A WCF Service Library.
  • Sandworks.Silverlight.nTier.Services.Host: A WCF Service Application.
  • Sandworks.Silverlight.nTier.Web: This hosts the Silverlight application.

Note, we won't be using a WCF RIA Services Class Library because the namespaces and assembly names are not so clean (.Web is appended to your server side class library):

 

Here are the steps you need to follow to create your own clean project structure:

  1. Open Visual Studio, select File, New Project
  2. Select Silverlight Application
  3. Enter the following:
     
    Name: My.Application.Client
    Solution: My.Application
     
  4. Visual Studio will ask you to host the application in a new ASP.NET Web Site.
    Make sure you change My.Application.Client.Web to My.Application.Web and press OK (do not check Enable WCF RIA Services).
  5. Add a new Silverlight Class Library called My.Application.Client.Model and remove Class1.cs
  6. In your project My.Application.Client add a project reference to My.Application.Client.Model
  7. Add a new WCF Service Library called My.Application.Services and remove all files.
  8. Add a new WCF Service Application called My.Application.Services.Host and remove the fake Service1.
  9. In your project My.Application.Services.Host add the following references:
     
    My.Application.Services
    (project reference)
    System.ComponentModel.DataAnnotations
    System.ServiceModel.DomainServices.Hosting

    System.ServiceModel.DomainServices.Server
     
  10. Rebuild your solution.
  11. In your project My.Application.Client.Model go to Properties and add a WCF RIA Services link to My.Application.Services
    This will make sure the code generation is in place.
  12. Create 3 solution folders: Client, Services, Web and reorganize your projects.

And you're done:

The only things left to do are:

  1. Create a new Domain Service Class in My.Application.Services
  2. Create a .svc file in My.Application.Services.Host (referencing that class, see start of this post)
  3. Rebuild your solution (code generation will take place in My.Application.Client.Model)
  4. Use your service context in My.Application.Client
  5. Configure the web applications on a fixed port (easier for when you're debugging).

Since your service isn't in the same project/Virtual Directory as the Web project you'll have to explicitly declare the url:

TasksDomainContext ctx = new TasksDomainContext(new Uri("http://localhost:10001/Tasks.svc"));

In a following article I'll explain how to configure these urls.
But for now here are the downloads:

Enjoy...

Comments (6) -

Luc Van Keer said:

Step 4 (copying the System.ServiceModel.DomainServices.Hosting
System.ServiceModel.DomainServices.Server assemblies locally) is not needed if you specify the fully qualified assembly name (strong name) for the service factory in the svc file.

e.g.
<%@ ServiceHost Service="Sandworks.Silverlight.nTier.Services.TasksDomainService" Factory="System.ServiceModel.DomainServices.Hosting.DomainServiceHostFactory,System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>

Copying  assemblies that are installed in the GAC to local application directories is not a good idea and can get you into trouble.

Cheers Smile

# September 02 2010, 00:46

Sandrino said:

Luc you are completely right about the fully qualified assembly name.
I've adapted the post and the source code.

Thanks for your comment!

# September 02 2010, 01:10

Tamil Movie said:

This is such a great resource that you are providing and you give it away for free. I love seeing websites that understand the value of providing a quality resource for free. It is the old what goes around comes around routine. Did you acquired lots of links and I see lots of trackbacks??

# October 09 2010, 20:43

John said:

Can the Entity Framework be implemented into this setup?

# December 29 2010, 18:33

Sandrino Di Mattia said:

Yes John, your ServiceContext would be linked to an Entity Framework ObjectContext.

# December 30 2010, 10:29

Justin said:

I implemented this architecture into our current project and everything was working within Visual Studio, but we ran into a snag when we tried to use MSBuild.  MSBuild ignores the solution's project dependency build order, so the build fails because it tries to build the Silverlight projects before the services (Services.csproj' project must be built before client proxy classes can be generated).  Has anyone found a workaround for this?

# January 18 2011, 16:28

Pingbacks and trackbacks (7)+

Add comment




  Country flag
biuquote
Loading