All posts by joshholmes

Taking The Polar Plunge

If you would like to donate to the 2010 Polar Plunge please visit my 2010 Polar Plunge Donation Page

Josh Holmes doing the Polar PlungeAs I talked about in a recent post, I recently participated in a fund raiser for the Special Olympics of Michigan. The end of the fund raiser was that I did a Polar Plunge.

clip_image002This is a charity that is special to me because of my youngest daughter, Maura, who has a lot of challenges of her own. One day, my hope is to see her compete in the Special Olympics.

 

To find out more about Maura, see the “About” page at Wonderpuzzle.org. http://www.wonderpuzzle.org/site/About.aspx

 

Turns out a lot of people wanted to see me jump in a frozen lake… 🙂 In the end, I raised $725.00 + whatever we get through matching funds so probably a little over $1000.00. So, for all of you who paid to see me do it – here’s the video.

 

Special thanks to all of you who donated – many of who are friends on twitter…

Display Name Date Amount  Comment
Omar Greene 2/14/2009 $50.00 Josh is a fine person. Known him since his boyhood.  
JSConf 2009 2/13/2009 $100.00  
Michael Eaton 2/13/2009 $25.00  
David Giard 2/13/2009 $25.00  
Aaron Lerch 2/13/2009 $25.00  
Carey Payette 2/13/2009 $25.00 Great Cause 
tye 2/12/2009 $25.00  
Anonymous 2/12/2009 $25.00 good luck! 
Dennis Burton 2/12/2009 $25.00  
Frank Martin 2/11/2009 $25.00 Happy to help this cause. 
Susan Holmes 2/11/2009 $25.00 Because we love you and yours 
kellie englund 2/10/2009 $25.00 hope Phoebe gets your new suit done in time!!! 
Denny Boynton 2/10/2009 $50.00 Because you’re even willing to do it… 
Pandamonial 2/10/2009 $40.00 Good luck!  
Ryan Stewart 2/10/2009 $50.00  
Anonymous 2/9/2009 $20.00 don’t freeze your butt off! 
Bruce Szabo 2/9/2009 $25.00 Good Luck! 
Anonymous 2/9/2009 $40.00 Good luck!  
Tim Adams 2/9/2009 $100.00 God Bless!!! 

 
 
Grand Total: $725.00

It was a surreal experience. I watched how far across the water it was and decided that I just needed to make a dive for it. The water was about 8 foot deep where I made the jump. When I hit the water, every last bit of breath left my body. As one person said, that’s God’s way of making sure you don’t yell bad words when you hit the surface. I said something about “Man that’s cold” but it came out “BBBBBRBRRRBBRBBBRBBRBBRBRBRB”. The really bizarre thing was getting out of the water and realizing that I was walking across the snow and my feet didn’t feel cold. The snow actually felt a little warm. I got in and changed the feelings got more bizarre as my skin warmed up but I was still cold inside – exactly the opposite of normal when it’s cold outside your skin is usually the first to get cold.

I just got off the phone with a friend who asked “Would you do it again?”. I answered “Yes”. He rephrased the question with “Would you do it again if there wasn’t a good cause involved?”. I answered “No…”

Look for me to do it again next year but I’m going to go bigger on the fund raising and possibly go with a costume…

Three Essential Expression Blend Add-ins

image Expression Blend, believe or not, has an add-in model. It’s highly unsupported but it exists. The unsupported nature of it means that you have to do a little Red Green style patching to get them to run in the first place and if they cause instability, don’t call Microsoft support. However, there are a couple of really cool ones that are out there.

There are three that I think that you have to have – Unify, Colorful Expression and BlendSense: XAML Intellisense for Expression Blend.

Getting a Blend Add-in to run

Because it’s not a supported add-in model, there’s not a built in add-in manager that does the heavy lifting like the Visual Studio Add-In manager.

imageWhat you have to do is open up Expression Blend (or Design) passing in your add-in as a command line option. This starts up blend with that add-in enabled. The good news is that you don’t have to do any type of COM registration or anything to get it to work. The bad news is that it’s a hassle for those of us who don’t live on the command line like some people.

imageAnother other option, is to alter your Blend Shortcut to include the –addin parameter. This accomplishes the same task as the command line, it just does so without all the hassle of opening a command line.

There are multiple problems with both of these solutions.

First, it is only able to handle one add-in at a time. Second, that only loads the add-in when you specifically click on that shortcut but doesn’t work from a lot of other places, like launching from Visual Studio.

The great news about the first issue is that it can be solved by another add-in.

Unify Add-in

imageUnify is an add-in manager. It’s going to do all of the heavy lifting of loading and launch a number of different plug-ins such as the Xaml Intellisense for Blend and Colorful.

When Unify installs it automatically gives you a prompt that starts the Unify add-in. However, that still only solves the first problem of getting the add-in loaded when we deliberately set out to do so.

Launching Blend with Unity from Anywhere

The second problem, as mentioned above, is a little harrier. It’s that the shortcut is not the only way to run Blend. What you have to do is fix all of the different ways that you can run Blend. That includes selecting a project file from Windows Explorer and clicking Edit in Blend in Visual Studio.

This, unfortunately requires some registry hacks and the like but you can get there from here. The first registry hack to fix is the opening a solution from Windows Explorer. To accomplish this, the following code copied into a reg file works on a 64X machine. You’ll have to remove the (86) on a 32X machine.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Expression.Blend.ProjectFile\Shell\Open\Command]
@=”\”c:\\Program Files (x86)\\Microsoft Expression\\Blend 2\\Blend.exe\” \”%1\” /addin:Unify.dll”

The second registry hack to fix is the launching from Expression Blend by right-clicking on a XAML file in Visual Studio and selecting “Edit in Expression Blend”. To do this requires understanding how the right click in Visual Studio works. The list of available commands comes from the registry. When selected, it passes in two parameter. The first is the path to the actual solution and the second is a /file:filename.extension parameter. It looks as follows:

“C:\Program Files (x86)\Microsoft Expression\Blend 2\blend.exe” “C:\Projects\QuickNavigation\QuickNavigation.csproj” /file:”Page.xaml”

What we have to do is redirect this in the registry to a bat file that will pass in our /addin parameter. Personally, I created a BlendWithUnify.bat file in the /Blend directory as follows:

