Getting started using Silverlight 4 in an ASP.NET MVC 3 application and accessing data with JSON

Posted on April 11th, 2011

ASP.NET MVC is such a great platform for web applications because it makes it so easy to tackle many different integration challenges. You need to add a Silverlight application to your web site and send it some JSON data to work with? No sweat. Stumped on where to start? Well, you are in the right place. Let's make it happen.

In honor of kicking off tomorrow, we will imagine that we are tasked with the need to build a web application that renders a list of MIX 11 sessions and allows the video of each session to be viewed in a browser (of course we don't really need to build such a solution because the live.visitmix.com site already provides that content for us...but, for the sake of being hypothetical). What a perfect reason to use Silverlight in a MVC 3 web application! We will work through rendering a Silverlight application in an MVC 3 view and populate it with a list of MIX 11 session names delivered in JSON from our MVC application. We will not be addressing how to render video in Silverlight in this post though, so if you want to take the Silverlight portion further you may want to check out www.iwantmysilverlight.com (is anyone actually rockin' that domain name?).

As always, we begin with a blank ASP.NET MVC 3 Web Application project (named Website) using an Empty project template and target the Razor view engine. Once the solution is created with the MVC project we will add a new Silverlight Application project to the solution.

New Project

To start this post I didn't have the Silverlight Developer Tools installed on my workstation running Visual Studio 2010 (Service Pack 1), so I encountered the following dialog upon clicking OK from the add project dialog:

No Silverlight Developer Tools installed

Clicking on the link in this dialog opened up a browser and downloaded the installer. After running the installer, restarting Visual Studio 2010, and attempting to add the new Silverlight Application project a second time I found success. The Silverlight Application project prompts you with an options dialog:

Silverlight Application options

I unchecked the options for "Add a test page that references the application" and "Enable Silverlight debugging (disables javascript debugging)" and clicked OK. Once the Silverlight Application project was added my solution tree looked like so:

Solution Explorer

With the projects in place we are ready to start adding some code. First up, we need to add a controller and a view that will render a page with our Silverlight application on it. Lets add a good old HomeController with a Index action method. Our HomeController.cs file will contain:

using System.Web.Mvc;

namespace Website.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
}

Our Views/Home/Index.cshtml file will contain:

@{
    ViewBag.Title = "Index";
}

Our Silverlight application demo

If we do a quick F5 to check out our page we are presented with the following dialog:

Page debugging

I clicked No...nothing broke or melted. The page showed up with our h1 tag screaming at us in huge bold font. Now lets see about getting our Silverlight in that view. The SilverlightApplication project comes pre-loaded with a MainPage.xaml file. If we open that file in Visual Studio 2010 it will give us a split window with a Design view at the top and a XAML view at the bottom. From here we can use the Toolbox window to add some UX stuff. If you don't have this displayed because you build rad ASP.NET MVC web applications without that crazy design view stuff or you recently read Scott Hanselman's blog post on how to Simplify your Visual Studio 2010 Toolbar and Free Your Mind and turned off everything under the sun then you can get it back by hitting Ctrl+Alt+X or navigating to View -> Toolbox from the main menu.

The default content for the MainPage.xaml file looks like:



    

    

We will drag and drop a TextBlock and set the Text attribute to "Session Videos". This will add the following XAML tag to the tag:


Our MainPage.xaml file will end up looking like so:



    
        
    

We can preview this by right clicking on the SilverlightApplication project in the Solution Explorer and selecting "View in Browser" (or hitting Ctrl+Shift+W). With our browser open we can see our Silverlight running, displaying the "Session Videos" text. If we right click on the window content we get the "Silverlight" context menu:

Silverlight right click

Now lets get this puppy running in our view. Guess what! By adding the SilverlightApplication to our solution after we added the ASP.NET MVC 3 Web Application we were presented with the "Host the Silverlight application in a new or existing Web site in the solution" option pre-checked and our project named Website pre-selected in the drop down. Since we left that option checked and the Website project selected, when we did a build of our Website application (the F5 we did earlier to preview it) the SilverlightApplication.xap file was created and deployed to a ClientBin directory in our MVC project.

Solution Tree 2

We can add an tag to our Index.cshtml view file to render our Silverlight application within the view. The code for our view file will be:

@{
    ViewBag.Title = "Index";
}

Our Silverlight application demo

Get Microsoft Silverlight

If we do another F5 we will see our page with our Silverlight application included.

Silverlight application in page

So we have some Silverlight running in an ASP.NET MVC 3 web application. Coolio! Now lets see what we can do to populate some data in that Silverlight. We will create a new action method in our HomeController.cs file named SessionVideoList that will return a JsonResult that will contain a list of session names we can use in our Silverlight application. We can create a List of some session names and return it as a Json object. Our updated controller code:

using System.Collections.Generic;
using System.Web.Mvc;

namespace Website.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public JsonResult SessionVideoList()
        {
            var sessionVideos = new List { "Keynote", "Silverlight Boot Camp", 
                "Fun with ASP.NET MVC 3 and MEF", "ASP.NET MVC 3 @:The Time is Now" };
            return Json(sessionVideos, JsonRequestBehavior.AllowGet);
        }
    }
}

