MVC Makes AJAX easier

by Admin 12. February 2012 19:07

MVC is a pretty new paridigm to me, I just started using it about 5 months ago, but one of the first things I noticed is how much easier it has made AJAX.  This is coming from someone who has had a very long career in ASP.NET.  There were a few different ways to provide Ajax functionality in ASP.NET the evil update panel being the easiest to implement.  My preference and, IMO, the more correct approach was to use the AJAX framework in conjunction with AJAX Aware WCF/Web Services.  The low framework overhead (no Eventing Model) in conjuction with the relatively small request/response package made these fairly easy to implement and perform very well.  The problem with these services is they were still tied up in all sorts of framework gook.

With MVC, all of that framework gook is gone, it is a much simpler PHP style implementation of AJAX.  There are several ways to utilize AJAX in the MVC world, there are the AJAX MVC Helper Class which is very easy to work with, but I perfer a pure JQuery ajax approach.

Enough talk here is an example of a simple implementation of ajax using 4 commonly used methods:

First the Controller (in this case I am using the Products table of the Northwind Database (kickin' it old school)):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
 
namespace JqueryAjax.Controllers
{
    public class ProductsController : Controller
    {
        //
        // GET: /Products/
 
        public ActionResult Index()
        {
 
            List<Product> prodList = null;
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prodList = ctx.Products.OrderBy(p => p.ProductName).ToList();
 
            }
            return View(prodList);
        }
 
        public ActionResult _productInfoJSON(int? id)
        {
            Product prod = null;
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prod = ctx.Products.Single(p => p.ProductID == id);
 
            }
            return Json(prod, JsonRequestBehavior.AllowGet);
        }
 
        public ActionResult _productInfo(int? id)
        {
            Product prod = null;
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prod = ctx.Products.Single(p => p.ProductID == id);
 
            }
            return PartialView(prod);
        }
 
        [HttpPost]
        public ActionResult _productInfoJSONParams()
        {
            Product prod = null;
            int prodId = int.Parse(this.ValueProvider.GetValue("id").AttemptedValue);
            using (NorthwindEntities ctx = new NorthwindEntities())
            {
                prod = ctx.Products.Single(p => p.ProductID == prodId);
 
            }
            return Json(new { prod.ProductName, prod.UnitPrice });
        }
 
    }
}

I use the "_" syntax to denote partial actions and views.  So looking at the above code you will notice there is only one full action "Index", so lets look at its view:

@model IEnumerable<JqueryAjax.Product>
 
@{
    ViewBag.Title = "Products List";
}
 
@section script{
    <script src="@Url.Content("~/Scripts/Info.js")" type="text/javascript"></script>
}
<h2>Index</h2>
<table>
    <tr>
        <th>
 
        </th>
        <th>
            ProductName
        </th>
    </tr>
 
@foreach (var item in Model) {
    <tr>
        <td>
            <a class="prodInfo" href="#" data-product-id="@item.ProductID">
                <img src="../../Content/Images/info.jpg" width="20" height="20" alt="info" border="0" />
            </a>
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ProductName)
            <div id="product-@item.ProductID" style="display:none;">
            </div>
        </td>
    </tr>
}
 
</table>
So in this view I am simply building a Table of product names with an info image, easy peasy.  The Ajax parts of the html are housed in the:
 
<div id="product-@item.ProductID" style="display:none;">
And the:
<a class="prodInfo" href="#" data-product-id="@item.ProductID">

The former is the place holder for our dynamic content and the latter is the link to our dynamic content.  Now that we have all of the page scaffolding in place we need to hook up the pieces.  There are several ways we can retrive the content.  We could retrieve a standard JSON object from a controller _productInfoJSON and _productInfoJSONParams or you can return a partial view.  This is where the power of MVC really hits home.  You can craft a fully functional page and return it to your AJAX container.  That is pretty sweet...  But first lets look at the JSON example:

I created 2 a JSON Get (useful for RESTful services) and a JSON Post (prefered for internal web site calls):

Here is the Java script for calling the JSON get in conjuntion with the previously crafted view and controller:

/// <reference path="jquery-1.7.1.min.js" />
$(document).ready(function () {
    $(".prodInfo").click(function (e) {
        //stop the href="#" from firing
        e.preventDefault();
 
        var prodId = $(this).data("productId");
        jsonGet(prodId);
 
    });
});

function jsonGet(prodId) {
    $.ajax({
        url: "/Products/_productInfoJSON/" + prodId,
        success: function (data) {
            $("#product-" + prodId).toggle();
            $("#product-" + prodId).html("<span> price:"+ data.UnitPrice +"</span>");
        }
    });
}
and the JSON parameterized post:

jsonPost(prodId);

function jsonPost(prodId) {
    $.ajax({
        url: "/Products/_productInfoJSONParams",
        type: "POST",
        data: { id: prodId },
        success: function (data) {
            $("#product-" + prodId).toggle();
            $("#product-" + prodId).html("<span> price:" + data.UnitPrice + "</span>");
        }
    });
}

This will get you a simple return value that you can format in JQuery.

Pretty simple right?  Well its about to get easier.  Now lets say we want to return a significant amount of data to the client and we don't want to do that messy JavaScript HTML formatting.  Partial Views to the rescue.  Create the following partial view from the _productInfo action:

@model JqueryAjax.Product
 
<fieldset>
    <legend>Product Info</legend>
 
    <div class="display-label"></div>
    <div class="display-field">
        QuantityPerUnit: @Html.DisplayFor(model => model.QuantityPerUnit)
    </div>
 
    <div class="display-field">
        UnitPrice: @Html.DisplayFor(model => model.UnitPrice)
    </div>
 
    <div class="display-field">
        UnitsInStock: @Html.DisplayFor(model => model.UnitsInStock)
    </div>
 
    <div class="display-field">
        UnitsOnOrder: @Html.DisplayFor(model => model.UnitsOnOrder)
    </div>
 
    <div class="display-field">
        ReorderLevel: @Html.DisplayFor(model => model.ReorderLevel)
    </div>
 
    <div class="display-field">
        Discontinued: @Html.DisplayFor(model => model.Discontinued)
    </div>
</fieldset>

Now change the JS click event to fire:

partialJqueryGet(prodId);

with the function definition of:

function partialJqueryGet(prodId) {
    $.get("/Products/_productInfo/" + prodId,
    function (data) {
        $("#product-" + prodId).toggle();
        $("#product-" + prodId).html(data);
    });
}

BA BAM done.  Now you are returning a partial view from an ajax call.  You can also use a pure jquery ajax implementation as opposed to the Get helper class:

function partialAjaxGet(prodId) 
{
    $.ajax({
        url: "/Products/_productInfo/" + prodId,
        success: function (data) {
            $("#product-" + prodId).toggle();
            $("#product-" + prodId).html(data);
        }
    });
 
}

 

All of the code and the northwind database can be found here:

JqueryAjax.zip (2.67 mb)

http://www.microsoft.com/download/en/details.aspx?id=23654

 

Tags: , , , , , ,

AJAX | ASP.NET | jquery | JSON | MVC3 | Razor

Calendar

<<  October 2017  >>
MoTuWeThFrSaSu
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar

Page List

RecentComments

None