start “Blend” “C:\Program Files (x86)\Microsoft Expression\Blend 2\blend.exe” /addin:Unify.dll %1 %2

Technically, we could have used the .bat file with the first mechanism as well. We need to fix the registry key as follows:

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Expression\Blend\VS]
“BlendLaunchPath”=”\”c:\\Program Files (x86)\\Microsoft Expression\\Blend 2\\BlendWithUnify.bat\””

Now we are cooking with gas and are ready to investigate a few more add-ins.

Colorful Expression Add-In

imageColorful Expression was directed to me by Jared Bienz after the Expression Design tutorial that I talked about recently. It’s a sweet add-in to Expression Blend (or Design) that gives you access to a ton of different color swatches that are out there on the web. Specifically, it taps into Kulor on the Adobe site. These are mostly swatches put together by pro-designers. These are also rated so you can pick the higher rated groups to be sure. In any case, they are definitely better than the ones that my color-blind self can choose.

imageJonas Follesø saw that Kulor has a open restful API and couldn’t resist playing with it. Combine that with the (unfortunately unsupported – see below on how to get it to actually run in Blend…) add-in model for Blend and magic happens.

What it does is that it shows up as a tab in Expression Blend (or Design) and alls you to browse color pallets from Kulor for use in your application. There are a couple of slick ways that you can do that.

First, if you are running Design, you can hit the down arrow looking thing under a swatch and save it as an Expression Design Color Swatch. The next two work in either Blend or Design.

First, you can click the # button or select the swatch and hit Ctrl-C to copy the swatch to the clip board. If you paste that on a Page or UserControl, you get the swatch, but more importantly, you get the colors created as static resource brushes. You can also just go into the XAML in either the UI surface or the app.xaml and paste them that way.

Second, you can use the color picker from the normal color picker to select an individual color. This is pretty cool as well as it allows you to be very selective about your colors.

You can also run it as a standalone application if you want to pick a color swatch for use in something other than Blend or Design. I can see using to figure out color pallets for my CSS style sheets. I’m also going to contact Jonas and see if he has thought about building it for Expression Web. But that’s just me wishing and hoping until I hear back from him.

Check out Colorful Expression and give it a whirl. I’m interested to see how you use it.

BlendSense: XAML Intellisense for Expression Blend Add-in

image Just yesterday I was on a call with a guy who was frustrated by the fact that there’s no Intellisense in Blend for XAML. Well, ask and you shall receive. There’s a skunk works project called BlendSense that was put up at http://code.msdn.microsoft.com/BlendSense but it was only for the Beta versions of Expression Blend 2.5. They haven’t updated it for the release which was actually called Expression Blend 2 SP1. So, the good folks at http://www.rhizohm.net recompiled the code for us and posted it at BlendSense: XAML Intellisense for Expression Blend.

There are a couple of limitations on it’s functionality. right now, it’s using the WPF namespace types and the like for it’s Intellisense. That means that it’s not ideal for Silverlight as the Intellisense might be lie to you – but that would just take me back to my MFC days… The second limitation is that it doesn’t handle custom namespaces and the like so you’re out of luck if you are using a custom control or third party components.

Technically, it’s using an XSD file that is built for Intellisense so you could edit it to fit your needs.

Conclusion

These three add-ins are fantastic and I’m thrilled that they are here. Both of them have already, in the day that I’ve been using them, saved me time and energy in some things that I’m working on. It’s a little bit of a frustrating process to get Unify running for every scenario but it’s worth it and hopefully I’ve done the leg work on figuring it out for for you.

Polar Plunging for the Special Olympics

What I’m doing:

I’m going to be polar plunging to raise money for the Special Olympics Michigan this coming weekend in Belleville.

clip_image002This is a charity that is special to me because of my youngest daughter, Maura, who has a lot of challenges of her own. One day, my hope is to see her compete in the Special Olympics.

To find out more about Maura, see the “About” page at Wonderpuzzle.org.

http://www.wonderpuzzle.org/site/About.aspx

 

How you can help:

If you can donate, please check out my donation page at http://www.firstgiving.com/joshholmes.  

 

About the Event:

If you want to watch (video – whatever), come and ‘bear’ the elements at the 2009 Polar Plunge – Belleville at 11:30 a.m. Saturday, Feb. 14 at the Belleville Moose Lodge (831 East Huron Dr. Belleville, MI 48111). Registration begins at 10:30 a.m. with the plunge and parade of costumes beginning at 11:30 a.m. with a warm post-plunge party at 12:30 p.m.

The polar plunge is a fun-filled event open to all courageous and community-minded individuals willing to plunge into the cold water and raise critical funds to support the year-round athletic training of more than 16,000 athletes across the state. Be sure to pre-register to receive detailed information.

 

About the Special Olympic Michigan:

The mission of Special Olympics Michigan is to provide sports training and athletic competition in a variety of Olympic-type sports for the children and adults with intellectual disabilities. Athletes are given continuing opportunities to develop physical fitness; demonstrate courage; experience joy; and participate in a sharing of gifts, skills, and friendship with their families, other Special Olympics athletes and the community. Through Special Olympics, athletes gain self-confidence and prove their own capabilities.

UI Design for Developers Series, by Total Training.

image

I’m at an internal conference at Microsoft this week and one of the sessions that I attended was called Practical Design tips and tricks for Developers. It was a set of hands on labs that were created out of the Expression team. It was really slick and I learned a whole lot of new techniques and am feeling a whole lot more confident in my Expression Blend abilities. The really slick part is that you get to work through those same labs if you are interested because they have been posted on Arturo’s blog.

This 13 part video series will walk you through creating a workable color palate with a range of colors which all work together, creating brush resource out of those, creating shapes all the way from simple straight and curved lines to glass button effects with the simplest possible steps and really sets you up with the basics of what you need to know. It was really cool to be able to walk through those labs.

The labs are as follows:

1Principles of Design Series:  Learning about Balance using Expression Design

2Principles of Design Series:  Learning about Rhythm using Expression Design

3Principles of Design Series:  Learning about Emphasis using Expression Design

4Principles of Design Series:  Learning about Symmetry and Asymmetry using Expression Design

5Principles of Design Series: Learning about Unity using Expression Design

6Principles of Design Series:  Learning about Points, Lines, and Form using Expression Design

7Choosing Colors to Complement Your User Interface with Expression Design

