This is post is meant to be a more straightforward overview of my previous post. The previous post got a little long and turned into a walthrough. If you need a walkthrough of this, check out that post at http://geekswithblogs.net/blachniet/archive/2011/08/03/walkthrough-updating-partial-views-with-unobtrusive-ajax-in-mvc-3.aspx
So in my new exploration of web development, I found what I assume to be a fairly common need to have part of a view/page update without the entire page updating. In my particular case, I wanted to have a page that listed items but also provided a form that allowed you to add an item. When an item was added, the list of items would be updated without having to regenerate the entire page.
This was eventually accomplised through the unobtrusive AJAX provided through the MVC and jQuery frameworks. Below you can see the Razor page that was used to solve my problem. In this page, we include the jquery.unobtrusive-ajax.min.js and create a form using the AjaxHelper. The Ajax form indicates that it needs to call the action function Index_AddItem, and then update the productList when the form is submitted. At the bottom, in the productList div, we render the partial view, ProductListControl with the list of products. (ProductIndexViewModel contains a Product and an IEnumerable<Product>. See Rachel Appel’s post for more information on ViewModels in MVC here: http://rachelappel.com/use-viewmodels-to-manage-data-amp-organize-code-in-asp.net-mvc-applications)
@* Views\Product\Index.cshtml* @@model BoringStore.ViewModels
.ProductIndexViewModel @ { ViewBag.Title = "Index";
}
<h2> Index</ h2>
<script src = "@Url.Content(" ~ / Scripts / jquery.unobtrusive -
ajax.min.js ")" type = "text/javascript">
</ script> @using(Ajax.BeginForm(
"Index_AddItem", new AjaxOptions { UpdateTargetId = "productList" })) {
<div> @Html.LabelFor(model => model.NewProduct.Name)
@Html.EditorFor(model => model.NewProduct.Name) < / div >
<div> @Html.LabelFor(model => model.NewProduct.Price)
@Html.EditorFor(model => model.NewProduct.Price) < / div >
<div><input type = "submit" value = "Add Product" /></ div>
}
<div id = 'productList'> @ {
Html.RenderPartial("ProductListControl", Model.Products);
}
</div>
The ProductListControl.cshtml is a very simple partial view that displays all the product names and prices in a table:
@* Views\Product\ProductListControl
.cshtml* @@model IEnumerable<BoringStore.Models.Product><table>
<!--Render the table headers.--><tr><th> Name</ th><th> Price</ th></ tr>
<!--Render the name and price of each product.--> @ foreach (var item in
Model) {
<tr><td> @Html.DisplayFor(model => item.Name) < / td >
<td> @Html.DisplayFor(model => item.Price) < / td > </ tr>
}</ table>
The controller has a GET action for the Index and a POST action for adding the item. The Index_AddItem function is what the Ajax form calls when it is submitted. This function returns a partial view, allowing us to avoid regenerating the entire page.
// Controllers\ProductController.cs
namespace BoringStore.Controllers {
public class ProductController : Controller {
public ActionResult Index() {
BoringStoreContext db = new BoringStoreContext();
ProductIndexViewModel viewModel =
new ProductIndexViewModel { NewProduct = new Product(),
Products = db.Products };
return View(viewModel);
}
public ActionResult Index_AddItem(ProductIndexViewModel viewModel) {
BoringStoreContext db = new BoringStoreContext();
db.Products.Add(viewModel.NewProduct);
db.SaveChanges();
return PartialView("ProductListControl", db.Products);
}
}
}
Summary:
The unobtrusive Ajax provided by MVC and jQuery looks like it may be useful in many areas in my future web development. I hope this post helps get some people to this solution faster than I got to it.