| Comments

My friend Joel Neubeck is doing a survey on his site about what patterns people prefer for Silverlight development.  I’m very interested in these results as well, so if you have 2 seconds, please post your vote:

Link: Poll: What separation pattern do you prefer in Silverlight development?

| Comments

[previously named "Silverlight as the V in ASP.NET MVC" but changed per comments]

One thing that I’m excited about is learning new technologies.  Moving to the Silverlight team, I’ve moved away from a breadth of technology knowledge to something a bit more narrow.  Now I feel like all other developers trying to keep up with the technologies we are releasing.  As such, I’m a beginner for most.  One such technology is ASP.NET MVC, which was just released to release candidate stability.

I thought I’d play around with it in the context of Silverlight and use Silverlight as the “view” in the model-view-controller concept.  It’s easy to link the two.  In fact when you create a new Silverlight project, you now have the option of creating an ASP.NET MVC application as the host:

So right from the beginning, you can marry the two together.  Now from here, how can we leverage Silverlight as a view.  Well, here’s my take…learn with me (and comment where you’d do it differently/better and why).

First, I’m still going to create my MVC architecture.  I’m using the Northwind database for simplicity sake in this learning task.  I’ve created a LINQ to SQL data model to that database (which is a local SQLExpress instance).  I then wanted to take the simple task of showing the products by category and displaying them in a simple Silverlight application.

NOTE: Yes, this Silverlight view is basically just a layout of ListBoxes, but remember, this is just a learning experiment for us.  You may also ask yourself about Authentication/Authorization…again, this post is about an experiment and not a full-featured implementation, so there are bound to be missing pieces.

I decided to create a CategoryController and a ProductController which would handle the actions to retrieve list of categories and products and then drill into the detail of a product.  From there I still need some web View to be a container for my real view, the Silverlight application.  I created a View for Category, since essentially that’s the initial view my user would see.  All it is is an index page hosting my Silverlight application:

   1: <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="SilverMvc.Web.Views.Category.Index" %>
   2: <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
   3:     <p>
   4:         <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
   5:             <param name="source" value="ClientBin/SilverlightWithMvc.xap"/>
   6:             <param name="onerror" value="onSilverlightError" />
   7:             <param name="background" value="white" />
   8:             <param name="minRuntimeVersion" value="2.0.31005.0" />
   9:             <param name="autoUpgrade" value="true" />
  10:             <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">
  11:                  <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
  12:             </a>
  13:         </object>
  14:     </p>
  15: </asp:Content>

Now all I have to do is start building my real view that will be here, the SilverlightWithMvc.xap application.  But first I obviously need my controllers to respond so some requests.  I wanted the CategoryController to display a list of categories and a list of products associated with a category.  But remember, my View will not be the ASPNET View, but rather my Silverlight app.  How then could I get the ViewData to be sent to my Silverlight application.

In MVC, typically your code will return a View from the action, similar to my Index view in my CategoryController:

   1: public ActionResult Index()
   2:         {
   3:             return View();
   4:         }

See where the return is an ActionResult (common) and the return is a View, also common.  This return would expect that there would be a View named Index in the project hierarchy, which in our case there is and again, is the initial hosting page for our app (located in /Views/Category/Index.aspx).  But what about our other data.  I wanted to add a controller action called List and Products that would list all the categories (List) and then list all the products for a given category (Products).  But I just wanted the data.  It turns out that the MVC framework can give us just the data instead of the View.  There is a Json return type.  So using my LINQ queries I created the two actions:

   1: public ActionResult List()
   2:         {
   3:             NorthwindDataContext db = new NorthwindDataContext();
   4:             var cats = from cat in db.Categories
   5:                        select new
   6:                        {
   7:                            cat.CategoryID,
   8:                            cat.CategoryName
   9:                        };
  10:  
  11:             return Json(cats);
  12:         }
  13:  
  14:         public ActionResult Products(int id)
  15:         {
  16:             NorthwindDataContext db = new NorthwindDataContext();
  17:             var prods = from prod in db.Products.Where(cat => cat.CategoryID == id)
  18:                         select new
  19:                         {
  20:                             prod.ProductID,
  21:                             prod.ProductName,
  22:                             prod.UnitPrice,
  23:                         };
  24:             return Json(prods);
  25:         }

As you can see the return type is Json and passing in the model data of what I need…as opposed to saying return View([modelData]).  I now get Json formatted data as a return result.  Great, now how to consume them?

Within Silverlight, we know we can consume Json data and we can take advantage of that capability to bring MVC and Silverlight together.  First let’s look at my layout UI code for the Silverlight application…it’s basically going to be a cascading ListBox view:

   1: <UserControl x:Class="SilverMvc.Page"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   4:     <Grid x:Name="LayoutRoot" Background="White">
   5:         <StackPanel Orientation="Horizontal">
   6:             <StackPanel Orientation="Vertical" Margin="0,0,25,0" x:Name="CategoryListing">
   7:                 <TextBlock Text="Select a category..." FontWeight="Bold" />
   8:                 <ListBox Width="200" Height="150" x:Name="CategoryList" ItemsSource="{Binding}" SelectionChanged="CategoryList_SelectionChanged" />
   9:             </StackPanel>
  10:             <StackPanel Orientation="Vertical" Margin="0,0,25,0" x:Name="ProductListings" Visibility="Collapsed">
  11:                 <TextBlock Text="Select a product..." FontWeight="Bold" />
  12:                 <ListBox Width="200" Height="150" x:Name="ProductList" SelectionChanged="ProductList_SelectionChanged" />
  13:             </StackPanel>
  14:             <StackPanel Orientation="Vertical" x:Name="ProductDetail" Visibility="Collapsed">
  15:                 <TextBlock Text="Product Details:" FontWeight="Bold" />
  16:                 <Grid>
  17:                     <Grid.RowDefinitions>
  18:                         <RowDefinition Height="Auto" />
  19:                         <RowDefinition Height="Auto" />
  20:                     </Grid.RowDefinitions>
  21:                     <Grid.ColumnDefinitions>
  22:                         <ColumnDefinition Width="Auto" />
  23:                         <ColumnDefinition Width="Auto" />
  24:                     </Grid.ColumnDefinitions>
  25:                     <TextBlock Grid.Column="0" Grid.Row="0" Text="Product Name: " />
  26:                     <TextBox Width="200" Grid.Column="1" Grid.Row="0" Text="{Binding Path=ProductName, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" HorizontalAlignment="Left" VerticalAlignment="Top" />
  27:                     <TextBlock Grid.Column="0" Grid.Row="1" Text="Unit Price: " />
  28:                     <TextBox Width="200" Grid.Column="1" Grid.Row="1" Text="{Binding Path=UnitPrice, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" HorizontalAlignment="Left" VerticalAlignment="Top" />
  29:                 </Grid>
  30:             </StackPanel>
  31:         </StackPanel>
  32:     </Grid>
  33: </UserControl>

Where one selection drives the next portion of the layout, etc.  You can see that I have several {Binding} statements in there as well as some selection changed handlers.  Let’s look at what happens on Loaded of the app:

   1: void Page_Loaded(object sender, RoutedEventArgs e)
   2:         {
   3:             WebClient mvc = new WebClient();
   4:             mvc.OpenReadCompleted += new OpenReadCompletedEventHandler(mvc_OpenReadCompleted);
   5:             mvc.OpenReadAsync(new Uri("http://localhost:33828/Category/List"));
   6:         }

You can see that I’m making a WebRequest call to a URI that happens to be our CategoryController with the List action command.  On the return event handler I’m getting that stream of data, which we know to be Json data, and setting the DataContext of my first ListBox:

   1: void mvc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
   2:         {
   3:             DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(List<Category>));
   4:             List<Category> cats = (List<Category>)json.ReadObject(e.Result);
   5:             CategoryList.DisplayMemberPath = "CategoryName";
   6:             CategoryListing.DataContext = cats;
   7:         }

Now you may at this point be asking a few questions about some of my decisions here within Silverlight.  First, the use of DataContractJsonSerializer.  Where is it?  Add a reference to System.ServiceModel.Web and you’ll get it.  You can also see that I’m using the ReadObject method and casting it to a List<Category>. 

Why not use System.Json and LINQ to JSON?  You could absolutely.  In doing so you could use your LINQ skills and get the data out of the Json stream and put it into a new object.  You’ll still have to create a local class representation because Silverlight can’t bind to an anonymous type.  This is the first reason I like just using the serializer.  The second reason is size.  I don’t know why I’m so picky, but I am.  Using the DataContractSerializer method here, my app is about 7K.  Adding a reference to System.Json and using those methods, my app is 27K.  For me, there is no additional benefit in code for what I’m doing to add that extra size, so I choose not to.  But you can…absolutely.  Your application needs may be different and the size cost/benefit analysis may result in a different outcome than mine…but there, I’ve stated my reasons here.

Where is Category defined?  Great question!  Category is a class defined in my Silverlight object that maps the data to a strongly-typed class..here’s the class definition:

   1: public class Category
   2:     {
   3:         public int CategoryID { get; set; }
   4:         public string CategoryName { get; set; }
   5:     }

Now that that is done, my data is retrieved, typed and bound to my UI.  Then in the category ListBox when a category is selected, we trigger a similar event to retrieve the products within that category and populate the product list using the same technique.  The final stage is that when a product is selected we populate a simple UI to show the details.  We could also have called another controller action, but here since we had most of the data in the product listing, we simply push the data to the DataContext of the layout container for the details:

   1: private void ProductList_SelectionChanged(object sender, SelectionChangedEventArgs e)
   2:         {
   3:             if (ProductList.SelectedIndex > -1)
   4:             {
   5:                 Product p = ProductList.SelectedItem as Product;
   6:                 ProductDetail.DataContext = p;
   7:                 ProductDetail.Visibility = Visibility.Visible;
   8:             }
   9:         }

