# Monday, April 19, 2010
« jQuery code snippets for Visual Studio 2... | Main | Being a pimp without Silverlight present... »

jQuery is a powerful javascript library which ships by default when you create an application based on the template of ASP.NET MVC 2.

MVC2LoadPartialViewThroughAjax

Normally one creates a partial view and adds that to a view and renders the whole thing at once. As I was experimenting with some dynamic behavior and jQuery ajax I wanted to try out if I could load a partial view into the already rendered html as another piece of html and then be able to post the whole thing back to the server and capture the the input.

First I created a Model class which looks like this:

public class Product
{
    public String Name { get; set; }

    public Decimal Price { get; set; }

    public String Category { get; set; }

    public override string ToString()
    {
        return String.Format("Name: {0}; Price: {1}; Category: {2}", Name, Price, Category);
    }
}

Then the controller:

public class ProductController : Controller
{
    //
    // GET: /Product/

    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Edit()
    {
        Product product = new Product()
        {
            Name = "Crispy crazy",
            Price = 3.17m,
            Category = "Sushi"
        };

        // Bad practice but just to show the animation in the right upper corner...
        Thread.Sleep(3000);

        return PartialView(product);
    }

    [HttpPost]
    public ContentResult Edit(Product product)
    {
        Product p = product;

        return Content(String.Format("Adjusted product: {0}", p.ToString()));
    }
}

Note the first Edit actionresult which fills up a dummy Product instance, halts for 3 seconds and then returns a PartialView which is found in the following code snippet:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MVC2LoadPartialViewThroughAjax.Models.Product>" %>

    <% using (Html.BeginForm()) {%>
        <%: Html.ValidationSummary(true) %>
        
        <fieldset>
            <legend>Fields</legend>
            
            <div class="editor-label">
                <%: Html.LabelFor(model => model.Name) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.Name) %>
                <%: Html.ValidationMessageFor(model => model.Name) %>
            </div>
            
            <div class="editor-label">
                <%: Html.LabelFor(model => model.Price) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.Price, String.Format("{0:F}", Model.Price)) %>
                <%: Html.ValidationMessageFor(model => model.Price) %>
            </div>
            
            <div class="editor-label">
                <%: Html.LabelFor(model => model.Category) %>
            </div>
            <div class="editor-field">
                <%: Html.TextBoxFor(model => model.Category) %>
                <%: Html.ValidationMessageFor(model => model.Category) %>
            </div>
            
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>

    <% } %>

The interesting part however is in the Index view where the needed jQuery script is placed which loads the partial view by calling the first Edit actionresult, shows an animation while it has to wait and then puts the rendered html of that partial view inside a div element where originally the button was.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
    <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="/Scripts/jquery-1.4.1.js"></script>    
    <script type="text/javascript">

        $(function () {

            $('#wait')
                .ajaxStart(function () { $(this).show(); })
                .ajaxStop(function () { $(this).hide(); });

            $('input:button').live('click', loadProduct);
        });

        function loadProduct() {
            $.get("/Product/Edit", {},
                function (data) {
                    $('#product').html(data);
                },
                "html");

        }

    </script>
</head>
<body>
    <div id="product">
        <input type="button" id="btnLoadProduct" value="Load product" />
    </div>
    <div id="wait">Please wait <img src="../../Content/Images/ajax-loader.gif" /></div>
</body>
</html>

The following part shows the div element with id=”wait” while the ajax action is performing.

$('#wait')
    .ajaxStart(function () { $(this).show(); })
    .ajaxStop(function () { $(this).hide(); });

By default this element is hidden thanks to the following piece of CSS:

#wait {
    position:absolute;
    top:0px;
    right:10px;
    width:200px;
    z-index:1000;
    vertical-align:middle;
    text-align:center;
    background: #febf00;
    display:none;
}

The loading part is:

$.get("/Product/Edit", {},
    function (data) {
        $('#product').html(data);
    },
    "html");

This is just a regular jQuery ajax get function call where in the anonymous function the result on success is passed with the name data. The next line uses a selector to find the div element with id product and then uses the html function to inject the retrieved html, from the Edit actionresult method which returns html, into the selected div element.

Here is a small video which shows the working of this code snippet:

 

Download of this article: MVC2LoadPartialViewThroughAjax.zip.

Grz, Kris.

Ajax | jQuery | MVC | PartialView