8 – Experimenting with User Interface Colors with Expression Design

9 – Creating Mosaic and Tiled Patterns using Expression Design
10 – Learning to Create Icons using Expression Design
11 – Creating a Sample Icon using Expression Design
12 – Designing a Glassy Button using Expression Design
13 – Applying Effects to Bitmap Images using Expression Design

 

For links to the videos and digital assets that you need to accomplish the the labs, check out Arturo’s post on it at ux.artu.tv » Blog Archive » New Video Series: UI Design for Developers Series, by Total Training.

Adding Paging to the Simple Photo Gallery

Turn the pageOver my last handful of posts, Building a Simple Photo Gallery in ASP.NET MVC Framework, Returning Thumbnails With the MVC Framework and Adding Lighbox.js to the Simple Photo Gallery I’ve built a simple photo gallery on the ASP.NET MVC framework.

In this post, we’re going to continue that project by adding paging rather than showing all of the pictures on the one page.

Adding Paging to the Model with LINQ

Since we are simply using an XML file for the storage, we need to do the paging manually against our set of objects that we have in memory. This method works well any time you have client side caching as well.

public class ImageModel : List<Image>
{
    public ImageModel() : this(1, 10)
    {
    }

    private List<Image> GetAllImages()
    {
        string imagesDir = HttpContext.Current.Server.MapPath("~/images/");
        XDocument imageMetaData = XDocument.Load(imagesDir + @"/ImageMetaData.xml");
        var images = from image in imageMetaData.Descendants("image")
                     select new Image(image.Element("filename").Value,
                     image.Element("description").Value);
        
        TotalCount = images.Count<Image>();

        return images.ToList<Image>();
    }

    public int TotalCount { get; set; }
    public int CurrentPage { get; set; }
    public int PageSize { get; set; }
    public ImageModel(int pageNum, int pageSize)
    {
        CurrentPage = pageNum;
        PageSize = pageSize;

        var images = GetAllImages();

        this.AddRange(images.Skip((pageNum - 1) * 
            pageSize).Take(pageSize).ToList());
    }
}

Notice that I added a new constructor that takes as parameters page number and page size. This will allow us, from the controller, to control the action happening here. The next thing to notice is that the default constructor is now calling the new constructor passing in default parameters of 1 and 10. Notice that we’re starting with 1 instead of 0. This will make a ton more sense to the user and makes mapping the pages a lot simpler. Lastly, notice that we’re setting some parameters (TotalCount, CurrentPage and PageSize). We’ll use these in the view in a little bit.

If we run right now, we’ll only get the first 10 pictures. If you happen to be following along and coding this with me, go ahead and try it.

Adding the Custom Route

Next, we need to add a route to handle the page mechanism.

In the global.asax.cs file, in the method called RegisterRoutes add the following route.

routes.MapRoute(
    "ImagePaging",                                              // Route name
    "{controller}/Page{pagenumber}",                           // URL with parameters
    new { controller = "Home", action = "Page", pagenumber = "1" }  // Parameter defaults
);

Notice how the routes are built. It’s a series of url parts and named parameters. For example, the Page2 is going to pass in 2 as the selected pagenumber. We actually could have hard coded the whole path except for the page number.

Adding the Paging Action to the Controller

Now that we’ve got data routing to the an Action, we need to make sure that we’re handling it.

Turns out, this was the easiest piece of all.

public ActionResult Page(string pagenumber)
{
    ImageModel model = new ImageModel(int.Parse(pagenumber), 10);
    return View("index", model);
}

Notice that we are just creating the ImageModel leveraging our new constructor and passing it into a view. The view that we’re using is still the index view, which is the default. We don’t have to go build a new view for the paging, we just need to alter the data that we’re passing into our current view.

If you want, you can go test by browsing to /image/page2 and see what it shows.

Adding the Navigation Links

The last thing to do is to add the navigation links to the view. If you use the <% %> tags in any ASPX it runs on the server side. What this is actually doing is that the ASPX page is parsed and generated into code and compiled into a .NET assembly on the server side and the code inside the <% %> just gets copied into that generated code before it’s compiled. This means that the code that’s inside your brackets must match the language that you set at the top of the page.

<%if (ViewData.Model.TotalCount > ViewData.Model.PageSize){ %>
<div class="paging">
    <%if (ViewData.Model.CurrentPage > 1) { %>
        <%= Html.ActionLink("Back", 
"Page" +
(ViewData.Model.CurrentPage - 1).ToString(), "Image")%>&nbsp; <% }%> <%decimal numberOfPages =
decimal.Divide(ViewData.Model.TotalCount, ViewData.Model.PageSize); int lastPageNumber = (int)decimal.Ceiling(numberOfPages); for (int i = 1; i <= lastPageNumber; i++) { if (i != ViewData.Model.CurrentPage) { %> <%= Html.ActionLink(i.ToString(), "Page" + i.ToString(), "Image")%>&nbsp; <% } }%> <%if (ViewData.Model.CurrentPage < lastPageNumber) { %> <%= Html.ActionLink("Next",
"Page" + (ViewData.Model.CurrentPage + 1).ToString(), "Image")%> <% }%> <%=lastPageNumber%> </div> <% }%>

Notice that we’re using the properties set by back in the model here. There’s three different sections here. The first checks to see if we need a back button. The second loops over the pages and creates step links. And the third checks to see if we need a next button.

The navigation links in the view turned out to be the most complicated part of adding paging to the photo gallery.

Stay tuned to future posts for styling with CSS, adding a Silverlight front end and more.

Adding Lighbox.js to the Simple Photo Gallery

image In my previous two posts, Building a Simple Photo Gallery in ASP.NET MVC Framework and Returning Thumbnails With the MVC Framework, I built a simple photo gallery on the ASP.NET MVC framework. In this post we are going to start making this a little prettier. To start with, we are going to leverage an JavaScript project called Lightbox.js that’s released under the Creative Commons Attribution 2.5 License.

One cool part about it is that you can get a tremendous amount of functionality with little to no JavaScript coding on your own. It leverages a couple of different JavaScript libraries including Prototype and Scriptaculous. These do a lot of generic HTML Dom manipulation and visualization.

The result of leveraging Lightbox.js is that when you click on one of the thumbnails that we started showing in Returning Thumbnails With the MVC Framework the full sized picture will show in a really nice lightbox style effect.

First, you need to download the Lightbox.js project. It comes in a zip file that comes with a sample application. Unzip the contents into the appropriate folders. This means that the .js files go in your /scripts directors and the images and the css in the /content folder.

The cool part is that since you have the source to it all, rock on and modify it to your heart’s content. And we’re going to do a light modification right off the bat. We could have put the images from the Lightbox.js project in the /images folder but we’re already using that for something else so we put them in the /content folder. That means that you need to open up lightbox.js and change the directory of the loading and close images to point to the correct directory.

LightboxOptions = Object.extend({
    fileLoadingImage:        'content/loading.gif',
    fileBottomNavCloseImage: 'content/closelabel.gif',

That’s the only mod that we *need* to make at the moment. If you feel like it, you can fix the image paths in lighthouse.css as well.

#prevLink:hover, #prevLink:visited:hover { background: 
url(Content/prevlabel.gif) left 15% no-repeat; } #nextLink:hover, #nextLink:visited:hover { background:
url(Content/nextlabel.gif) right 15% no-repeat; }

The only thing left to do is update the Images/index view to take advantage of our new capabilities. There are two mods to make. First, we need to include links to the lightbox.css and the required 3 JavaScript files (prototype.js, scriptaculous.js and lighbox.js). Second, we need to add a rel=”lightbox” to the anchor tag around our picture.

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
AutoEventWireup="true" CodeBehind="Index.aspx.cs"
Inherits="PhotoGalleryMVC.Views.Image.Index" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <link rel="stylesheet" href="content/lightbox.css" type="text/css" media="screen" /> <script src="scripts/prototype.js" type="text/javascript"></script> <script src="scripts/scriptaculous.js?load=effects,builder" type="text/javascript"></script> <script src="scripts/lightbox.js" type="text/javascript"></script> <p><%= Html.ActionLink("Add your own image", "Upload", "Image")%></p> <% foreach (var image in ViewData.Model) { %> <span class="image"> <a href="/images/<%= image.Path %>" rel="lightbox">
<
img src="/image/thumbnail/<%= image.Path %>" />
</
a> <span class="description"><%= image.Description %></span> </span> <% }%> </asp:Content>

It’s that simple. This will render a really nice little lightbox effect on our images.

Stay tuned for future posts about styling the CSS, paging the pictures and a whole lot more.

Returning Thumbnails With the MVC Framework

In my last post, we put together a quick and simple photo gallery. This post will be building on that.

Depending on the size of your photo, however, it didn’t have the worlds greatest user experience. I’ll be playing with the CSS, JavaScript and a ton more over time. Today, however, I’m going to be just returning a thumbnail rather than the full picture to show in the view.

I don’t want to have to physically create each of the thumbnails so we’ll generate those dynamically on the fly.

Creating a Custom ActionResult

To return a given type of result, you have to return an ActionResult of that type. The types that are currently built in are View, Redirect, RedirectToAction, RedirectToRoute, Content, or Json. We need to create a specific action type that we’ll call the ThumbnailResult. It will be created with a virtual path to the picture that we need to show. When it’s executed, it will generate and return the thumbnail.

public class ThumbnailResult : ActionResult
{
    public ThumbnailResult(string virtualPath)
    {
        this.VirtualPath = virtualPath;
    }

    public string VirtualPath {get;set;}

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = "image/bmp";

        string fullFileName =
            context.HttpContext.Server.MapPath("~/images/" + VirtualPath);
        using (System.Drawing.Image photoImg =
            System.Drawing.Image.FromFile(fullFileName))
        {
            using (System.Drawing.Image thumbPhoto =
                photoImg.GetThumbnailImage(100, 100, null, new System.IntPtr()))
            {
                using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                {
                    thumbPhoto.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                    context.HttpContext.Response.BinaryWrite(ms.ToArray());
                    context.HttpContext.Response.End();
                }
            }
        }
    }
}

Notice that we’ve set the HttpContext.Response.ContentType to “image/bmp”. This is critical for the browser to understand the data that it recieves.

Leveraging the Custom ActionResult

The next step is to add a method to the controller that will return the ThumbnailResult.

public ActionResult Thumbnail(string id)
{
    return new ThumbnailResult(id);
}

And lastly we need to update the view to leverage this new thumbnail action.

<a href=”/images/<%= image.Path %>“><img src=”/image/thumbnail/<%= image.Path %>” /></a>

When you run now, you should get the thumbnails instead of the full sized picture. However, you should still be able to click through to the actual picture. In an upcoming blogpost, we’ll change this to use lightbox.js.

Building a Simple Photo Gallery in ASP.NET MVC Framework

image I decided to create a simple photo gallery in the ASP.NET MVC framework. The fun part is that this level of application is really the new “Hello World”. It takes less time to build than the “Hello World” did back in the day.

In this post, I’ll walk you through the process of creating this simple photo gallery with the MVC framework.

First, let’s talk a little about what the ASP.NET MVC framework is. It’s a web framework built on .NET with the principles of the MVC architecture behind it.

The MVC Architecture

MVC architecture divides the responsibilities of an application into three main components – models, views, and controllers.

image“Models” are responsible for the the data access. The data is often times in a database but it doesn’t have to be. The model could be over an XML file or whatever other data store that you happen to use. By default the ASP.NET MVC framework uses the Entity Framework. However, it can work with any data access type that returns a set of objects that the view can access. Most of the time, this will be an ORM such as the Entity Framework, NHibernate or SubSonic. In our demo below we’re actually going to just be reading in an XML file from the disk.

“Views” are responsible for the actual user interface. Typically this is HTML but it could be XML, JSON or any other number types of display/service response. Most of the time, these displays/responses are built based on model data.

“Controllers” are responsible for the actual logic. It handles the end user interaction, manipulates the data in the model and decides which view to return to the user. Simple enough? 

Creating the ASP.NET MVC Framework Project

image I started out creating an ASP.NET MVC Web Application called PhotoGalleryMVC. There are a couple of very important things to notice in an ASP.NET MVC framework project.

First, look at the Global.asax and it’s code behind. It’s got a really important method called RegisterRoutes where you define your routes.

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

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

}

These routes define what happens when your application receives a request. The controller is a class and the action is a method on that class. The parts after that are parameters to the method. We’ll see more with this in a few moments.