You can see we get the SelectedItem as a Product (another internal class like Category) and make it the DataContext of the ProductDetail StackPanel who’s children have binding instructions.  The end result is this “view” below (the headings above the list boxes are not in the UI, but rather just labels to map to the controller action used to populate:

As I completed this little experiment, several things did come to mind…

  • What about deep linking?  The URI in the app didn’t change.
  • Now that I’m looking at a detail view, does the URI stating the initial view matter?

I think mostly these are “simple” things, but important to an MVC developer audience.  The interaction of URI semantics with Silverlight are important and things we are addressing in Silverlight 3 to make even this simple experiment easier.

So tell me, ASP.NET MVC experts, does this make sense?  Good/bad/what would you do different?  Help me learn how you would make the interaction between ASP.NET MVC and Silverlight better?

You can download my sample code for this project here (requires SQL 2008 and VS2008 with Silverlight and ASP.NET MVC tools installed): SilverlightWithMvc.zip

| Comments

Silverlight MVP and friend, Joel Neubeck, has started a series in the Expression Newsletter.  The first article is available now and is part of a 6-part series in building a casual game in Silverlight:

    • Getting Started – Architecture / framework
    • Movement and collision detection
    • Design – Sprites, boards and dialogs
    • Animations and sound
    • Initialization and Deployment
    • Advanced concepts (Physics, Multiplayer, Optimization)

This first article talks about some of the framework that will be used, specifically an MVC model:

“In Silverlight development, MVC is an excellent way to support role specific tools such as Visual Studio for the developers and Expression Blend for designers and animators.  Using MVC in a game ensures a foundation that isolates a developer’s ability to control state (position, movement and collisions) while allowing designers full control over how game elements are rendered.”

This should be a good series to watch and add to your toolbox for developing casual games in Silverlight 2.

| Comments

Well, I wish I was going to this event: ReMIX UK!  For one, it would be starting the day of my birthday and would be a great birthday treat!  Secondly, I would be able to meet up with my fellow escamoles chaps and maybe take in some local cuisine instead.

If you are in the UK, or for some reason really wanted to see the current value of the US dollar, make sure you head to ReMIX UK!  The lineup is pretty incredible when you look at it…here’s some Microsoft favorites:

I also saw on the agenda for the 2 day event that Tim Sneath and Jesse Liberty were listed, so it should be even richer (pun intented) content.  In addition it looks like some great stuff on the designer and creative strategy side of the business as well.  I’m sure there will be enough Silverlight stuff there to keep you going as well as WPF, ASP.NET and others!

By the way, I listed Dr. Neil above as one of my Microsoft favorites.  He’s actually one of our Regional Directors.  If you have never met Dr. Neil…do so.  He’s a great guy, very intelligent and fun to be around.  Ask him about how he manages developer teams and the ‘check-in’ metaphor for people, not just code.  Seriously, he would be a not miss either.

I wish I could travel across the pond for this one, but I’ll be hopefully approximately 25 meters under water in some area of Mexico celebrating with friends.  Have fun though!

| Comments

If you already pay attention to the IronRuby dev group and are on the distribution list, apologies for the dupe.  I’ve just got back from a camping trip and rifling through all my emails now.  I checked in on the IronRuby group and noticed a new project emerging from someone.

It’s from Ivan Porto Carrero and he calls it IronNails.  It was previously called something else (quite frankly I liked the other name better myself) but there was already a project named after his chosen name.  So alas, IronNails it is!  Ivan describes this as:

IronNails is a framework inspired by the Rails and rucola frameworks. It offers a rails-like way of developing applications with IronRuby and Windows Presentation Foundation (WPF). This framework uses the pattern Model - ViewModel - View - Controller (M-VM-V-C). It should be able to run on both WPF and Silverlight.  The idea is that the views can be created using a design tool like Blend for example and just save that xaml as is. The designer should not need to use anything else than drag and drop to create a GUI design. The behaviors are then added to the view by using predefined behaviors in the framework or by defining your own behavior. Source: IronNails GitHub homepage

The project is really just started so don’t expect a ton of meat there just yet, but it has a great goal and I can’t wait to see it evolve.  Ivan’s using the Rails-like framework of MVC where the XAML can serve as the view for either a WPF or Silverlight application.  The idea being that someone can create a view using a rich interface design surface like Expression Blend and write the code that targets the view which can be fine tuned to either Silverlight or full WPF.

The vision is something like this:

   1: class MyController < IronNails::Controllers::Base
   2:  
   3:   view_object :some_model, :refresh => :refresh_some_model, :refresh_interval => 2.minutes
   4:  
   5:   view_action :some_action, :target => :my_button, :action => :some_action_implementation
   6:  
   7:   def refresh_some_model
   8:     # code here
   9:   end
  10:  
  11:   def some_action_implementation
  12:     # code here
  13:   end
  14:  
  15: end

If you are interested in contributing or lurking, get on over to GitHub and watch the project!