ASP.NET MVC, JSON, and Prototype

I've tinkered with the method of posting JSON between the browser and the server via a generic handler. When the new MVC Preview came out and had native support for JSON I knew I needed to do some further tinkering. This post will describe in brief how to perform such a thing. I'll demonstrate how to perform a login process using JSON communication between an MVC Controller's action method which returns a JsonResult instance. Sounds tricky, but that's how Prototype helps us. It makes the communication process pretty easy. I'll try to be pretty short and sweet here and will keep the code discussion to a bare minimum.

Environment Setup 

First and foremost, you'll need to learn the basics of the ASP.NET MVC approach and find the two downloads over at ScottGu's blog post on the topic. That's about the best place to start.  Once you've got everything installed you should create a new MVC project. Add a folder to the Viewsfolder called Login. This is a relatively simple topic that all must implement at some point or another. I'll use the Prototype JavaScript framework for this. So make sure you download Prototype and put it into your web project. Finally, add a reference to the script in your Site.Master page, which should be in the Views/Shared folder. 

Creating the Login Index View and Controller

Within the new Login folder, create an MVC View Content Pagenamed Index.aspx.  This page will contain some HTML code, as you'll see below. This code contains some form elements and some JavaScript code. The JavaScript code is what will perform the duty of packing up the data collected from the form in the structure of a JavaScript object called Login. Once the object is created, it will be shipped over HTTP to the server.

 

<%@ page title="" language="C#" masterpagefile="~/Views/Shared/Site.Master" autoeventwireup="true" codebehind="Index.aspx.cs" inherits="MvcPreviewThree.Views.Login.Index" %>
<asp:content id="Content1" contentplaceholderid="MainContent" runat="server">
    <div class="row">
        <div class="cell">
            <label for="username">username</label>
            <input type="text" id="username" value="username" />
        </div>
    </div>
    <div class="row">
        <div class="cell">
            <label for="pwd">password</label>
            <input type="password" id="pwd" value="password" />
        </div>
    </div>
    <div class="row">
        <div class="cell">
            <input type="button" id="buttonLogin" value="login" onclick="doLogin();" />
        </div>
    </div>
    <script language="javascript" type="text/javascript">
    var Login = Class.create(
    {
        initialize: function()
        {
            this.Username = $('username').value;
            this.Password = $('pwd').value;
        }
    });
    function doLogin()
    {
        var login = new Login();
        var request = new Ajax.Request('/Login/Authenticate', 
        {
            method: 'post',
            contentType: 'application/json; charset=utf-8',
            postBody: Object.toJSON(login),
            
            onSuccess: function(transport)
            {
                alert(transport.responseText);
            },
            
            onFailure: function()
            {
                alert('fail!');
            }
        });
    }
    </script>
</asp:content>
 

 

Controlling Things

Take note of the URL in the call to the Ajax.Request constructor. The call is going to be made to /Login/Authenticate. Understanding that step will give you a better comprehension of how the URL's are converted into useful routes on the server to view pages. The first step is to create a Controller class. Since I've created a Views folder named Login, I must create the class useful for controlling all login-related procedures. This class, LoginController, will contain action methods that perform various actions the user will need to execute during the Login routines. The first of these - the Index view - needs to be controlled first. 

 

public class LoginController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

 

}

 

 

This one's pretty obvious - the call to View() will just render the Index view I already created, with the login form and JavaScript call. The next one isn't so obvious and requires a quick glance at some helper methods I've written into a JsonHelper class. This class just makes some of the heavy lifting easier in a moment. The ToJson extension method wouldn't have been possible without a post from ScottGu's blog.

 

public static class JsonHelper
{
    public static string ToJson(this object target)
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();
        return ser.Serialize(target);
    }
    public static T FromJson<T>(string json)
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();
        return ser.Deserialize<T>(json);
    }
    public static T FromJson<T>(Stream stream)
    {
        StreamReader rdr = new StreamReader(stream);
        return FromJson<T>(rdr.ReadToEnd());
    }
}

 

The last step in our controller class is the actual niftynessof the whole post. Within this method the code takes a peek at the current Request,specifically the incoming JSON string contained within the request's InputStream property. This is where I'll use my JsonHelper class, which makes it a snap to parse an HTTP Request into a JSON object. 

 

public JsonResult Authenticate()
{
    Login login = JsonHelper.FromJson<Login>(this.Request.InputStream);
    return new JsonResult
    {
        Data = (login.Username == "username" && login.Password == "password")
    };

 

}

 

The Final Touch

Last, I'll need to give the user some way of finding the Login's Index view so I'll add a link to the view in the Site.Master file's navigation section.

 

    <%= Html.ActionLink("Login", "Index", "Login")%>
</li>

 

Once you've done all this you should be able to run the code with success. I'll get around to uploading this sample onto the server so you can see it working in the next few days, but I couldn't wait to share this technique. Using Prototype as a means to communicate with a ASP.NET MVC Controller class' JsonResult methods makes for a powerful combination of tools to build truly rich, interactive applications that run in all modern browsers.

Happy Coding!