The next thing is to notice the controllers. The default method that you get in the helper class is as follows:

public ActionResult Index()
{
    ViewData["Title"] = "Home Page";
    ViewData["Message"] = "Welcome to ASP.NET MVC!";

    return View();
}

This is the default action for the controller. It’s simply setting some properties on the View and then returning it. Notice that we’re not instantiating a copy of the view and setting properties directly on it. Instead, we’re staying with the very loosely coupled method of using a ViewDataDictionary called ViewData. This is a dictionary of items that both the view and the controller have access to.

Creating the ImageModel

The first thing I want to create is a way to get the images in the first place. Rather than creating a database, we’re going to simply use an XML file as our storage for our information about our images.

Create a folder called Images under the root of the project. This will be where we put the images.

As a file ImagesMetaData.xml in the images directory following the format below. Feel free to substitute your own data in for the data I have below…

<?xml version="1.0" encoding="utf-8" ?>
<images>
  <image>
    <filename>IMG_3717.JPG</filename>
    <description>Paul playing Guitar Hero.</description>
  </image>
  <image>
    <filename>IMG_3720.JPG</filename>
    <description>Phizzpop Signin.</description>
  </image>
</images>

Add a class called Image under the model folder. For now this will be really simple.

namespace PhotoGalleryMVC.Models
{
    public class Image
    {
        public Image(string path, string description)
        {
            Path = path;
            Description = description;
        }
        public string Path { get; set; }
        public string Description { get; set; }
    }
}

All this class provides for now is a holder for the image path and description. We’ll do more with this class in the future.

The next thing that we need to do is create a way to get those images from the disk. This will be in a class called ImageModel. To make this really simple, we will inherit from a generic list of Image. This gives us a lot of functionality already. What we need to add is a constructor that will retrieve the images from the disk.

namespace PhotoGalleryMVC.Models
{
    public class ImageModel : List<Image>
    {
        public ImageModel()
        {
            string imagesDir = HttpContext.Current.Server.MapPath("~/images/");
            XDocument imageMetaData = XDocument.Load(imagesDir + @"/ImageMetaData.xml");
            var images = from image in imageMetaData.Descendants("image")
                         select new Image(image.Element("filename").Value,
                         image.Element("description").Value);
            this.AddRange(images.ToList<Image>());
        }
    }
}

All this model is doing is reading in the XML file and creating a list of images based on that metadata.

Creating the Controller

The next step is to create the controller. Again, for the moment, this will be extremely simple. We’ll do more with it in the future.

namespace PhotoGalleryMVC.Controllers
{
    public class ImageController : Controller
   
{
        public ActionResult Index()
        {
            return View(new ImageModel());
        }
    }
}

Notice that this is slightly different than the default controller as it’s passing in the ImageModel. We’ll have to create the View to accept it here in just a moment.

Creating the View

Now we need to add a folder to the hold our images view in the Views folder. Now to create the view in the Images view folder, right-click on the folder and select Add View. Name the view Index.

Now that we have our view, modify it’s declaration to accept the ImageModel class.

namespace PhotoGalleryMVC.Views.Image
{
    public partial class Index : ViewPage<ImageModel>
    {
    }
}

What this does is set up our view based on a generic ViewPage with ImageModel as it’s base.

And lastly we need to add the HTMLish stuff to do the actual display.

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
AutoEventWireup="true" CodeBehind="Index.aspx.cs"
Inherits="PhotoGalleryMVC.Views.Image.Index" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <% foreach (var image in ViewData.Model) { %> <span class="image"> <a href="images/<%= image.Path %>"><img src="images/<%= image.Path %>" /></a> <span class="description"><%= image.Description %></span> </span> <% }%> </asp:Content>

If you’ve ever done ASP Classic or PHP, this HTMLish stuff shouldn’t look too odd. If you strip out the HTML code, you’ve got a normal foreach loop written in C#. The bad news about this approach is that there’s a lot less controls, such as the datagrid and such, available to you. The good news is that you’ve got absolute control over the HTML that is produced.

You should notice, however, that we’re able to leverage master pages as we do in ASP.NET 2. This is great because it allows us to define our look and feel in a master page. There’s a great amount of flexibility and power in that.

Last step is that we need to add a tab on the main navigation to get to the images page. We do that in the /views/shared/site.master

<ul id="menu">
    <li><%= Html.ActionLink("Home", "Index", "Home")%></li>
    <li><%= Html.ActionLink("Images", "Index", "Image")%></li>
    <li><%= Html.ActionLink("About Us", "About", "Home")%></li>
</ul>

Even though we’ve got few controls at out disposal, there are some interesting helpers such as this Html.ActionLink. This returns a link that points to the appropriate controller and action without us having to divine what that link should be based on the current routes. 

At this point, the application runs and shows really big pictures (assuming that you’ve put a few in the images folder in the first place).

Adding a New Picture

Now that we’ve got a few manually placed a few of the pictures in the folders and gotten them to display on the view, we need a way for the user to add their own pictures to the site. We’re going to do this one in reverse order where we create the view and work backwards from there.

Step one is that we need a new view and a way to get to it from the images page. We can accomplish that with a simple Html.ActionLink in the Image Index view.

    <p><%= Html.ActionLink("Add your own image", "Upload", "Image")%></p>

Now we need to create the view for the New action. Simply right click on the View folder and select Add|View. Name this view “Upload”.

In the view, we need to create a form that will do the post.

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
AutoEventWireup="true" CodeBehind="Upload.aspx.cs"
Inherits="PhotoGalleryMVC.Views.Image.Upload" %>

<asp:ContentID=”Content1″ContentPlaceHolderID=”MainContent”runat=”server”>
<
form method=”post” action=”<%=Url.Action(“save”) %>enctype=”multipart/form-data”>
    <
input type=”file” name=”file” />
    <input type=”submit” value=”submit” /> <br />
    <input type=”text” name=”description” />
</form>
</
asp:Content>

It’s not the world’s prettiest form but it’s functional. Notice the action on the form tag. It’s using another helper called Url.Action. This maps to the same controller but a different action.

Now we need to add the upload and save action to the controller. The Upload action is very simple. It simply returns the Upload view. The Save is a little more complicated as it has to do the actual logic of getting the files and descriptions and putting those on the model.

