Working With JQuery Ajax API on ASP.NET MVC 3.0 - Power of JSON, JQuery and ASP.NET MVC Partial Views

In this post, we'll see how easy to work with JQuery AJAX API on ASP.NET MVC and how we make use of Partial Views to transfer chunk of html from server to client with a toggle button example.
9 September 2011
9 minutes read

Related Posts

JQuery-logo

So, here it is. Nearly every blog I occasionally read has one JQuery related post which has JQuery ‘write less, do more’ logo on it. Now, I have it either Smile This is entirely not the intention of this blog post. What the real intention of this blog post is to lay down some useful stuff done with JQuery Ajax API on ASP.NET MVC 3.0 framework.

I am no expert on neither JQuery nor JavaScript but I am working on it and I hit the resources so hard nowadays. I am no expert on ASP.NET MVC either but I am sure I am pretty damn good at it. It is my favorite platform since v1.0.

ASP.NET MVC embraces the web (html, http, plain JavaScript) and enables you to move which direction you want on your layout. I mean you can real have your way. So, it is so important here to be able to use JavaScript (for most, it is not JavaScript anymore. It is JQuery. Don’t be surprised if you see Content-Type: text/jquery response header) as Ninja in order to get the most out of ASP.NET MVC’s V part (V as in View).

Easiest way to get JQuery package into your ASP.NET MVC 3.0 project is to do exactly nothing. No kidding, it is already there if you install the ASP.NET MVC 3 Tools Update

If you would like to get the latest version of it (which the below samples has been written on), simply type Update-Package JQuery inside PMC (Package Manager Console) and hit enter and you will be done !

Let’s get it started then.

Overview of the Process

Setting expectations correctly is the real deal. We need to set them correctly so that we will be as satisfied as we planned. In this quick blog post, I will walk you through a scenario: a basic to-do list application. We will:

  • Make AJAX calls to our server,
  • Display loading messages while processing,
  • Make use of partial views when we need to update our web page seamlessly.

File New > Project > ASP.NET MVC 3 Web Application > Internet Application > Razor View Engine > No thanks, I don’t want the test project > OK

So the mini title above actual explains what we need to do first, briefly Smile What I would like to do first is to set up my model, ORM (I will use Entity Framework for that) and database.

The main concern of this blog post is AJAX API usage on ASP.NET MVC so I am not go through all the steps of creation our model, database and all that stuff. I will put the sample code at the bottom of this blog post so feel free to dig into that

Then I will make sure to update my JQuery Nuget package to the latest one. I will tweak the default application a little bit as well.

Go get him tiger

Now we are all set up and ready to rock. Let’s begin.

imageOur database here is so simple as you can see on the left hand side. I have created the database with SQL Server Compact edition because database is not the point we are emphasizing on this post.

Our application will only consist one page and we will do all the work there.

First, I will create the JQuery structure. As I mentioned, we will display user friendly loading message to the end user. In order to do that, we will use JQuery.UI dialog api. We will have it inside our _layout.cshtml page (the reason why we do that is to be able to use it everywhere without writing it again. This app might contains only one page but think about multiple page apps for this purpose).

The code for that is really simple actually. We will only have a section defined as html code inside the DOM and we will turn that into a JQuery.UI dialog for loading messages.

Below is the html code for our loading box :

        <div id="ajax-progress-dialog">
            <div style="margin:10px 0 0 0;text-align:center;">
                <img src="@Url.Content("~/Content/img/facebook.gif")" alt="Loading..." />
            </div>
        </div>

Very simple html (please forgive me for putting the style code inline Smile). The below JQuery code will handle this html code :

        (function () {
            $(function () {
                //Global ajax progress dialog box
                //Simply run $("#ajax-progress-dialog").dialog("open"); script before the ajax post and
                //$("#ajax-progress-dialog").dialog("close"); on the ajax post complate
                $("#ajax-progress-dialog").dialog({
                    autoOpen: false,
                    draggable: false,
                    modal: true,
                    height: 80,
                    resizable: false,
                    title: "Processing, please wait...",
                    closeOnEscape: false,
                    open: function () { $(".ui-dialog-titlebar-close").hide(); } // Hide close button
                });
            });
        })();

