Home > English > Using ICustomTypeProvider in Silverlight 5 beta with JSON and ASP.NET MVC 3

Using ICustomTypeProvider in Silverlight 5 beta with JSON and ASP.NET MVC 3

One of the really powerful new features in Silverlight 5 is the new interface ICustomTypeProvider. This allow us to have a dynamic way to bind to objects that we don’t know the shape of until at runtime. There are three blog posts that you need to read before continuing forward. Please read this post by Alexandra Rusina. In it she provides a nice implementation for ICustomTypeProvider. The other post is by Jeremy Likness. In his post he expounds a little more on what Alexandra provided and gives us the ability to parse JSON. The last post, basically gives us an easy way to format our JSON so that we can see it in a human readable format instead of what it looks like once we pull it from the stream.

This post basically will takes us from the point where Jeremy and Alexandra left us and use ASP.NET MVC 3 to act as our service host for getting data across the wire.

Ok, let’s get started. First of all, I created a blank solution called “CustomTypeProvider”.

Next, I added a new Silverlight 5 project. When asked, I changed the host to be a ASP.NET MVC project. I gave the name of the Silverlight project, “CustomerTypeProvider.Silverlight” and the web host, “CustomTypeProvider.Web”.

I like to use Caliburn.Micro whenever I can and I opted to use the latest version of Caliburn.Micro in my Silverlight project. I used NuGet to pull down the package. It is as easy as right-clicking your References and selecting, “Add Library Package Reference”. Once the dialog appeared, I changed it to online and entered, “Caliburn.Micro” in the search and installed it once it appeared.

I basically followed the steps provided in the web page that comes up in Visual Studio once Caliburn.Micro’s package is installed. I also added the following assembly references:

  • System.Json
  • System.ComponentModel.DataAnnotations
  • System.Windows.Controls.Data

Let’s look at the code necessary for the web first:

namespace CustomerTypeProvider.Web.Controllers
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Collections;
    using System.Data.SqlClient;

    public class HomeController : Controller
        public JsonResult GetCustomers()
            var data = LoadCustomers();
            return Json(data, JsonRequestBehavior.AllowGet);
        public JsonResult GetOrders()
            var data = LoadOrders();
            return Json(data, JsonRequestBehavior.AllowGet);
        public JsonResult GetQuery(string query)
            var data = LoadQuery(query);
            return Json(data, JsonRequestBehavior.AllowGet);
        private List<Customer> LoadCustomers()
            List<Customer> result = new List<Customer>();
            result.Add(new Customer() { FirstName = "Matt", LastName = "Duffield" });
            result.Add(new Customer() { FirstName = "Dean", LastName = "Duffield" });
            return result;
        private List<Order> LoadOrders()
            List<Order> result = new List<Order>();
            result.Add(new Order() { ContactName= "Matt Duffield",
              OrderDate= DateTime.Now, OrderNumber = 100 });
            result.Add(new Order() { ContactName = "Dean Duffield",
              OrderDate = DateTime.Now, OrderNumber = 101 });
            return result;
        private ArrayList LoadQuery(string query)
            ArrayList objs = new ArrayList();

            //SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;User Id=myUsername;Password=myPassword;");
            SqlConnection conn = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security = SSPI;");
            //SqlCommand cmd = new SqlCommand("SELECT TOP 10 [CustomerID],[CompanyName],[Address],[City],[Region],[PostalCode],[Country]  FROM [Customers]", conn);
            SqlCommand cmd = new SqlCommand(query, conn);
            SqlDataReader r = cmd.ExecuteReader();
            while (r.Read())
                    CustomerID = (r["CustomerID"] is DBNull ? "" : r["CustomerID"]),
                    CompanyName = (r["CompanyName"] is DBNull ? "" : r["CompanyName"]),
                    Address = (r["Address"] is DBNull ? "" : r["Address"]),
                    City = (r["City"] is DBNull ? "" : r["City"]),
                    Region = (r["Region"] is DBNull ? "" : r["Region"]),
                    PostalCode = (r["PostalCode"] is DBNull ? "" : r["PostalCode"]),
                    Country = (r["Country"] is DBNull ? "" : r["Country"])

            return objs;

        public class Customer
            public string FirstName { get; set; }
            public string LastName { get; set; }
        public class Order
            public int OrderNumber { get; set; }
            public DateTime OrderDate { get; set; }
            public string ContactName { get; set; }

Okay, so there is a little going on but we will start from the top. We basically have three public methods at the top:

  • GetCustomers()
  • GetOrders()
  • GetQuery(string query)

The first two call helper methods that basically create a generic List<> with some sample data and pass it back to the calling method.  The third is a little more dynamic in that it uses ADO.NET to create a SqlConnection, SqlCommand, and finally a SqlDataReader.  It executes the query passed in and then loops through the data reader to shapes a new object that gets added to an ArrayList.  The ArrayList then gets passed back to the calling method. One thing to note about the data reader loop is that we are checking for DBNull and giving it a default value. This is necessary on the client side so that we can infer the type information.

In each of the corresponding methods above, a new Json object is created passing in the data that was returned from the helper methods as well as a second parameter is set to allow the Get verb.

Now let’s move on to the client side.  In the client side, I have to folders that are of interest:

  • Formatting
  • Framework

In the Formatting folder is the logic necessary to format the JSON stream that comes from the web make it human readable.

In the Framework folder is the logic that I took from Alexandra Rusina’s and from Jeremy Likness’ blog posts.  I won’t go into detail in these classes since there are separate posts by each of them dedicated to the classes.  What I will show you is the ShellView and ShellViewModel to see how we get this data and render on screen.

