At the Mix 09 conference Microsoft announced a new technology called RIA Services. This new technology simplifies the communication between the RIA Client Technologies like Ajax and Silverlight and the Server technology ASP.NET.
Everybody who has been using Silverlight 2 knows about the lack of support for specific features that we’re used to make use of in for example ASP.NET. And yes, we need to remember that Silverlight is a technology that runs inside the browser (or outside the browser when activated the specific Silverlight 3 Beta feature).
Let’s start with a very simple RIA Service and let’s call it HelloWorldDomainService. I’ve seen other articles about RIA Services but they most of the time dive deep by combining the Entity Framework right away.
First thing: what special things does a RIA Service need?
- The RIA Service needs to be derived from DomainService, or from a different class that’s derived from DomainService.
- The RIA Service needs to be decorated with an attribute called EnableClientAccessAttribute.
- The operations need to be decorated with an attribute called ServiceOperationAttribute.
A very simple HelloWorldDomainService now looks like this (this class needs to be in the ASP.NET Project, not the Silverlight project).
[EnableClientAccess]
public class HelloWorldDomainService : DomainService
{
[ServiceOperation]
public string HelloWorld(string name)
{
return string.Format("Hello {0}.", name);
}
}Second thing that’s important is the configuration is correct.
So what’s required? A configuration for a new HttpHandler specially for RIA Services in general. Just add this piece in the HttpHandlers part of the Web.config.
<add path="DataService.axd" verb="GET,POST" type="System.Web.Ria.DataServiceFactory, System.Web.Ria, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
Next thing is getting the Silverlight project bound to the ASP.NET project.
When you right click on the Silverlight project and choose properties you’ll get something similar to this.
Select the ASP.NET server project link to the ASP.NET server project that contains the RIA Services. In this example the ASP.NET server project is called MM.Sl3Experiments.Web.
Let’s build the whole solution…
… what happens? Let’s have a look at all files (also hidden files) in the Silverlight project by hitting the show all files button in the solution explorer. And you will suddenly see a folder called Generated_Code containing a file alike to <WebProjectName>.g.cs.
So there’s a lot of code generation behind the scenes? Yes it is. And that’s why I recommend people to write kind of a Service Agent so you’re not actually calling the generated code directly. But that’s something for a different post, or something you can figure out yourself. We’re now talking about RIA Services specifically.
But what gets generated?
For the sake of this article I removed a lot of code from this generated class, things that are just there but have no real purpose in this example. What we have left is this:
public sealed partial class HelloWorldDomainContext : DomainContext
{
public HelloWorldDomainContext() :
base(new HttpDomainClient(new Uri("DataService.axd/MM-Sl3Experiments-Web-HelloWorldDomainService/", System.UriKind.Relative)))
{
}
public event System.EventHandler<InvokeEventArgs> HelloWorldCompleted;
public void HelloWorld(string name)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("name", name);
base.InvokeServiceOperation("HelloWorld", typeof(string), parameters, this.OnHelloWorldCompleted, null);
}
private void OnHelloWorldCompleted(InvokeEventArgs args)
{
if ((HelloWorldCompleted != null))
{
this.HelloWorldCompleted(this, args);
}
}
}
What we have in the generated code are the following things:
- A constructor to create a HelloWorldDomainContext.
- A method that’s called HelloWorld with typed arguments.
- An event that get’s called upon completion of the HelloWorld execution.
So we can easily write this code inside our Silverlight application to call the HelloWorldDomainService that’s really running on the ASP.NET Server side.
var helloWorld = new HelloWorldDomainContext();
helloWorld.HelloWorldCompleted += new EventHandler<InvokeEventArgs>(HelloWorldHelloWorldCompleted);
helloWorld.HelloWorld("Mark Monster");Just very simple, create a new object, attach to the Completed event and call the method.
The method being called upon completion only prints the return value to the Debug window.
private void HelloWorldHelloWorldCompleted(object sender, InvokeEventArgs e)
{
Debug.WriteLine(e.ReturnValue as String);
}
Places for improvement for RIA Services…
One thing that can be made better is the fact that InvokeEventArgs doesn’t have typed property ReturnValue. It’s of type object, and you still need to cast it to the right type. A recommendation for the team behind RIA services would be to make InvokeEventArgs generic (InvokeEventArgs<T>) to make something like this possible:
/// <summary>
/// The generated class
/// </summary>
public sealed partial class HelloWorldDomainContext : DomainContext
{
public HelloWorldDomainContext() :
base(new HttpDomainClient(new Uri("DataService.axd/MM-Sl3Experiments-Web-HelloWorldDomainService/", System.UriKind.Relative)))
{
}
public event System.EventHandler<InvokeEventArgs<string>> HelloWorldCompleted;
public void HelloWorld(string name)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("name", name);
base.InvokeServiceOperation("HelloWorld", typeof(string), parameters, this.OnHelloWorldCompleted, null);
}
private void OnHelloWorldCompleted(InvokeEventArgs<string> args)
{
if ((HelloWorldCompleted != null))
{
this.HelloWorldCompleted(this, args);
}
}
}And an improved way of using. The ReturnValue is now typed.
var helloWorld = new HelloWorldDomainContext();
helloWorld.HelloWorldCompleted += new EventHandler<InvokeEventArgs<string>>(HelloWorldHelloWorldCompleted);
helloWorld.HelloWorld("Mark Monster");
private void HelloWorldHelloWorldCompleted(object sender, InvokeEventArgs<string> e)
{
Debug.WriteLine(e.ReturnValue);
}Another improvement would be to include the generated files in the project. This is because of two reasons. The first and most important reason would be Source Control. I think we want to have those generated files under Source Control as well. We now would have to add those files manually to source control, or right click on those generated items to include them in the project, so the Source Control Systems will pick them up automatically.
The second reason I want those files to be included is: ReSharper, although I know it’s not a product by Microsoft. Because the generated files are not part of the project, I won’t be able to make use of ReSharper’s intellisense and what about the ReSharper Code Analysis?
In the end I really like this ability to run code on the server side this easily. I know RIA Services is still in CTP, let’s hope for a few improvements. It’s already a good product, but it could be even better.
Ps. This article is cross posted on: Mark Monster’s blog and Silverlight Help.




Also, I'd recommend checking out the other stuff on DomainService, other than ServiceOperation. ServiceOperation is an escape mechanism to get to doing immediate WCF-style async methods. The other bits such as CRUD methods are the primary focus areas and value propositions for DomainService.
Regards