With this approach, we set up an environment for ourselves to open this dialog when we start the AJAX call and close it when the action is completed.

Some of you guys probably think that .ajaxStart() and .ajaxComplate() would be a better fit here but I don’t. They will hook up the functions for all the AJAX calls but we might need separate loading messages. With the above approach we will call the global loading message only when we need it.

imageNow we can move up. I have added some items to the list manually and list then on the page and we have the result as the picture on the left side.

It is quite simple yet but don’t worry, it will get messy in a moment. First thing that we will do here is to add a functionality to enable toggling IsDone property of the items. When we click the anchor, the To-Do item will be marked as completed if it is not and vice versa.

Let’s look at the view code here before doing that because there is some fundamental structure for our main purpose here :

@model IEnumerable<JQueryAJAXToDoListMVCApp.Models.ToDoTB>

@{
    ViewBag.Title = "Tugberk's To-Do List";
}

@section Head { 
    <script>
        (function () {
            $(function () {
                //JQuery code will be put here
            });
        })();
    </script>
}

<h2>Tugberk's To-Do List</h2>

<div id="to-do-db-list-container">
    @Html.Partial("_ToDoDBListPartial")
</div>

As you can see have rendered a partial view here. The complete partial view code is as follows :

@model IEnumerable<JQueryAJAXToDoListMVCApp.Models.ToDoTB>

<table style="width:100%;">

    <tr>
        <th>Item</th>
        <th>Creation Date</th>
        <th>IsDone</th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>@item.Item</td>
        <td>@item.CreationDate</td>
        <td>@item.IsDone</td>
    </tr>   
}

</table>

So why we did that is a good question in this case. When we need to make a change to our list view through an AJAX call, we will render this partial view on our controller method and send it back to the client as JSON result. This partial view will be our template here. When we make a change to this partial view, this change will be made all of the places that use this partial view which is kind of nice.

Also, this action will show us one of the main fundamentals of ASP.NET MVC which is separation of concerns. View doesn’t care how the model arrives to it. It will just displays it. The same is applicable for controller as well. It does not care about how the view will display the model. It will just pass it.

Let’s put the above paragraph in action. First, we need to make a little change to our partial view for toggle function :

@foreach (var item in Model) {
    <tr>
        <td>@item.Item</td>
        <td>@item.CreationDate</td>
        <td>
            @if (@item.IsDone) { 
                <a class="isDone" href="#" data-tododb-itemid="@item.ToDoItemID">Complated (Mark as Not Complated)</a>
            } else { 
                <a class="isDone" href="#" data-tododb-itemid="@item.ToDoItemID">Not Complated (Mark as Complated)</a>
            }
        </td>
    </tr>   
}

With this change, we make the DOM ready for the JQuery. Let’s look at the JQuery code for the toggle action :

        (function () {
            $(function () {

                function toggleIsDone(e, element) {

                    var itemId = element.attr("data-tododb-itemid");
                    var d = "itemId=" + itemId;
                    var actionURL = '@Url.Action("toogleIsDone", "ToDo")';

                    $("#ajax-progress-dialog").dialog("open");

                    $.ajax({
                        type: "POST",
                        url: actionURL,
                        data: d,
                        success: function (r) {
                            $("#to-do-db-list-container").html(r.data);
                        },
                        complete: function () {
                            $("#ajax-progress-dialog").dialog("close");
                            $(".isDone").bind("click", function (event) {
                                toggleIsDone(event, $(this));
                            });
                        },
                        error: function (req, status, error) {
                            //do what you need to do here if an error occurs
                            $("#ajax-progress-dialog").dialog("close");
                        }
                    });

                    e.preventDefault();
                }

                $(".isDone").bind("click", function(e) {
                        toggleIsDone(e, $(this));
                });

            });
        })();

