Silverlight WCF RIA Services DTO for light weight entities + filter relational child entity collections

WCF RIA servies has great support for Linq and Entity Framework. But if you have a large domain model and would like to send a slightly different view of the entities (for example merge some normalised entities into one conceptual entity, or only send a subset of fields, or only send a selection of the children in a parent-child collection) then DTOs may be what you are after.

DTO stands for Data Transfer Object and is simply a view of the entity that is what you really want to send to the silverlight client, not what the database is storing or the rest of your application is using. The best bit about these is RIA services will automagically add support for INotifyPropertyChanged, validation and change tracking!

You can create these DTOs just as any other class as they are POCOs (Plan old CLR Objects) and we will have full control over what is sent to the client and Data Annotations for validation or even custom methods for the entity.

Create a class to represent your entity using public properties as the attributes. Mark the key of the entity with the DataAnnotations.Key attribute as shown below. Associations can also be mapped as shown below.

using System.ComponentModel.DataAnnotations;
using System.ServiceModel.DomainServices.Server;

    public class OrderDTO
        public int OrderID { get; set; }
        public string Title { get; set; }

        [Association("Order_Items", "OrderID", "ItemID", IsForeignKey=false)]
        public IEnumerable<ItemDTO> Items { get; set; }

To serve these to silverlight simple create a DomainContext (not a LinqToEntitiesDomainService) and create a method which will act as the GET method.
Another great plus is you can easily filter the child collections that are to be returned to silverlight.

    public class OrdersDomainService : DomainService
          public IEnumerable<OrderDTO> GetOrdersAndItems()
               return context.Orders.Select(p => 
               new OrderDTO
                      //TODO map the order details
                      Items = p.Items
                      .Where(m => m.Cost > 100.0) // easily filter nested collection
                      .Select(m =>
                            new ItemDTO
                                // TODO map the item details

         // You may need this for ria to project to silverlight what a ItemDTO actually is.
         public IEnumerable<ItemDTO> GetItems()
               return null;

Now on the client side we can use these entities just as if the LinqToEntitiesDomainService projected them from the Entity Framework.

I hear more support is coming to RIA for these POCO entities so stay tuned!

Silverlight: Deploying Silverlight on IIS 6 (Mime Types)

Deploying Silverlight is relatively easy, there are a few things which can be annoyances especially when using ria services as noted in my post

To allow IIS to serve Silverlight content you will want to create a virtual directory containing your silverlight hosting web application. Ensure that your silverlight xap file is in the ClientBin. If it is not
Create your virtual directory and create a .NET application for it if it already doesn’t show up in IIS as an application.

Once at this point (the normal website deployment) we need to register the silverlight mime types. Right click on the virtual directory and go into the properties. Next head over to the ‘HTTP Headers’ tab and click on the ‘Mime Types..’ button. Here you will need to add 3 types to be sure.

.xaml application/xaml+xml
.xap application/x-silverlight-app
.xbap application/x-ms-xbap

MVVM Tips: How to close the current window / dialog?

To keep your ViewModel separated from the View we would like to make sure the ViewModel knows as little about the UI as possible, this includes no hard references. So how do we close the window?

I like to create a abstract ViewModel class specifically for this purpose which extends from my ViewModel base class and adds an event called RequestClose. Lets call it CloseableViewModel.

public abstract class CloseableViewModel : ViewModel
    public event EventHandler RequestClose;

    protected OnRequestClose()
        if (RequestClose != null)
            RequestClose(this, EventArgs.Empty);

Now just make sure your view model extends the CloseableViewModel. When you are linking your ViewModel to your view add a listener to the event

public partial class DialogView : ChildWindow
    public DialogView(DialogViewModel model)
        this.DataContext = model;
        model.RequestClose += delegate (object sender, EventArgs args) { this.Close(); }

When you want to close the window from your ViewModel call OnRequestClose();

Easy as that, and your ViewModel doesn’t need to know about your View 🙂

Silverlight ChildWindow Close() leaves background disabled

Found an issue today where the background was left disabled after calling Close() on a Silverlight ChildWindow (Reproduced on SL4 intermittently after many open/closes). A thread following the issue can be found here
Quick workaround was to replace the call to Close() with DialogResult = true which will then close the window without problem.

Deploying Silverlight WCF RIA Services on IIS 6

OK so you’ve just created a great Silverlight application, it works like a charm and it has come time to finally deploy. That should be the easy part.. think again!

Tim Heuer has a great post on his blog about this If you search Google you will find tons of people with RIA deployment issues, however if you were like me you have to really sift through it to find any information that relates to your situation. Before reading the following make sure you have read Tim’s post and installed the RiaServices.msi with the server flag as noted. This will place the RIA DLL’s into your global assembly cache so that all applications running on the server have access to the files.

With RIA and IIS 6 you want to look for a few gotchas, once you know them they are easy. To find these you will first need to download a great piece of software called Fiddler (Google it) and whilst running fiddler, open your favourite browser and try to run your Silverlight application.

Now at this point you may get a 404 Not Found error shown in Silverlight. That doesn’t mean much as you may need fiddler to see the exact exception. Check the request for the web service in fiddler, copy the URL and load it into your browser. If you still get a 404 then most likely something is disallowing you from accessing the generated WCF service. Otherwise you should get an exception which well help you identify the source of your problem (your one of the lucky ones).

If you still cannot access the web service its time to try the web.config file. RIA services uses WCF in the back-end (The WCF services are dynamically generated) and as such you will need

     multipleSiteBindingsEnabled="true" />

in your web.config. An easy way to do this (and add the appropriate references to RIA DLL’s is to create a new DomainService in your application and then simply delete it. Visual studio will handle all of the work for you. Reload your Silverlight app and try again.

If you are sure all of this is working next check your IIS virtual directory and ensure that the mapping extension .svc is mapped to the aspnet_isapi for which .NET framework you are using. To check this go to the properties of your virtual directory and click on the “Configuration…” button on the “Virtual Directory” tab. Make sure that when you update the mapping for .svc you UNCHECK the “verify file exists” check box. This is a very important step as the WCF service is dynamically served and does not exist on the file system. You should be able to find your asp.net_isapi should be able to be found in C:\Windows\Microsoft.NET\Framework\[Version]\aspnet_isapi.dll.

If you are still having issues getting to your RIA service at this point I would check the isapi wildcard extension. This is also a very important step, I have been caught out with this one way too many times. Ensure that the wildcard extension if any points to the correct aspnet_isapi and that the “verify file exists” checkbox is again UNCHECKED.

At this point your IIS virtual directory should be serving your WCF services, your web.config should allow WCF and RIA to do its thing and your RIA dll’s are in the GAC ( try copy local if cannot find the dll’s). By now if you still have problems post them in the comments. You could try manually creating the “.svc” files which map to their RIA domain service counterparts as a temporary solution.

Hopefully by now you’ve got the problem fixed and this post may have saved you a little time. If It has or you would like to point out more tips or correct something I have said please leave a comment