namespace PhotoGalleryMVC.Controllers
{
    public class ImageController : Controller
    {
        public ActionResult Index()
        {
            return View(new ImageModel());
        }

        public ActionResult Upload()
        {
            return View();
        }

        public ActionResult Save()
        {
            foreach (string name in Request.Files)
            {
                var file = Request.Files[name];

                string fileName = System.IO.Path.GetFileName(file.FileName);
                Image image = new Image(fileName, Request["description"]);

                ImageModel model = new ImageModel();
                model.Add(image, file);
            }
            return RedirectToAction("index");
        }
    }
}

The important part here is that this controller is not actually doing the logic of saving out to the disk. This is important because it gives us the flexibility to alter the model switch from file based storage to a database and so on. This separation is key to the success of the architecture.

Last thing to do is alter the model to actually save out to the disk.

public void Add(Image image, HttpPostedFileBase file)
{
    string imagesDir = HttpContext.Current.Server.MapPath("~/images/");
    file.SaveAs(imagesDir + image.Path);

    this.Add(image);
    XElement xml = new XElement("images",
            from i in this
            orderby image.Path
            select new XElement("image",
                      new XElement("filename", i.Path),
                      new XElement("description", i.Description))
            );

    XDocument doc = new XDocument(xml);

    doc.Save(imagesDir + "/ImageMetaData.xml");
}

The LINQ makes creating the XML document really simple.

There are a lot of optimizations that could be done here such as storing off the model in memory and the like so that we’re not constantly reading/writing to the disk and the like. That’s not the point of this exercise. The point here is to work with the MVC framework.

At this point we’ve got a functioning image gallery with uploads and a view.

In my next post, I’ll alter this to serve up thumbnails and give a nicer user experience.

Ann Arbor Day of .Net

Wow I’ve been swamped. There’s so much to blog about in the past couple of weeks so I’m just going to catch some of the highlights.

Ann Arbor Day of .NET was on 5/5/2007. It was fantastic! It sold out at 250 people and of that there were 210 people show up. That’s actually really good as most free events have a 40% droppoff and they had less than 20% droppoff. The only downside on the day was that with less than a 20% droppoff – pizza was a little short at lunch.

They are actually thinking about going to every 6 months instead of every 12 months. I think this would be fantastic!

I kicked off the day with a session on User Experience technologies at Microsoft. I borrowed from some of the materials that we are putting together for the upcoming ArcReady (Check the site for dates and times across the entire central region – Detroit on 5/25 in two weeks for all those that attended Day of .Net). We dipped into WPF, AJAX and Silverlight. My favorite demo is the Silverlight Airlines Demo. It shows a truly out of the box user experience that’s not all glitz and glammor but a truly solid UI for a true business application. Many of the demos, while showing off the platform really well, are marketing apps that show lots of 3D and animation. My customers often look at the glitzy demos and say that they are not doing 3D so they don’t look at the technologies. What they are missing is that there are real benifits here with enabling truly rich interfaces that go well beyond text and pictures.

I had two more 30 minute sessions. In both of those sessions the overwhelming requests were to have more Silverlight content. I had nothing prepared for these sessions but they went really well. In the first session, I pulled Don Burnett, who started Michigan Interactive Designers, out of the crowd and asked him to do a tour around Expression Blend and Silverlight. He got up, completely unscripted, and did a fantastic job! I will definitely be bringing him in to do more demos and presentations – especially when we have a designer based crowd. It turns out that he used to work with Bill Wagner (my former business partner when I was at SRT Solutions) on the Lion King Animated Storybook.

In the second session, I was on my own but I showed Top Banana, the DLRConsole (python and javascript version – IronRuby will be released as a CTP from CodePlex later this year) and talked about the .NET support in Silverlight 1.1 Alpha. Yes – I actually wrote some Python and did a simple overview for people at the conference. It was a fun day!

Here are some of the resources that we talked about during the three talks:

•Windows Forms @ .NET FX Developer Center
http://windowsclient.net

•WPF @ MSDN Developer Center
http://msdn.microsoft.com/winfx/reference/presentation/default.aspx

•.NET 3.0 (WPF, WCF, WF) Community Site
http://windowsclient.net/

•Silverlight
http://www.silverlight.net

•ASP.NET AJAX @ ASP.NET Developer Center
http://msdn.microsoft.com/winfx/reference/presentation/default.aspx

•ASP.NET AJAX Community Site
http://ajax.asp.net/

•DirectX @ DirectX Development Center
http://msdn.microsoft.com/directx/

•Microsoft Visual Studio @ Visual Studio Developer Center
http://msdn.microsoft.com/vstudio/

•Microsoft Expression
www.microsoft.com/expression

 

Day of .NET site

Link to Day of .Net in Ann Arbor 2007 – Home

Don Burnett’s write-up of the event.

Link to Don.NET’s WPF Designers Blog: Eastern Michigan Day of Dot Net

 

Playing with JSON

Silverlight Plasma ReactorI was asked on Friday by a friend how one can consume JSON in Silverlight. At the time, I just said start with the System.Json namespace and I’ll get you a sample later. Well, here’s a sample and a peek into my head because I couldn’t just stop with creating the sample that he needed.

Download Solution – PlayingWithJSON.zip

*Update – gotta do a quick shoutout to Leon Gersing for his passionate defense of JavaScript and JSON. It’s part of what inspired me to spend as much time on this as I did.

Really short JSON overview

JSON, for those of you who don’t know, is a really simple data format heavily used with JavaScript. It’s a lot smaller and lighter than XML.

This is the JSON that I’m using in this example. As you can see, it’s just name/value pairs with a little bit of extra formatting. Curly Braces separate objects in a list. Commas separate values. Colons separate the names from the values. 

[
{“FirstName”:”Etta”,”LastName”:”James”,”Url”:”http:\/\/www.etta-james.com\/”},{“FirstName”:”Billie”,”LastName”:”Holiday”,”Url”:”http:\/\/www.billie-holiday.net\/”},{“FirstName”:”Ella”,”LastName”:”Fitzgerald”,”Url”:”http:\/\/en.wikipedia.org\/wiki\/Ella_Fitzgerald”}]
}

Creating the JSON service with ASP.NET MVC Framework

The first thing that I did was slap together an ASP.NET MVC Framework application to produce the JSON and host the Silverlight application. This was remarkably easy. I decided against going through the effort of creating a database because that’s not really the point of the exercise.

