Friday, October 31, 2008

I've got an admission to make: I've never used any of the Microsoft Ajax Toolkit. But recently I've been adding some mapping functionality to the project I'm working on. We wanted users to be able to pull a marker to a position on a map and have the new position updated on the server. Obviously we were going to have to use Ajax of some kind to do that. What I want to show today is how trivially easy it's proved to be to use MVC Framework on the server and jQuery on the browser to do Ajax requests and updates. JQuery is now included in the default project for the MVC Framework, so there's no excuse not to use it.

Here's a very simple scenario. I've got a a page where I want to show a list of people when I click 'Get People'. I also want to add a person to the database when I type their name into a text box and click 'Add Person'. Here's what it looks like:

The first thing we do is create the button for 'Get People' and an unordered list to put the people in:

<inputtype="button"id="getPeople"value="Get People"/>

<ulid="people_list">

Next we have a jQuery ready handler (which fires when the page loads) that sets up the event handler for the getPeople button:

$(function() {

$("#getPeople").click(function() {

$.getJSON("/Home/People", null, getPeople);

});

});

When the button is clicked we fire off a json request to /Home/People. This maps to a People action in our Home controller:

[AcceptVerbs(HttpVerbs.Get)]

public ActionResult People()

{

var db = new DataClasses1DataContext();

return Json(db.Persons);

}

All we do here is get all our Person records (using LINQ to SQL) and return them as Json. When the response is returned to the browser the getPeople callback function is called. Remember we set this in the getJSON jQuery method above. Here's the getPeople function:

function getPeople(people) {

$("#people_list").text("");

$.each(people, function(i) {

$("#people_list").append("<li>" + this.Name + "</li>");

});

}

The callback provides the data returned from the JSON request as its argument. All we have to do is use the handy jQuery each function to iterate through our people collection and append a new li element to our list for each one. The really nice thing here is how well the MVC Framework and jQuery interact. I didn't have to do any conversions between them. Our data just automagically converts from C# objects to Javascript.

How about the update? This is just as simple. First we need some more HTML: a text box to type the name into and a button to fire the update:

<label>Name <inputtype="text"id="name"/></label><br/>

<inputtype="button"id="addPerson"value="Add Person"/>

Next another click event handler is set up to handle the addPerson click event:

$("#addPerson").click(function() {

varname = $("#name")[0].value;

if (name == "") {

alert("You must provide a name");

return;

}

var person = { Name: name };

$.post("/Home/People", person, null, "json");

});

This time we use the useful 'post' function to post our newly created person JSON object to the /Home/People URL. Because this is a POST request it's handled by our overloaded People action, this time attributed with AcceptVerbs[HttpVerbs.Post]:

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult People(string Name)

{

var db = new DataClasses1DataContext();

var person = new Person {Name = Name};

db.Persons.InsertOnSubmit(person);

db.SubmitChanges();

returnnull;

}

All we have to do to retrieve the Name of the person is to name the argument of the action 'Name'. The MVC Framework automatically pulls apart the request, finds a value called 'Name' and supplies it to the action. If you have a complex JSON structure you can deserialize it to a C# object using the built in data binding. All that's left to do is create a new Person instance with the given name and save it to the database. Nice!

I'm a latecomer to the Ajax party, but with jQuery and the MVC Framework I'm finding a breeze to wire up some pretty nice functionality.

Thursday, October 30, 2008

So C# 4.0 is finally with us (in CTP form anyway). I've just been watching Ander's PDC presentation, The Future of C#. The main focus is providing interop with dynamic languages and COM, so in order to do that they've added some dynamic goodness in C# itself. There's a new static type called dynamic :) Yes, it's the number one joke at PDC it seems. The dynamic keyword allows us to say to the compiler, "don't worry what I'm doing with this type, we're going to dispatch it at runtime".

OK, so we've got a little console application. I've defined a method, DoSomethingDynamic, which has a parameter, 'thing', of type dynamic. We call the Act() method of thing. This is duck typing. The compiler can't check that thing has an Act method until runtime, so we're going to wrap it in a try-catch block just in case it doesn't. A side effect of duck typing is that there's no intellisense for the thing variable, we can write whatever we like against it and it will compile. Any of these would compile: thing.Foo(), thing + 56, thing.X = "hello", var y = thing[12].

