Delete Like a Rock Star with MVC3, Ajax and jQuery
Sure you can be a chump and use the out-of-the-box delete functionality that the MvcScaffolding gives you. Or you can use a little jQuery and delete like a rock star. Get your project set up first. Create a new MVC3 web app in Visual Studio 2010. If you have SP1 you have a choice now: internet or intranet. I'll assume we're creating an internet app but it doesn't matter really. Next add a new model called Widget:
public class Widget { public int Id { get; set; } public string Name { get; set; } }
Build the solution. Then right-click on Controllers folder and add a new controller called (what else?) WidgetController. Use the EF template and let the scaffolder do its thing. If your popup doesn't look like mine then you probably don't have SP1 installed:

Your WidgetController will be stubbed out for you. We're going to ignore the DbContext it references because this blog post ain't about EF. Just return a static list of widgets from your Index method:
public ViewResult Index() { var widgets = new List<Widget> { new Widget() {Id = 1, Name = "Purple Square Widget"}, new Widget() {Id = 2, Name = "Red Round Widget"}, new Widget() {Id = 3, Name = "Blue Octagonal Widget"} }; return View(widgets); }
One last little detail. In your Shared folder edit _Layout.cshtml to add a menu link to the widget page:
<li>@Html.ActionLink("Widgets", "Index", "Widget")</li>
Ok build and run the app. Click on the Widgets tab and you should see your stubbed-out list of three widgets. Now click on the Delete link for one of them. See that postback with the big delete button? Do you really like that behavior? Neither do I. Wouldn't it be cooler to click the Delete link and be able to confirm and delete on the index page without posting back the entire page? That's the real subject of this post. So let's do it. Close your browser and get back into VS 2010.
We're going to use jQuery for some client-side magic so in your _Layout.cshtml page reference two scripts:
- jquery-ui-1.8.11.min.js
- jquery.unobtrusive-ajax.min.js
Now back at the WidgetController. You can see how the scaffolder created an action method for the GET verb and then another for the eventual POST from the confirmation page. Go ahead and comment out both of those methods and add this one:
[AcceptVerbs(HttpVerbs.Post)] public JsonResult Delete(int id) { // let's just pretend we deleted it from the database var message = string.Format("Deleted Id '{0}' from the database!", id); return Json(new { id = id, message = message }); }
Two things. I changed the return type to a JsonResult and I added a POST verb attribute to the method as a matter of best practice.
Ok now go to your Widget Index.cshtml page. We want to do four things here. First, put a span tag above the table for a confirmation message. Second, change the Delete ActionLink to an Ajax call. Third, add a javascript function to handle the Ajax success callback. Finally, put some class names on the table so we can refer to them later. Rather than waste your time and mine let me just show the entire Index.cshtml page with all four of these changes:
@model IEnumerable<WidgetApplication.Models.Widget> @{ ViewBag.Title = "Index"; } <h2>Index</h2> <p> @Html.ActionLink("Create New", "Create") </p> <span id="actionMessage"></span> <table class="widgets"> <tr> <th> Name </th> <th></th> </tr> @foreach (var item in Model) { <tr id="widget-id-@item.Id"> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.ActionLink("Edit", "Edit", new {id = item.Id}) | @Html.ActionLink("Details", "Details", new {id = item.Id}) | @Ajax.ActionLink("Delete", "Delete", "Widget", new {id = item.Id}, new AjaxOptions { HttpMethod = "POST", Confirm = "Are you sure you want to delete this widget?", OnSuccess = "deleteConfirmation" }) </td> </tr> } </table> <script type="text/javascript"> function deleteConfirmation(response, status, data) { // remove the row from the table var rowId = "#widget-id-" + response.id; $('.widgets').find(rowId).remove(); // display a status message with highlight $('#actionMessage').text(response.message); $('#actionMessage').effect("highlight", {}, 3000); } </script>
See how the old delete ActionLink is now replaced with an Ajax action link? It's a little more verbose but not too bad. You have to tell it the controller name following the MVC convention. And there's a new AJaxOptions parameter with three settings: (1) HttpMethod to force a POST to the server; (2) Confirm to require client-side confirmation as a condition of the AJax post; and (3) OnSuccess to define a javascript callback function when we have a response.
The jQuery magic is in that deleteConfirmation javascript function. Since the widget was deleted successfully server-side we need to remove it from the table. Since our table rows have a unique id on them we can find the exact tr tag and remove it from the table. That's a lot more elegant than calling a window.location.reload() or redirecting to the Index page again like the scaffolder does. We removed the table row but that might be a bit sudden for our end users. So we put a message in the actionMessage span tag and give it a highlight effect for 3 seconds so it catches their eye and gives them a warm fuzzy that everything is ok.
Time to run it? Go for it. Now delete a row or two and relish in the awesomeness that jQuery gives us. And our code changes weren't all that complex either. Enjoy.

My name is James Still and I'm a seasoned software developer living and working in Oregon USA. I'm an avid cyclist, backpacker, reader, stargazer, and I pick at the guitar from time to time.
1 Comment
Aaron said
Thank you James! Your article was very useful for me \m/