I created a simple class that to fill out and serialize and then returned it from a controller.

public class Artist
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Url { get; set; }
}

The next step was to create a simple controller that would return my list as JSON. As you can see, there’s a JsonResult that you can return right from a controller method.

public class ArtistsController : Controller
{
    public JsonResult GetAll()
    {
        List<Artist> artists = new List<Artist>();

        artists.Add(new Artist("Etta", "James", "http://www.etta-james.com/"));
        artists.Add(new Artist("Billie", "Holiday", "http://www.billie-holiday.net/"));
        artists.Add(new Artist("Ella", "Fitzgerald", "http://en.wikipedia.org/wiki/Ella_Fitzgerald"));

        return Json(artists);
    }
}

To test it, I just browsed to http://localhost:mylocalport/artists/getall. That returned the JSON file. As the browser doesn’t display JSON auto-magically, it prompted me to download a file and save it off.

Now, take notice of the URL. The ASP.NET MVC Framework is producing what’s called a RESTful Service. The parameters and all are simply in the URL. In the URL, “artists” takes us to a particular Controller called the ArtistsController and the “getall” calls the “GetAll()” method on that controller. We can further specify parameters and the like in the URL. Scott Guthrie has a great article that explains the URL routing and all at http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx.

Now that we are producing JSON from a services, we are ready to create a client.

Getting the JSON from the RESTful service.

The first client that I tried was the straight up System.Json namespace client. Since we are using a RESTful service, we can’t generate the proxy object in the same way that we’re used to with SOAP. Instead, we need to leverage the WebClient object.  This is done as follows:

void mainButton_Click(object sender, RoutedEventArgs e)
{
    Uri serviceUri = new Uri("/Artists/GetAll", UriKind.Relative);
    WebClient downloader = new WebClient();
    downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(downloader_OpenReadCompleted);
    downloader.OpenReadAsync(serviceUri);
}

Notice that the URL that I’m using is relative. You can specify the full URL if the service is not on your own server. These calls, as all calls in Silverlight, are async. Therefore I wire up the downloader_OpenReadCompleted event and call OpenReadAsync. Simple enough?

Leveraging System.Json

Once the downloader returns, I can get the result off of the event arguments. Load is a static method on the JsonArray that will automatically parse out the results from the stream object. Then, I can just loop over the objects in the array and use them to fill out my own type that I’m ready to databind to.

void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    JsonArray jsonArray = (JsonArray)JsonArray.Load(e.Result);

    List<Artist> artists = new List<Artist>();

    foreach (JsonObject jsonArtist in jsonArray)
    {
        Artist artist = new Artist();
        artist.FirstName = jsonArtist["FirstName"];
        artist.LastName = jsonArtist["LastName"];
        artist.Url = jsonArtist["Url"];

        artists.Add(artist);
    }

    dataGrid1.ItemsSource = artists;
}

This was fairly straight forward and simple, but I wasn’t ready to be done yet.

Leveraging LINQ

The next thing is to try LINQ against this JsonArray and see what happens.

void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    JsonArray jsonArray = (JsonArray)JsonArray.Load(e.Result);

    var query = from artist in jsonArray
                select new Artist
                {
                    FirstName = (string)artist["FirstName"],
                    LastName = (string)artist["LastName"],
                    Url = (string)artist["Url"],
                };

    List<Artist> artists = query.ToList() as List<Artist>;
    dataGrid1.ItemsSource = artists;
}

Personally, I think that the LINQ version is a lot more powerful. It’s not immediately obvious in this simple example but there’s a ton that I could do with the LINQ query from filling out sub-types to filtering and so on.

JSON in JavaScript

JavaScript ReferenceBut then I started thinking about all of the different ways that one can get and parse out JSON directly in JavaScript (I mean it does have JavaScript right in the name).

First, I did it the old school way that I used to do back when I was doing a ton of JavaScript development.

Quick note here – before you start copying this code – this is NOT the way to do this in the modern era. I did it to prove a point. You really need to be leveraging one of the many great JavaScript frameworks that are out there in order to accomplish your JavaScript today. I’ll get to those in a minute.

Short version, you’re going to be doing an XMLHttpRequest directly. When that returns you’ll get an “onreadystatechange” event which you can respond to. If it’s actually ready, then you can call a JavaScript function called eval that will return and array of objects parsed out from the string that you pass in.

<script language="javascript" type="text/javascript">
    function GetJson(url) {
        // Create xmlhttprequest object
        var xmlhttp = null;
        if (window.XMLHttpRequest) {
            xmlhttp = new XMLHttpRequest();
            //make sure that Browser supports overrideMimeType
            if (typeof xmlhttp.overrideMimeType != 'undefined') {
                xmlhttp.overrideMimeType('text/xml');
            }
        }
        else if (window.ActiveXObject) {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        else {
            alert('Perhaps your browser does not support xmlhttprequests?');
        }

        // Create an HTTP GET request
        xmlhttp.open('GET', url, true);

        // Set the callback function
        xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                var json = xmlhttp.responseText;

                var artists = eval(json);

                var newArtistList;
                newArtistList = "<ul>";

                for (var i in artists) {
                    var artist = artists[i];
                    newArtistList += "<li>"
                    + artist.FirstName + " "
                    + artist.LastName
                    + "</li>"
                }

                newArtistList += "<ul>";

                outputControl = document.getElementById("divOutput");
                outputControl.innerHTML = newArtistList;
            } else {
                // waiting for the call to complete
            }
        };

        // Make the actual request
        xmlhttp.send(null);
    }
</script>

Alright, that’s a lot of JavaScript to get through and understand. There are multiple possible problems here. First, that’s just a ton of code. Second, the same eval function that you are calling here is the same eval function used to dynamically execute a piece of JavaScript in a string. This means that you’re open to all kinds of possible attacks. Finally, there are a ton of frameworks that have come up in the past handful of years.

So, let’s go look at some of those frameworks.

Leveraging MS AJAX

The AJAX framework that I’ve been trying to learn lately is the MS AJAX one. It’s got a lot of power. First, notice that the WebRequest actually looks a lot like what I did in C#. Next, notice the JavaScriptSerializer object. This gives me some nice and easy serialization to and from JSON. The reason to use this is that it’s a much safer mechanism than eval. Lastly, notice the $get at the end. This is a nice and easy selector that does all of the heavy lifting of finding the object in the DOM and the like.