Next, in the Main method, we call DoSomethingDynamic a few times, passing in different kinds of arguments. First we pass in the literal 7. Int32 doesn't have an Act method so a RuntimeBinderException is thrown. Next we pass an instance of a normal C# class, Actor. Actor has an Act method so Act is called normally as expected.The last invocation of DoSomethingDynamic shows off how you can do dynamic dispatch in C# 4.0. We define a new class called DynamicThing and have it inherit IDynamicObject. IDynamicObject has a single method you must implement: GetMetaObject. GetMetaObject returns a MetaObject and all you have to do is implement a CustomMetaObject that knows what to do with any method (or parameter, or indexer etc) invocation. Our CustomMetaObject overrides Call and simply writes the name of the method to the console.
Chris Burrows from the C# compiler team has a series of three blog posts showing off these techniques here, here and here.
Anders' PDC presentation, The Future of C# is here. C# is primarily a statically typed language and Anders obviously still believes that static typing is a better paradigm for large scale software. He sees the dynamic features as a way of adding capabilities to C# that have previously been the prerogative of VB and dynamic languages. He's especially contrite about the failure of C# to interoperate with COM efficiently in the past. However there are going to be lots of cases when using dynamic will be a short cut to features that are hard to implement statically. I can see the C# forums humming with complaints that intellisense doesn't work anymore, or hard to diagnose runtime errors as a result of over zealous dynamism.

The last ten minutes of the talk, when he showed us some of the post 4.0 features, was very cool. They are rewriting the C# compiler in C#. This means that the compiler API will be just another library in the framework. Applications will be able to call compiler services at runtime giving us lots of Ruby style meta-programming goodness. Tools will be able to read the C# AST, giving us incredible power for refactoring or post compilation style tweeks.

Tuesday, October 21, 2008

A tree view is a wonderful way to present nested data structures or trees. Here's an example:

I've written an HTML helper that presents tree structures as nested unordered lists in HTML. First I've got an interface to represent a tree node. It's called IComposite after the GoF pattern.

publicinterface IComposite<T>

{

T Parent { get; }

ISet<T> Children { get; }

}

Now we just need to make sure that our entity implements this interface. Here's a simple example, CompositeThing:

publicclass CompositeThing : IComposite<CompositeThing>

{

public CompositeThing()

{

Children = new HashedSet<CompositeThing>();

}

publicstring Name { get; set; }

public CompositeThing Parent { get; set; }

public ISet<CompositeThing> Children { get; set; }

}

Now all we need to do is get the object graph from the database. Techniques for doing that are the subject for another post, but it's pretty straight forward with both LINQ-to-SQL and NHibernate. Once we have the graph we can pass it to our view and display it like this:

Monday, October 20, 2008

The legacy application I'm currently replacing features multiple databases for some insane reason. Luckily it's quite easy to get NHibernate to do joins across databases so long as they are on the same server. The technique is detailed by Hector Cruz in this thread on the NHibernate forum. The trick is to specify the schema you are addressing in each mapping file. Because the schema name simply becomes a table prefix, you can also use it to specify cross database joins. So long as you follow good practice and have one mapping file per entity, it means that, in theory, each entity could be persisted to a different database. I've put together a little project to show this working using Northwind. You can download the code here:

I took a backup of Northwind and then restored it to a new database so that I had a Northwind and a Northwind2. I'm going to get the Product entity from the Products table on Northwind and the Supplier from the Suppliers table in Northwind2. The great thing is that you only need a single connection string pointing to one database (in my case the original Northwind).

As you can see the Product was retrieved from Northwind and the Supplier from Northwind2. It's similar to when you do cross database joins in a stored procedure. The stored procedure has to live in a particular database, but because each table gets prefixed with it's database name the DBMS simply looks up the table in the referenced database.

Note that this trick is simply to deal with a legacy situation that I can't do much about. You really don't want to architect a system like this from scratch.

It puts the MVC assemblies in the GAC when you run the installer. This means that they won't be copied to your bin directory by default. Beware of this if you are expecting to deploy your application to a non-MVC installed server.

It doesn't include the 'futures' assembly Microsoft.Web.Mvc. You have to download this separately from the Codeplex project site.

There are a number of other small (some breaking changes) so be sure to checkout the release notes.

Wednesday, October 15, 2008

A couple of weeks ago I blogged about the common service locator that had just been announced by the Microsoft Patterns and Practices team. I've just updated our current application to use it. Here is what you need to do:

First, download the the binaries from codeplex. You can also get the code and build it yourself. You then need to add the Microsoft.Practices.ServiceLocation assembly to your project.

