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
    {
        [Key]
        public int OrderID { get; set; }
        public string Title { get; set; }

        [Include]
        [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.


    [EnableClientAccess()]
    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!

Advertisements

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 https://refactorthis.wordpress.com/2010/11/23/deploying-silverlight-wcf-ria-services-on-iis-6/

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 asp.net 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 show a message box or dialog in MVVM Silverlight?

The key to successfully separating the concerns of your application is all in the abstraction.

Of course we do not want to call MessageBox.Show() from within our ViewModel as this will not allow us to automatically test it. We will need to abstract the call to MessageBox.Show() so that you can swap it out for testing. A simple way to do this is to use a service implementing an interface that we can swap out depending on whether we are testing or running the application.


public interface IMsgBoxService
{
    ShowNotification(string message);
    bool AskForConfirmation(string message);
    //... etc
}

public class MsgBoxService : IMsgBoxService
{
    public void ShowNotification(string message)
    {
        MessageBox.Show(message, "Notification", MessageBoxButton.OK)
    }

    public bool AskForConfirmation(string message)
    {
            MessageBoxResult result = MessageBox.Show(message, "Are you sure?", MessageBoxButton.OKCancel);
            return result.HasFlag(MessageBoxResult.OK);
    }
}

Now that we have implemented our message box service we just need to get an instance of it and call the appropriate method in our ViewModel


private IMsgBoxService messageService;
public TestViewModel(IMsgBoxService msgboxService)
{
   this.messageService = msgboxService;
}

public void SomeMethod()
{
    messageService.ShowNotification("Hey!");
}

There it is, a few lines of code and you have a message box you can safely use throughout your application in a MVVM way that will allow for testability and seperation of concerns.

Lots more MVVM tips to come so subscribe if you would like to stay updated. Thanks!

MVVM Tips: ViewModel INotifyPropertyChanged compile time errors with Visual Studio Refactoring

Ok so I’m not too much of a fan of strings used to represent variable/property/method names. Say, INotifyPropertyChanged, no Visual Studio Refactor support for renaming and you could accidentally type the wrong string, resulting in no compile error as shown below.

    private string name;
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            RaisePropertyChanged("Names");
        }
    }

I came across a great little helper function created by the Microsoft Patterns and Practices guys to fix this problem. In your ViewModel base class, try adding this:


        protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpresssion)
        {
            var propertyName = ExtractPropertyName(propertyExpresssion);
            this.RaisePropertyChanged(propertyName);
        }

        private string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
        {
            if (propertyExpression == null)
            {
                throw new ArgumentNullException("propertyExpression");
            }

            var memberExpression = propertyExpression.Body as MemberExpression;
            if (memberExpression == null)
            {
                throw new ArgumentException("The expression is not a member access expression.", "propertyExpression");
            }

            var property = memberExpression.Member as PropertyInfo;
            if (property == null)
            {
                throw new ArgumentException("The member access expression does not access a property.", "propertyExpression");
            }

            if (!property.DeclaringType.IsAssignableFrom(this.GetType()))
            {
                throw new ArgumentException("The referenced property belongs to a different type.", "propertyExpression");
            }

            var getMethod = property.GetGetMethod(true);
            if (getMethod == null)
            {
                // this shouldn't happen - the expression would reject the property before reaching this far
                throw new ArgumentException("The referenced property does not have a get method.", "propertyExpression");
            }

            if (getMethod.IsStatic)
            {
                throw new ArgumentException("The referenced property is a static property.", "propertyExpression");
            }

            return memberExpression.Member.Name;
        }

Now you can do this:

    private string name;
    public string Name
    {
        get  {  return name; }
        set
        {
            name = value;
            RaisePropertyChanged(() => this.Name);
        }
    }

and get compile time error handling of INotifyPropertyChanged

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 http://forums.silverlight.net/forums/t/176423.aspx.
Quick workaround was to replace the call to Close() with DialogResult = true which will then close the window without problem.