<script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
    function GetJson() {
        var request = new Sys.Net.WebRequest();
        request.get_headers()['Content-Type'] = 'application/json; charset=utf-8';
        request.set_url('/Artists/GetAll');

        request.add_completed(Function.createDelegate(null, DisplayArtists));
        request.invoke();
    }

    function DisplayArtists(executor) {
        if (executor.get_responseAvailable()) {
            var json = executor.get_responseData();
            var artists = Sys.Serialization.JavaScriptSerializer.deserialize(json);

            var newArtistList;
            newArtistList = "<ul>";

            for (var i in artists) {
                var artist = artists[i];
                newArtistList += "<li>"
                + artist.FirstName + " "
                + artist.LastName
                + "</li>"
            }

            newArtistList += "<ul>";

            $get("divOutput").innerHTML = newArtistList;
        }
    }
</script>

This is a lot less code and a lot safer than what I was doing in raw JavaScript. However, I thought I should try this with a few more frameworks.

Leveraging Prototype

image A framework that I’ve used for a while and really like is Prototype.

This is a whole lot less code. Notice the “Ajax.Request”. That packages up all of the work of doing the network call behind one simple to use function. And on the response is a nice and easy method called evalJSON that will parse out the JSON string to an array of objects that you can loop over. Finally, notice the $() selector.

<script src="../../Scripts/prototype-1.6.0.2.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
    function GetJson() {
        new Ajax.Request('/Artists/GetAll', {
            method: 'get',
            onSuccess: DisplayArtists
        })
      }

      function DisplayArtists(transport) {
        var json = transport.responseText.evalJSON();
        var newArtistList;
        newArtistList = "<ul>";

        json.each(function(artist) {
            newArtistList += "<li>"
                    + artist.FirstName + " "
                    + artist.LastName
                    + "</li>"
        });

        newArtistList += "<ul>";

        $("divOutput").insert(newArtistList);
    }
</script>

I liked this a lot. A feature that I didn’t take advantage of is that Scriptaculous, which is a fantastic set of JavaScript libraries for visualization, weaves in with Prototype really easily.

Leveraging jQuery

image The last JavaScript framework that I tried was jQuery. One extra cool part about this one for me is that I get intellisense right in Visual Studio. Check out Scott Guthrie’s post on jQuery Intellisense in VS2008 to see how to enable it.

Notice that it’s got the same type of easy to use function that packages up the call to get the JSON. Since it knows that it’s JSON, the variable returned to the callback is already parsed out into a usable object. And lastly, notice the $() selector again. There is a subtle difference between this one and the Prototype selector in that the jQuery one uses a # to signify that it’s looking for an ID, . to signify objects with a given class and so on.

<script language="javascript" type="text/javascript">
    function GetJson() {
        $.getJSON("/Artists/GetAll",
          {},
          DisplayArtists);
      }

      function DisplayArtists(data) {
          var newArtistList;
        newArtistList = "<ul>";

        for(var i = 0; i < data.length;i++)
        {
            var artist = data[i];
            newArtistList += "<li>"
                + artist.FirstName + " "
                + artist.LastName
                + "</li>"
        }

        newArtistList += "<ul>";

        $("#divOutput").html(newArtistList);
    }
</script>

Now that I was done playing with different JavaScript libraries, I thought I’d see if I could piece it all back together.

Leveraging jQuery and Silverlight

I decided to try jQuery and Silverlight together, leveraging jQuery to get and parse the JSON and Silverlight to do the display. This turned out to be remarkably simple.

First, in order for Silverlight to call into the JavaScript, you just have to call HtmlPage.Window.Invoke. That dynamically looks up and executes the method named in the first parameter.

void mainButton_Click(object sender, RoutedEventArgs e)
{
    HtmlPage.Window.Invoke("GetJson", "/Artists/GetAll");
}

Now, I could have wired up the JavaScript to listen for the button click event directly but that’s a lot more code than what I’ve got here.

Next I had to enable the Silverlight objects for callbacks. Step 1 is to Register the class with the browser’s scripting engine.

public LeveragingJQuery()
{
    InitializeComponent();
    HtmlPage.RegisterScriptableObject("LeveragingJQuery", this);
...
}

Step 2 is to declare one of the methods as a ScriptableMember. This gives the scripting engine access to the method in question. There’s also ScriptableType for creating serializable objects but that’s not what we need here. Notice, however, that the object type passed in is a ScriptObject. The slick part about this object is that it’s got a “ConvertTo” method that will take the weakly typed objects that it contains and serialize them to the type of object that you specify. This made the C# code here REALLY simple.

[ScriptableMember]
public void CallBackFromJavaScript(ScriptObject artists)
{
    List<Artist> listofartists = artists.ConvertTo<List<Artist>>();
    dataGrid1.ItemsSource = listofartists;
}

What’s left is the JQuery in the browser that we’re talking to. Notice that the first part is exactly the same. The second part, however, is a little different. First, we have to get a reference to the Silverlight plugin itself. Since I’m in a form object, ASP.NET mangles the name a little bit but it wasn’t too hard to figure out the new name. Next, I have to get the object that I had registered with the RegisterScriptableObject method. Then, all that’s left is calling the method to pass in my array of Artists.

<script src="/Scripts/jquery-1.2.6.js" type="text/javascript"></script>
<script language="javascript" type="text/javascript">
    function GetJson(url) {
        $.getJSON(url,
          {},
          DisplayArtists);
    }

    function DisplayArtists(artists) {
        var control = document.getElementById("ctl00_MainContent_SilverlightPlugin");
        var leveragingJSPage = control.Content.LeveragingJQuery;
        leveragingJSPage.CallBackFromJavaScript(artists);
    }
</script>

Conclusion

This is how I learn about new things. I’m not satisfied with just getting the job done in one and only one way. I want to try out 3, 4, 5 different ways to accomplish a given task. That way I know what the right way to do something is in a given context. For example, I don’t know that I’ll ever need to mingle jQuery and Silverlight. But, I know how it’s done now and know that it’s a lot simpler than I originally thought it would be.

JSON is a simple but powerful format. There are a ton of simple services, from flickr to twitter to many of your production applications that could be producing JSON. It saves bandwidth compared to XML and is a just as simple to use.