We also need to add a route to our route table to be able to call this action method. An update to our Global.asax.cs file will look like so:

using System.Web.Mvc;
using System.Web.Routing;

namespace Website
{
    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "SessionVideoList",
                "SessionVideoList",
                new { controller = "Home", action = "SessionVideoList" }
            );

            routes.MapRoute(
                "Default",
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

        }

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

Our MVC application is set up to provide data for our Silverlight application to consume. Our final step involves adding the code to our Silverlight application to hit our MVC route and process the data returned. To keep it simple, we will modify our MainPage.xaml file to enlarge the TextBlock element so that it fills the Silverlight application and use that to render our list of session names. We can add a Width attribute and change the existing Height attribute on our tag:


This will ensure that the rendering of our TextBlock will be big enough to display a handful of lines of text. From here we need to open up our MainPage.xaml.cs file and add some code to call our MVC action url and process the response stream content. In the constructor for MainPage we will add an instantiation of a Uri object, a WebClient object, and do an async read of the Uri object with the WebClient object. We will also add a private method named openReadCompleted that we will add to the WebClient.OpenReadCompleted event handler. This method will handle processing the JSON data from the response stream and populating our TextBlock element. We are going to use System.Json to process the JSON data which requires us to add a reference to the .NET assembly in our SilverlightApplication project.

Add reference

Lets take a look at the code in the file as a whole and then we will go over the parts.

using System;
using System.Json;
using System.Net;

namespace SilverlightApplication
{
    public partial class MainPage
    {
        public MainPage()
        {
            InitializeComponent();
            var serviceUri = new Uri("/SessionVideoList", UriKind.Relative);
            var webClient = new WebClient();
            webClient.OpenReadCompleted += openReadCompleted;
            webClient.OpenReadAsync(serviceUri);
        }

        private void openReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            if (e.Error != null) return;
            var sessions = (JsonArray)JsonValue.Load(e.Result);
            foreach (string sessionName in sessions)
            {
                this.textBlock1.Text += string.Format("{0}{1}", Environment.NewLine, sessionName);
            }
        }
    }
}

In the MainPage constructor we instantiate a new Uri object. We pass in a relative uri string that represents the route to our action method. We need to include the UriKind argument (value of UriKind.Relative) in this constructor in order for our Silverlight application to correctly resolve the path when rendered in our MVC application. Then we instantiate our WebClient, add the event handler, and do our asynchronous read.

public MainPage()
{
    InitializeComponent();
    var serviceUri = new Uri("/SessionVideoList", UriKind.Relative);
    var webClient = new WebClient();
    webClient.OpenReadCompleted += openReadCompleted;
    webClient.OpenReadAsync(serviceUri);
}

In our openReadCompleted method we do a simple check for errors and return without taking any action if we encounter an error. From there we use the JsonValue.Load method to deserialize the response stream data that is stored in the OpenReadCompletedEventArgs.Result property and cast it to a JsonArray object. This is based on knowing the structure of the JSON objects we are dealing with...there are other JSON object types that can be used here. More info can be found on MSDN. Finally, we iterate through the JsonArray object and add the session name to a new line in our TextBlock element.

private void openReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    if (e.Error != null) return;
    var sessions = (JsonArray)JsonValue.Load(e.Result);
    foreach (string sessionName in sessions)
    {
        this.textBlock1.Text += string.Format("{0}{1}", Environment.NewLine, sessionName);
    }
}

If we go back to our MVC project and do an F5 we will see our Silverlight application rendered in our page and populated with the JSON data from our SessionVideoList action method.

Final page view

And voilà, we have a starting point for an integration between ASP.NET MVC 3 and a Silverlight 4 application. The rest is easy right? Simply build a robust Silverlight application solution and update the MVC application to return more complex JSON data. Knock that out in a day or two? I think I'll spend the next day or two sitting at home watching the and toss some sadfaces out as I watch all the Twitter chatter from all of those out in Vegas having fun instead. Oh, and answer reader comments of course!

Discussion

Arroyocode
Arroyocode
12 Apr, 2011 05:16 PM

Excellent post. Regarding the SP1 installation issue, installing Silverlight 4 Tools for Visual Studio 2010 takes care of Silverlight, WCF Ria services/SP and developer runtime, etc. in one shot (if memory serves me correct).

Bart Czernicki
12 Apr, 2011 05:33 PM

I created an ASP.NET MVC HTML Helper for Silverlight that takes away all that nasty HTML object markup:

http://silverlighthack.com/post/2010/11/16/Creating-a-ASPNET-MVC-HTML-Helper-for-Silverlight.aspx

I used it in ASP.NET MVC 2, but should work in ASP.NET MVC 3.

12 Apr, 2011 05:43 PM

Bart Czernicki
Nice! Thanks for sharing. Here, let me make that link clickable so we can help people get to your post easier :)

raytheon
raytheon
16 Apr, 2011 09:20 AM

good article.

paulomarcos
paulomarcos
23 Apr, 2011 01:17 PM