Let’s bring that code down into pieces. First, we bind toggleIsDone(e, element) as a click function to every element whose class attribute is ‘isDone’ and we know that they are our toggle anchors. On the toggleIsDone function, we will grab the itemId of the clicked item from data-tododb-itemid attribute of clicked anchor. Then, we will set the itemId as parameter on d variable.

Look at the actionURL variable. What happens there is that : we assigning the URL of toogleIsDone action of ToDo controller.

Before we begin our AJAX call, we simply fire up our loading dialog to display that we are doing some stuff.

On the AJAX call, we make a post request to actionURL and we are passing the d variable as data. We know that we will get back a JSON result which contains a data property and on success event of the call we simply change the content of to-do-db-list-container element with the new one which we have received from the server as JSON result.

Just before we step out the success event, we do very tricky stuff there. It is tricky in this case and hard to figure it out if you are new to JQuery. I will try to explain what we did there. We bind toggleIsDone(e, element) as a click function to every element whose class attribute is ‘isDone’. The weird thing is the fact that we have done the same just after the DOM has loaded. So, why the heck do we do that? We have bind the specified function to specified elements just after the DOM has loaded. That’s fine. Then, we have update the entire content of to-do-db-list-container div and the all click event that we have bind has been cleared out. In order not to lose the functionality, we have bind them again.

This kind of an Inception way is the best way that I come up with for this functionality and if you thing there is a better one, let me know.

On complete event, we made sure to close our loading dialog.

At the end of the code, we call a function called preventDefault() for the event. What this does is to prevent the anchor to do its default function which would be the append the # to the URL. Not necessary here but it is kind of nice to use here though.

So far, we have completed our work on client side code and lastly, we need to implement the server side function which updates the database according to parameters and sends a JSON result back to the client.

Before we do that we need to use Nuget here to bring down a very small package called TugberkUg.MVC which will have a Controller extension for us to convert partial views to string inside the controller.

image

image

The complete code of out ToDoController is as indicated below :

using System.Linq;
using System.Web.Mvc;
using TugberkUg.MVC.Helpers;
using System.Data.Objects;
using System.Data;

namespace JQueryAJAXToDoListMVCApp.Controllers
{
    public class ToDoController : Controller {

        private readonly Models.ToDoDBEntities _entities = new Models.ToDoDBEntities();

        public ActionResult Index() {

            var model = _entities.ToDoTBs;

            return View(model);
        }

        [HttpPost]
        public ActionResult toogleIsDone(int itemId) {

            //Getting the item according to itemId param
            var model = _entities.ToDoTBs.FirstOrDefault(x => x.ToDoItemID == itemId);
            //toggling the IsDone property
            model.IsDone = !model.IsDone;

            //Making the change on the db and saving
            ObjectStateEntry osmEntry = _entities.ObjectStateManager.GetObjectStateEntry(model);
            osmEntry.ChangeState(EntityState.Modified);
            _entities.SaveChanges();

            var updatedModel = _entities.ToDoTBs;

            //returning the new template as json result
            return Json(new { data = this.RenderPartialViewToString("_ToDoDBListPartial", updatedModel) });
        }

        protected override void Dispose(bool disposing) {

            _entities.Dispose();
            base.Dispose(disposing);
        }

    }
}

When you look inside the toogleIsDone method, you will see that after the necessary actions are completed, we will pass a model to our partial view which we have created earlier, render it and finally return it to the client as JSON. Why we return it as JSON instead of content is a totally subjective question in my opinion. For me, the advantage of JSON result is to be able to pass multiple values. For example, we would pass the result as follows if we needed :

            return Json(
                new { 
                    CustomMessage = "My message", 
                    data = this.RenderPartialViewToString("_ToDoDBListPartial", updatedModel) 
                });

Now when we compile our project and run it, we will see a working application :

image image image

Also, here is a quick video of a working example :

Summary

What we need to get out of from this blog post is to see that what we are capable of doing with a little effort for very usable and user friendly web pages. Also, we can visualize how things fit together and flow on your project. There are lots of way of making calls to your server from client side code and lots of them have its own pros and cons.

I hope that this blog post helps you, even a little, to solve a real world problem with your fingers Smile