If, like me, you're using Castle Windsor you should download the code for the Castle Windsor Adaptor. This includes a file called WindsorServiceLocator.cs that you can add to your project. If you are using another IoC container, check the main page of the common service locator codeplex project for the relevant adaptor.

In your application startup code (Global.asax.cs Application_Start() for examle), register the WindsorServiceLocator with the ServiceLocator:

And there's no direct dependency on Windsor so you can swap in StructureMap, AutoFac, Unity or whatever when the mood takes you.

Now there's a big big caveat with this. You should really only use the static service locator when dependency injection (DI) is not an option. In an MVC Framework application you will typically provide a ControllerFactory that gets controller instances from the IoC container. Every further dependency in the object graph that handles the request should be provided by DI. Even when you need to defer service location, the abstract factory pattern is a better choice than ServiceLocator.

The next thing that needs to happen is for ServiceLocator to be fully leveraged by the MVC Framework code. At the moment you have to use the MvcContrib WindsorControllerFactory, or write your own controller factory. It would be very nice if simply calling SetLocationProvider did the same thing.

Thursday, October 09, 2008

For the last week or so I've been having a lot fun at work adding some Google map functionality to our application. It's an internal application for my clients, so I can't show you any of the code, but I've put together a little demo to demonstrate some of the techniques. The core message here is that it's easy. Taking a some geographic information from your model and putting some markers on a google map with a bit of interactive functionality is really only a matter of a few lines of code. You can download a zip file of the solution here:

Here's the application. It's pretty simple, it just displays a map with a collection of locations. For fun I've made it show some of the places I've been lucky enough to live in during my fun-packed life :) Each location has a latitude, longitude, name and an image. You can click on the marker for a location and its name is displayed in a speech bubble (known as an 'info window' by Google) and it's image is displayed to the right of the map.

I build the map object graph in memory with a simple 'repository' (this is just a demo, your repository would normally talk to a database).

using Mike.GoogleMaps.Models;

namespace Mike.GoogleMaps.Repositories

{

publicclass MapRepository

{

public Map GetById(int id)

{

returnnew Map

{

Name = "Places Mike has lived",

Zoom = 1,

LatLng = new LatLng { Latitude = 0.0, Longitude = 0.0, },

Locations =

{

new Location

{

Name = "St. Julians, Sevenoaks, UK",

LatLng = new LatLng { Latitude = 51.25136, Longitude = 0.21992 },

Image = "st_julians.jpg"

},

new Location

{

Name = "Kadasali, Gujerat, India",

LatLng = new LatLng { Latitude = 21.235142, Longitude = 71.4462 },

Image = "india.jpg"

},

// ...

}

};

}

}

}

Next we have a controller action that returns the object graph serialized as JSON:

public ActionResult Map()

{

var mapRepository = new MapRepository();

var map = mapRepository.GetById(1);

return Json(map);

}

On the home controller's index view we have some simple HTML that has div placeholders for the content. One for the map name, another for the map itself and two more for the dynamic location name and image. Please forgive the inline CSS :(

Note that this is the HTML as rendered and is a combination of the master view and the home controller's index view. Also note the script references for the Google maps API, jQuery and the LocationMap.js script which controls the page.

jQuery makes writing Javascript a dream. I am a Javascript novice, but I found it blissfully easy to write this code. Here's the javascript which does all the work:

When the page loads we make an ajax request 'getJSON' to the HomeController's Map action listed above. When the call completes, it fires the callback function 'initialise'. This creates the map and binds it to the map div. We set the centre of the map to the map object's LatLng and the zoom level to the map's Zoom value.

Next we iterate (using jQuery's $.each()) through the locations and call setupLocationMarker for each one. This creates a new Marker object for each location and adds it to the map. It also adds a click event handler to each marker to set the name and image url, and popup the info window.

Simple and easy. I've been really impressed by the power of jQuery. It's very good news that Microsoft have adopted it. With the Firebug plugin for Firefox doing javascript development is a real pleasure. As for the Google maps API, it is nicely conceived and has excellent documentation.

Code Rant

Notepad, thoughts out loud, learning in public, misunderstandings, mistakes. undiluted opinions. I'm Mike Hadlow, an itinerant developer. I live (and try to work in) Brighton on the south coast of England.

All code is published under an MIT licence. You are free to take it and use it for any purpose without attribution. There is no warranty whatsoever.