Posted on June 15, 2009 09:43 by swilliams

I gave two talks at Desert Code Camp this last weekend on ASP.NET MVC. The talks went well enough, though the time was far too short to cover everything I wanted to. I did get requests to share the code created during the sessions. So, here it is, for the most part.

http://krazyyak.com/sogeti/DemoBlog.zip

I say “for the most part” because it’s not the exact same stuff written during the presentation. I went through, cleaned up, and commented many of the methods and functions in everything.

The stuff with StructureMap is still pretty rough; I’m not a StructureMap expert, but I want to learn more about it. I’ll hopefully be able to blog about it in July.

As far as a disclaimer, this code is public domain and should be only used for demonstration/educational purposes. I offer no warranties on it, etc. Actually using it for a blog engine is probably a bad idea.

Feel free to discuss it here and ask questions.



Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on June 2, 2009 17:41 by swilliams

In the project I am currently working on, we are using JavaScript and jQuery in just about everything. One of the frustrations that I have been seeing is that I’ll render a view representing an object, but also want a JSON version of that object to manipulate. I am also quite anal when it comes to keeping my code clean and separating the concerns; I did not want to have JavaScript strewn throughout my HTML or vice versa.

I considered a couple of options. The first just involved making an AJAX call to the server and having it return a JsonResult. This is clean, but I did not want to effectively double my calls to the server.

I also considered extending the MVC framework and writing my own ActionResult class that returned both HTML and JSON. However, that also “felt” wrong; like I was short-circuiting the framework. I would have had to rely on JavaScript on the client side to parse the resulting object and place the HTML, not something I want to be doing with all of my views.

I let it sit on the backburner for a while, and then today came up with a pretty good solution. It’s not ideal, but it works well enough for me. I created a simple HtmlHelper extension that just dumps the JSON out into a variable:

    
using System.Web.Script.Serialization;

    public static class JsonExtensions {
        public static string Json(this HtmlHelper html, string variableName) {
            return Json(html, variableName, html.ViewData.Model);
        }

        public static string Json(this HtmlHelper html, string variableName, object model) {
            TagBuilder tag = new TagBuilder("script");
            tag.Attributes.Add("type", "text/javascript");
            JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
            tag.InnerHtml = "var " + variableName + " = " + jsonSerializer.Serialize(model) + ";";
            return tag.ToString();
        }
    }

You call it from a page like so:

<%= Html.Json("foo") %>
<%= Html.Json("bar", Model.Something) %>

This is not an ideal solution, you are still technically putting JavaScript in the HTML. But, it does not make an extra call to the server, and the markup in the IDE is still very clean.

Another approach I considered was to have an Action that returned a JavaScriptResult that consisted of the same thing. You could then add a script tag like:

<script type="text/javascript" src="/javascript/MyObject/1000">

The catch though is that it would cause more overhead, especially if the app was designed in such a way that the retrievals are expensive (ours is).

I’m still ruminating on that perfect scenario, but for now I’ll be doing it this way.



Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on May 14, 2009 13:04 by swilliams

Just prior to their 1.0 release, the ASP.NET MVC dev team added a nice feature to prevent CSRF attacks, the AntiForgeryToken. In brief, a CSRF attack is when a 3rd party gets one of your users to accidentally run a malicious script that accesses normally restricted URLs. The AntiForgeryToken pattern allows the web server to reject requests that come from places it was not expecting. More details can be found here. If you are a web developer and aren’t familiar with CSRF attacks, you need to fix that.

Anyways, the AntiForgeryToken bit is all well and good, but what if you are using jQuery (or another library) to handle your AJAX calls? Say you have an Action method like this:

[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken]
public ActionResult DeleteAccount(int accountId) {
    // delete stuff
}

And you call it via:

$.post('/home/DeleteAccount', { accountId: 1000 }, function() {
    alert('Account Deleted.');
});

Since the POST does not include the AntiForgeryToken, it will fail.

Fortunately, it doesn’t take much brainpower to fix this. All the client side component of AntiForgeryToken does is put the token in a basic hidden field. So, you just need to pull that data out and include it in your AJAX call.

var token = $('input[name=__RequestVerificationToken]').val();

$.post('/home/DeleteAccount', { accountId: 1000, '__RequestVerificationToken': token }, function() {
    alert('Account Deleted.');
});

Do note that if you have multiple forms on the page with multiple AntiForgeryTokens, you will have to specify which one you want in your jQuery selector. Another gotcha is if you are using jQuery’s serializeArray() function, you’ll have to add it a bit differently:

var formData = $('#myForm').serializeArray();
var token = $('input[name=__RequestVerificationToken]').val();
formData.push({ name: '__RequestVerificationToken', value: token });

$.post('/home/DeleteAccount', formData, function() {
    alert('Account Deleted.');
});

Again, if you are making a web site that has any sort of interactivity at all, you need to be aware of these kinds of attacks. The tools to prevent them are readily available for you to use.



Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted on May 11, 2009 21:36 by swilliams

I'm a big fan of the ASP.NET MVC framework. I love the fine grained control it gives you over everything. But what I love most is that you can unleash the fully armed and operational firepower of jQuery.

Recently, I've been working on a site that is using both MVC and jQuery to make AJAX calls. Typically the method being called returned HTML (via a PartialView). But, if an error was thrown, I wanted to return a JSON object encapsulating it.

Unfortunately, jQuery could not decide how to handle a response that could be either HTML, or a JSON object. You can tell jQuery what to expect, or let it try to figure out what the response dataType is. Here's the behavior of my Action method:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult HandleAjax(int id) {
    try {
        var myObj = RetrieveData(id);
        return PartialView("myview", myObj);
    } catch (Exception ex) {
        return Json(new { success = false, message = ex.Message });
    }
}

The problem is that regardless of what gets returned, jQuery only recognizes it as a string, and treats it as HTML.

I did think of one solution, but it used pretty poor design: it attempted to parse the responseText as JSON. If that was successful, it meant the error object was returned. But, if an exception was thrown, it was the HTML. The problem is that it was using error handling mechanisms to capture an expected result. Bad news; I'm not even going to post the code.

Fortunately, someone pointed out that if I set the http status code to 500, jQuery will send the result to the error() callback function, as opposed to success(). Thus, if you added:

this.Response.StatusCode = 500;

In the catch block, you can then use jQuery's error() callback to do exactly as you'd expect:

$.ajax({
    data: { id: 100 },
    dataType: 'html',
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        var errorObj = JSON.parse(XMLHttpRequest.responseText);
        handleError(errorObj);
    },
    success: function(data) {
        $('#resultContainer').html(data);
    },
    url: '/home/HandleAjax'
});

This also makes use of Crockford's JSON library to parse the responseText string to a JSON object.

It is this transparency that makes me sing the praises of the MVC framework. Such a mechanism is certainly possible with classic WebForms, but it is hidden under layers of abstraction, and likely would have required mixing of markup, script, and server side code.



Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5