Tuesday, October 07, 2008
Posted on Tuesday, October 07, 2008 7:05:49 AM (Mountain Daylight Time, UTC-06:00)  Comments [6] | 
Categories: .NET | Agile | Ajax | ASP.NET MVC | Dojo

1028209_man_thinking With the recent announcement that jQuery will ship with ASP.NET MVC and Visual Studio, the question of what javascript framework to use just got more complex.

Here's my situation:

1) I need to work with the ESRI Javascript API for the maps in my apps, and this is based on the dojo toolkit

2) I want to work with ASP.NET MVC because it's actually a sane way to built RESTful web apps on the Microsoft platform.

3) I need to send complex data between client and server as json

4) I work in an agile manner, so I need an environment that's flexible - hand coding of client-side "data classes" is a waste of time if they can be generated.

So - what to do?

jQuery is awesome, but if I already have dojo loaded into the browser for the map controls, it does not add much to the mix (besides more bytes to download!)

MSAjax and ASP.NET JSON Web Services make sending complex data across the wire super simple, but should I drag along this library just to save some effort here and there? Sending complex data is possible with dojo, but it requires coding the Json deserialization on the server, which is tedious but not that difficult.

So - what to do?  My initial thinking goes like this - for apps that use Google Maps or Virtual Earth, I'm inclined to use just jQuery. If I need to send complex data across the wire, then adding MSAjax into the mix is likely worth it. For sites using the ESRI Javascript API, I'm torn. Dojo has to be loaded, so I don't see good reason to load up jQuery as well. Again the call on MSAjax will be based on the complexity of the data services.

If you are working with this stack, I'd love to hear your thoughts on this...

Wednesday, October 01, 2008
Posted on Wednesday, October 01, 2008 12:28:18 PM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: .NET | Ajax | ASP.NET MVC | Dojo

Next up in my series of posts on using dojo to communicate with a Controller class is POSTing data. In this example, I used dojo.xhrPost to send Json as a form and have the MVC framework parse it into the Create(string name, string age) method on the Services controller. In this case, the data being sent back and forth is simple - a Name and Age from two text boxes.

Dojo Code

function CreateEmployeeMVCPost(){
    var responseNode = dojo.byId("responseMVCPost");
    var request = {"name":dojo.byId("username").value , "age":parseInt(dojo.byId("age").value)};     
         
    dojo.xhrPost({
        url: '<%= Page.ResolveClientUrl("~/Service/Create") %>',
        handleAs: 'json',
        timeout:3000,
        content: request,   
        //Don't set content type to Json
        contentType: "application/x-www-form-urlencoded",
        load: function(person,args){                         
            responseNode.innerHTML = "Response: " + person.Name + " " + person.Age;
        },
        error: function(error,args){ 
            alert(error);               
            responseNode.innerHtml("Error!",error);
        }
    });
}

Controller Code

ASP.NET MVC looks at the form data and matches up form elements which have the same name as the parameters of the method. So - the in-bound json {"name":"steve", "age":34} is parsed into form elements called "name" and "age", which line up with the parameters of the method (shown below). The controller just uses the inputs to create a new instance of an Employee object, which is then Json serialized and returned to the client.

[AcceptVerbs("POST")]

public ActionResult Create(string name, string age)

{

    return Json(new Employee(name, Convert.ToInt32(age)), "text/json-comment-filtered");

}

This is pretty smooth and works very well for simple data. Next time I'll look at trying to POST complex objects.

Monday, September 29, 2008
Posted on Monday, September 29, 2008 7:28:29 PM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: Ajax | ASP.NET MVC | Dojo

My first exploration of using MVC with the dojo toolkit focused on GETting data from a Controller.

I created a simple ServiceController, and added a ListEmployees method. In MVC, this relates to a Url like  http://localhost/mvcajax/Service/ListEmployees. I added the AcceptVerbs attribute to restrict this action to GET's. Code is below:

[AcceptVerbs("GET")]
public ActionResult ListEmployees()
{
    List<Employee> emps = new List<Employee>();
    emps.Add(new Employee("Dave",37));
    emps.Add(new Employee("Kai", 2));
    return Json(emps, "text/json-comment-filtered");          
}

As you can see, this just creates two "employees", adds them to a strongly typed list, and returns them as Json. Super simple.

In the View, I wired things up using dojo.xhrGet, and then converted the json into an array of objects.

What's nice about this is that the json that's returned is automatically turned into objects.

<script type="text/javascript">
function GetEmployeesMVCGet(){
    var responseNode = dojo.byId("responseMVCGet");                       
    dojo.xhrGet({
        url: '<%= Page.ResolveClientUrl("~/Service/ListEmployees") %>',
        handleAs: 'json',
        timeout:3000,                    
        contentType: "application/json; charset=utf-8",
        load: function(person,args){                                     
            responseNode.innerHTML ="Response: " + person[1].Name + " " + person[1].Age;
        },
        error: function(error,args){ 
            alert(error);               
            responseNode.innerHtml("Error!",error);
        }
    });
}
</script>

You may notice that the url passed into xhrGet looks a little funky - well, this code was copied from the View in Visual Studio, so the <%= Page.ResolveClientUrl("~/Service/ListEmployees") %> has not been evaluated. When the page is served, this expression is evaluated, and the full url added in. This is much better than putting in the path manually, as it can be used the same way from any view.

So, this is very usable, and relatively easy to build and consume

Next up - posting Data with dojo.xhrPost...

Sunday, September 28, 2008
Posted on Sunday, September 28, 2008 8:17:02 PM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: Ajax | ASP.NET MVC | Unit Testing

I'm becoming more and more reliant on unit testing as a critical part of my development process, and so I'm really excited to get a chance to build some web applications (internal research sites) using the new ASP.NET MVC (model-view-controller) bits. It's not "officially" released, but it's in "Preview 5", there is a "go-live" license, and it means you can build saner web apps without all the ASP.NET Web Forms shinanigans. So lets jump in!

I'm going to be doing a number of posts related to ASP.NET MVC, and this will be the "anchor" post - I will likely be editing it over time to add in more pointers to good resources.

The Basics

I'll point you to the official www.ASP.net/mvc site to get all the gory details, but at a high-level the things I like about this style of development are pretty simple:

  1. absolute control over the HTML and javascript that's sent to the browser,
  2. REST concepts baked in,
  3. separation of the presentation from the data from the logic (separation of concerns),
  4. Framework is test-driven development friendly

In my post on the Model View patterns, I gave some background on the idea of "MVC", so I'll consider that to be covered.

Getting Started

First thing to do is grab the bits. The installer and the source code (yes, Microsoft is publishing the source code for ASP.NET MVC!) are available at codeplex.com. This builds on .NET 3.5 and you will want to use Visual Studio 2008 (I don't think it's 100% required, but it makes the experience smoother).

Once installed, you get a new project type - ASP.NET MVC Application

mvc-project

Immediately after this dialog you are prompted to create a test project with your testing framework of choice. I like MBUnit, so that's what I selected.

mvc-project-test

So - how's that for sweet and different? Defining your unit testing strategy UP FRONT, instead of as an after thought. Tasty.

The Code

At Preview 5, the template kicks out a starter website, that's ready to roll. It's designed to show users how to do some of the common things - membership, roles, login / logout etc.

Not surprisingly the code is laid out as Models, Views and Controllers, with folders for each. Requests are routed to Controllers which then apply logic to the Model, and then determine which View to render to the client.

sol-exp

This is nice in that it helps ensure consistency across MVC projects.

Looking at the default project a little closer, we see some naming conventions at work...

details

We see two controllers - AccountController and HomeController. Then, under Views, we see two folders - Account and Home. This is not a mistake - although not required, setting things up like this simplifies the code you need to write. In the View subfolders, we see aspx pages with names that look like they may be methods, and that's exactly the case. The HomeController has 2 methods, which relate to the 2 View aspx files in /Views/Home. Initially this looks all jumbled in terms of the Url hiearchy, but that's taken care of by routing.

Routing 101

Unlike normal ASP.NET sites, the requested Url in an MVC site does not (usually) map to specific ASPX file on disk. In fact, you usually never see a file extension at all. For example, suppose you had a Url http://foo.com/orders - in traditional ASP.NET, a request to that url would look for a "default.aspx" file in the "orders" folder, and load that. With MVC, the Url is separated from the actual content on disk. Rather, decisions on what to execute are made based on what "routes" are setup for the site.

Essentially, routing is a way to map Urls to Controllers. In the sample site, a request to "/", actually routes to the HomeController, and specifically the Index action on the HomeController.

This is all setup in the Global.asax file, and looks like this:

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

    routes.MapRoute(
        "Default",                                              // Route name
        "{controller}/{action}/{id}",                           // URL with parameters
        new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
    );
}

The sample site is very simple, so the routing is very simple, but you can get much more creative with this stuff. What's really nice about this is that you can start to build RESTful applications - so getting the details of an order could be accessed via a url like /Orders/Details/123-098. You could also send along more information - either as another element in the url, or as a parameter, and specify the response format - much like how the ArcGIS Server 9.3 REST API works. This adds a tremendous amount of power and flexibility to the ASP.NET toolbox, allowing you to build one application which simultaneously provides a HTML based interface AND a Json interface - just by varying a parameter on the url (and a very minor amount of Controller code!)

Unit Testing

As noted earlier, unit testing is a key (but not mandatory) part of ASP.NET MVC. In the past, anyone concerned with testing usually kept their data classes (essentially the model) in a separate assembly which the web site referenced. This allowed the developer to write unit tests without meddling with classes in App_Code. But there was still all the code-behind logic which was a bear to test. This is where the Controllers come in. They do a lot of the logic that used to be in the code behinds. And they are testable. I'll be getting into this in more detail in upcoming posts, but you can test both the View output, as well as the routing logic.

Javascript: MSAjax, Dojo, jQuery oh my!

Since the developer has complete control over the markup that is emitted into the page, it's much easier to work with non-Microsoft Ajax libraries. This was somewhat complex in ASP.NET as the use of UserControls tended to cause all sorts of issues with respect to the ID of the HTML elements in the page. If you've ever looked at the HTML in a page and seen an id like "ctl1_ctl3_mydiv", that's ASP.NET trying to "help" you. This worked well for WebForms applications, but it's a total pain for Ajax apps where consistent ID's is critical. Why would we want to use another library? Consider that for sites using the ESRI Javascript API, the dojo toolkit is already loaded into the page, and it has all the Ajax plumbing we need to talk to back to the server - wouldn't it be nice to not load MSAjax if we did not have to? Later this week I'll be posting about some experiments I've been working on to see how this works.

 

Resources:

Tutorial Videos @ ASP.NET - good content for getting a handle on the main MVC ideas.

ASP.NET MVC Quick Start pages - high-level documentation for the framework