Lovely post.

Congrats and Thanks.

PM.

tresorunikin
26 Jun, 2011 04:42 PM

What a good interoperability!!!!

19 Jul, 2011 10:08 PM

The application compiles and runs correctly, but the Silverlight object shows and immediately disappears. It is still there because the context menu in that area shows "Silverlight", but it is invisible.

Did I miss something in the code or properties???

Thanks

Chris S.

20 Jul, 2011 12:31 AM

Christian Sanabria
Do you have the width and height attributes on your TextBlock element? Width and height attributes on the html object tag? Is the "Sessions Videos" text showing up? If so, can you put a breakpoint in the SessionVideoList action method on the MVC side and a breakpoint in the openReadCompleted method on the Silverlight side and confirm that those are getting reached when running in debug mode? It sounds like it may be an issue with the TextBlock element on the Silverlight side, but without seeing the code I am kind of shooting at the dark. Is your TextBlock element nested inside the Grid element in your xaml?

Navin
Navin
09 Aug, 2011 02:48 PM

Nice article. thanks

Andy
Andy
23 Aug, 2011 07:43 PM

Nice Article!! Thanks for sharing. I have a doubt though. I have SL-3 app that i am using inside MVC as you told in the article. But on the browser i always get the message that Plug-Ins required...inspite of checking that all plug-ins are available. My SL-3 app is image sliding app.

25 Aug, 2011 02:52 PM

Navin
Welcome!

Andy
I would suggest checking out the HTML object tag. Maybe there is something off in there or maybe something needs to be tweaked for the browser you are using.

Jack
Jack
02 Sep, 2011 04:29 PM

When I run the project after adding the object block to the Index.cshtml, the Silverlight block appears simply red. The grid in the xaml, along with the grid's contents, do not display. Is there a setting (browser, VS 2010, other) that I am missing?

08 Sep, 2011 02:21 AM

I have SL-3 app that i am using inside MVC as you told in the article. But on the browser i always get the message that Plug-Ins required...inspite of checking that all plug-ins are available.

21 Oct, 2011 10:57 AM

A great explanation on how to pull data from an MVC app but how would you handle binding data back? Some sort of a 'POST' perhaps?

Paul Wade
Paul Wade
22 Oct, 2011 06:32 PM

Thought I would share this re. If you don't see anything appearing after you run the application, or you only see a red box.....

Check the object tag in your Index.cshtml (see below).

I had to change SilverlightApplication.xap to SilverlightApplication1.xap (see above)

This has to match the name in your ClientBin folder.

Hope this helps.

nick
08 Dec, 2011 07:10 PM

Great article. The only thing I would add is what your fiddler response is. The only reason, is because I had an issue with the new URI being different because of how I implemented it. Otherwise, really great code!

jessie
jessie
09 Jan, 2012 01:09 AM

THANK YOU VERY MUCH... this helps me a lot as beginner to ASP MVC 3 and Silverlight 4. this will resolve my issues in integrating C#.NET-ASP MVC 3-Silverlight-Oracle. again THANK YOU, THANK YOU, THANK YOU...

ThaiCarrot
ThaiCarrot
20 Feb, 2012 07:57 AM

Hi, I just scan but not all of this content. What is the advantages about this? However, I was found that Controller is great endpoint for manipulate html's view and data.

I am not agree with this blog posted because we would like to take advantages of Silverlight FrameWork rather than force Silverlight into HTML abilities.

We can integrated Silverlight into MVC3+ by Expose WCF Ria Service or WCF. Is it more easier and more power? Yes U can.

Chase
Chase
06 Mar, 2012 07:52 PM

I am also having trouble getting this to work - I copied this code verbatim as it's shown in this article and nothing...

Here's what's happening... (FWIW - I am using the Razor View Engine and MVC3)

My view loads just fine and the HTML object tag loads a silverlight window as expected with the correct dimensions, but for some reason my silverlight XAP file doesn't appear to be getting loaded (i.e. my form that I created in the silverlight project never get's displayed just an empty silverlight window).

I checked the app file in the silverlight project and verified that the correct startup object (my silverlight form) is being constructed so that's not the problem...

I also already verified that it does not have anything to do with a potential typo that may be in the path to my XAP or anything else within the object tag because I can cut and paste the entire object tag into a regular HTML page (sans MVC3) and it works like it's supposed to.

What would be the cause of this? Is it because I am using a layout page? I am confused - any help would be greatly appreciated!

Chase
Chase
17 Apr, 2012 04:32 PM

Fantastic Article! I was able to get this working just fine, but now I want to save data using a similar method. Do you have any recommendations or articles / posts where posting data in the same fashion from Silverlight can be accomplished?

Again - thanks for writing this, it was a huge help!

Teletexto
Teletexto
07 Jun, 2012 03:41 PM

Fantastic work!!! It was so helpful. I am trying to do your example with entityframework for the data. Textblock works good cause it "needs" string but i´m trying to do it whit a datagrid and i´m not able to populate data in the itemsource property. Any suggestion?? Thanks for write the article.

No new comments are allowed on this post.