Let’s take a look at the ShellView:

<UserControl x:Class="CustomerTypeProvider.Silverlight.ShellView"
    <Grid Background="White" Margin="5">
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        <sdk:DataGrid AutoGenerateColumns="True"
            ItemsSource="{Binding Path=ResultsPaneItems}"
        <TextBox x:Name="JsonResult" AcceptsReturn="True"
                 Grid.Column="1" Grid.Row="0" 
                 Width="400" VerticalScrollBarVisibility="Auto" 
        <StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal">
            <Button x:Name="LoadCustomers" Content="Load Customer" Margin="5" />
            <Button x:Name="LoadOrders" Content="Load Orders" Margin="5" />
            <Button x:Name="LoadQuery" Content="Load Query" Margin="5" />

Because I am using Caliburn.Micro, my XAML is very clean.  We see a DataGrid that has it’s ItemsSource property bound to collection property called, “ResultsPaneItems” object.  We also see a TextBox that is bound to a property called, “JsonResult” as well.  Finally, we see three buttons that call the three corresponding web methods.
Looking at the ShellViewModel we see the following:

namespace CustomerTypeProvider.Silverlight 
    using System.ComponentModel.Composition;
    using System.Collections.ObjectModel;
    using Core.Framework;
    using Core.Framework.Formatting;
    using Caliburn.Micro;
    using System;
    using System.Net;
    using System.Json;
    using System.IO;
    using System.Diagnostics;

    public class ShellViewModel : Screen, IShell 
        public ObservableCollection<CustomType> ResultsPaneItems { get; private set; }
        private string _jsonResult;
        public string JsonResult
            get { return _jsonResult; }
                _jsonResult = value;
                NotifyOfPropertyChange(() => JsonResult);

        #region ctor

        public ShellViewModel()
            ResultsPaneItems = new ObservableCollection<CustomType>();



        public void LoadCustomers()

        public void LoadOrders()
        public void LoadQuery()
            string query = "SELECT TOP 10 [CustomerID],[CompanyName],[Address],[City],[Region],[PostalCode],[Country]  FROM [Customers]";
            LoadResultsPane("/home/GetQuery?query=" + query);

        private void LoadResultsPane(string uri)
            ResultsPaneItems = new ObservableCollection<CustomType>();

            Uri serviceUri = new Uri(uri, UriKind.Relative);
            WebClient downloader = new WebClient();
            downloader.OpenReadCompleted += (s, e) =>
                // Load the JsonArray from the service call.
                StreamReader sr = new StreamReader(e.Result);
                var content = sr.ReadToEnd();
                JsonResult = new JsonFormatter(content).Format();
                var jsonArray = JsonArray.Load(e.Result) as JsonArray;
                if (jsonArray == null) return;

                // Pull the first record as a template.
                var template = jsonArray[0] as JsonObject;
                if (template == null) return;

                // Use the template to get type information.
                var jsonHelper = new JsonHelper<CustomType>(template);

                // Iterate over the results and add to the underlying collection.
                foreach (var item in jsonArray)
                    var customType = new CustomType();
                    jsonHelper.MapJsonObject(customType.SetPropertyValue, item);
            // Retrieve the data.


Okay, let’s start from the top and work our way down. First we see that declaration of the ResultsPaneItems collection. Next we see the property for the JsonResult string. In the constructor, we initialize the collection.

Next, we have the three methods that respond to the corresponding buttons. All three of them call a helper method called, “LoadResultsPane(string uri)”. It is this method that does all of the heavy lifting. The only difference in the methods is that the last one also passes in the query as part of the query string to the GetQuery method on the controller.

In the LoadResultsPane(…) method, we are initializing the ResultsPaneItems to a new collection. Note that this collection is of type CustomType. This is important since we want each button click to load a fresh set of data. Next we use the Uri and WebClient objects to perform the OpenReadAsync(…) call. This is an asynchronous call and that is we we have an anonymous delegate in the form of a lambda expression stating what to do when the call comes back. Inside the expression, we create a StreamReader object off of the Result. We read the stream so that we can use our formatter class and display the raw JSON that was just returned to us. Next we create a JsonArrary and load the same Result object trying to cast it to a JsonArrary object. If that is successfuly, then we use the first row as a representation of the data so that we can type it accordingly. If you recall, this is why we had the test for DBNull in the data reader loop on the controller. Finally, we loop over the JsonArrary and create a CustomType object. We use the JsonHelper provided by the previous blog posts and then add it to our collection.

That is all there is to it. You now have a very dynamic model in which you can data bind to any object that is sent from the server. You no longer need to know about it. The server-side code could be further abstracted so that you had a completely generic solution instead of the hard-coding I have shown in the loop of the data reader.

Here is a sample screen shot of the application:

You can download the sample code here. Don’t forget that this solutions works only for Silverlight 5 beta.
Hope you enjoy…

  1. June 21, 2011 at 8:12 pm

    Somebody necessarily lend a hand to make severely posts I would state. That is the first time I frequented your web page and to this point? I amazed with the analysis you made to make this actual publish extraordinary. Excellent task!
    Welcome to my blog : [url=http://www.neckbackpainrelief.org]Lower back pain relief[/url]

  1. June 6, 2011 at 12:54 pm
  2. June 7, 2011 at 7:18 am
  3. September 1, 2011 at 5:18 pm
  4. September 3, 2011 at 1:40 am
  5. September 6, 2011 at 7:59 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: