Geeks With Blogs
Brian Lachniet

After writing this post, I realized that it is obnoxiously long, and maybe includes a little bit too much hand-holding. Nevertheless, I decided to post this very detailed step-by-step walkthrough of implementing a simple AJAX form in MVC3 with Razor. I'm probably going also post a shortened version of this topic for those that don't need a complete walkthrogh.

So I've been attempting to dive into ASP.NET MVC 3 lately, and have hit plenty of bumps along the way. This is my first encounter with any ASP.NET, or web development in general, so it is not surprising that I've had so much trouble. I spent about 3 evenings on the problem I'm describing below, so I decided to write up a quick post about it. Please remember that this is my first encounter with ASP.NET, so it is definitely possible that there are better ways to do this. If I do eventually find one, I will update this post. Feel free to educate me if you find any errors.

Problem: I want to have a page that lists a bunch of items (household products in my example). From this page I also want to be able to add items. When I add an item, I don't want to have to reload the entire page, but just the list of items.

Soultion:
For my example I will be using the following model (Product) and data context (BoringStoreContext):

namespace BoringStore.Models
{
    public class Product
    {
        public int ID { getset; }
        public string Name { getset; }
 
        [DataType(DataType.Currency)]
        public decimal Price { getset; }
    }
    public class BoringStoreContext : DbContext
    {
        public DbSet<Product> Products { getset; }
    }
}

Normally I generate a controller with read, write and views already implemented, then just bend it to my will. However, for this post I will do an empty controller so that I can focus on the things we NEED.

// Controllers\ProductController.cs
namespace BoringStore.Controllers
{
    public class ProductController : Controller
    {
        public ActionResult Index()
        {
            BoringStoreContext db = new BoringStoreContext();
            return View(db.Products);
        }
    }
}

This only created the controller for me (in <project>\Controllers), so I now need to create a strongly typed view (Model class = IEnumerable<Product>) in Views\Product. I'm going to create this new view to map to the Index command, so the view will be named Index.cshtml, and I end up with:

@* Views\Product\Index.cshtml *@
@model IEnumerable<BoringStore.Models.Product>
 
@{
    ViewBag.Title = "Index";
}
 
<h2>Index</h2>

So this is the page that I'm going to use to both list Products and allow the user to add Products.We'll start with the list of products. This will be done in its own Partial View, ProductListControl.cshtml.

@* 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>

Now that we have created our partial view, we need to go back to the Index.cshtml to tell it to render the partial view with the model data passed to it. This is done through the @Html.RenderPartial command. the div id is important as you will see later.

Take a moment to launch your site, visit the ~/Product page, and make sure you see an empty table. If you don't, you did something wrong, so start over.

Now we want to be able to add Products on the same page, but we want to be able to do so without reloading the entire page. We only want to reload the partial view where the new Product will be displayed. To do this we will start in the controller. We now need to be able to pass in a new Product as well as a list of available products to the Index view. This means we need an ProductIndexViewModel. 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

// ViewModels\ProductIndexViewModel.cs
namespace BoringStore.ViewModels
{
    public class ProductIndexViewModel
    {
        public Product NewProduct { getset; }
        public IEnumerable<Product> Products { getset; }
    }
}

We now need to update the controller to build this ViewModel and pass it to the view.

        // In Controllers\ProductController.cs
        public ActionResult Index()
        {
            BoringStoreContext db = new BoringStoreContext();
            ProductIndexViewModel viewModel = new ProductIndexViewModel
            {
                NewProduct = new Product(),
                Products = db.Products
            };
            return View(viewModel);
        }

And now, update the view to use a ProductIndexViewModel. Note that we have to update the model passed to the @Html.RenderPartial command to Model.Products.

@* Views\Product\Index.cshtml *@
@model BoringStore.ViewModels.ProductIndexViewModel
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<div id='productList'>
    @{ Html.RenderPartial("ProductListControl", Model.Products); }
</div>

 

Now that we have the ViewModel, we can start on the form for adding a Product. Let's jump back over to the Controller again, and add the following function:

// In Controllers\ProductController.cs
        public ActionResult Index_AddItem(ProductIndexViewModel viewModel)
        {
            BoringStoreContext db = new BoringStoreContext();
            db.Products.Add(viewModel.NewProduct);
            db.SaveChanges();
 
            return PartialView("ProductListControl", db.Products);
        }

 

This is the action that the AJAX form is going to call to add an item. Here we simply add the item to our database context and then return a PartialView of the ProductListControl view that we created earlier. Now lets insert the AJAX form into the Index view:

<!-- Added to Views\Product\Index.cshtml -->
<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>
}

Here we have created an AJAX form with lables and editors for the Product. Take note of the UpdateTargetID in the AjaxOptions. This is telling the renderer that the div that we created earlier with the partial view in it is what should be updated with the return value from the action called when this form is submitted. Launch your site and try it out. You should be able to enter data for a new Product, hit the Add Product button, and the table below should update with the product you just added.

Let me know if you have any issues or if you find an alternative that you believe is better.

[TODO Add final source code here]

<!-- Appended to Views\Product\Index.cshtml -->
<div id='productList'>
    @{ Html.RenderPartial("ProductListControl", Model); }
</div>
Posted on Wednesday, August 3, 2011 3:39 PM C# , ASP.NET , MVC , Razor , Walkthrough | Back to top


Comments on this post: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
I was wondering how you handled the javascript being loaded into the partialview. I have an issue where my _layout.cshtml loads all the scripts but the partail view can not make use of them. I end up loading all the scripts in each partial view. But I run into issues when I have more than one Partialview on a single page.
Left by byrdman on Aug 16, 2011 1:58 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
I'm not sure why your partial views would not be able to use the javascript that was loaded by your _Layout.cshtml file. The _Layout.cshtml and whatever other cshtml files you use for a view are compiled together to generate a single html file at runtime. Just take a look at the source of the page when you run it, and you will see the <script> tags from the _Layout.cshtml at the top, and the markup for your partial down lower. Can you give a more detailed explanation of the issues you are having?

Thanks!

P.S. This blog has recently moved over to http://www.blachniet.com.
Left by blachniet on Aug 16, 2011 11:01 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
Hi...
This example was so usefull. Its really really cool
Thanx a lot
Left by Neero Holan on Nov 16, 2011 10:32 PM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
Thanks man!! Very usefull!
Left by sergio on Mar 07, 2012 3:22 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
Hi...
This example was so usefull. Its really really cool
Thanx a lot
Left by Arun on Mar 28, 2012 9:25 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
I am new to the MVC3 + Razor and am wondering if a main view can use more than one partial views where some partials are a Form (ie Html.BeginForm() or Ajax.BeginForm()) and each has its own model
(ie one partial has Settings as its model class while another partial has JobStatus as its model class).
Is that possible?

Also what is the difference between the Html and Ajax BeginForms?
Left by Sheir on Apr 09, 2012 12:56 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
Can you plz upload your final source-code
Left by Bengaru on Apr 28, 2012 3:46 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
Very useful informations, thx a lot
Left by Alberto on May 08, 2012 5:07 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
This is one of the best walkthrough on the internet regarding Unobtrusive Ajax. In above scanario you are saving each record on clicking "Add Product" but what if we want to save all products at once? Actually this is the business requirement of our application. We like to give chance to user to add and subtract products and then save record at once.
Left by SAM on May 11, 2012 12:17 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
great tutorial.. thanks man
Left by Khurram on May 27, 2012 7:40 PM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
Great walkthrough, i was looking for code to do this. I have one question, when I press the add button, it adds to the database but the list in the partial view is not updated. If I go off the page and back again it refeshes?

Again, great walkthrough.
Left by rodney on Jun 05, 2012 6:33 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
this is not working.can u give me another Idea
Left by shashi on Aug 07, 2012 6:20 PM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
@rodney you don't need to refresh the page you need to write some logic on server side to get "HtmlString" of partial view, as partial view return type is string so you get it easily and return it.i will modified above stuff little bit

In Controller write one method to get string of partial view


protected string RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");

ViewData.Model = model;

using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}

Then Modified your Index_AddItem Action


public ActionResult Index_AddItem(ProductIndexViewModel viewModel)
{
BoringStoreContext db = new BoringStoreContext();
db.Products.Add(viewModel.NewProduct);
db.SaveChanges();

string HtmlString = RenderPartialViewToString("ProductListControl",model)

return HtmlString;
}


This will return you partail view with updated record
Left by shivkumar on Sep 11, 2012 9:52 PM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
Thank you for this post I have been looking for this solution for a while. Much apprectiated
Left by Eamonn Connolly on Oct 11, 2012 8:53 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
To all those who have posed questions here, I apologize that I have not responded. I moved my blog a while back to http://blachniet.com, and did not realize that this post was still getting attention. Most of the questions were posed a while back, so I assume you have probably found an alternate solution by now. If you are still having issues, please let me know.
Left by blachniet on Oct 12, 2012 6:37 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...

This is awesome!! really helpful for me. Thanks for sharing with us. Following links also helped me to complete my task.

http://www.codeproject.com/Articles/313500/Partial-View-Auto-Refresh-in-ASP-NET-MVC3

http://www.mindstick.com/Articles/74634c5e-1c0b-4cba-b7a9-198a99551fac/?Auto%20Refresh%20Partial%20View%20in%20ASP%20NET%20MVC
Left by O Henry on Jun 12, 2013 7:25 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
thank you. it makes my day.
Left by fatih on Jul 11, 2014 3:09 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
Hi ,

I have a problem that my partial view is being opened as whole new view , instead of being embedded in my index.cshtml . What could be the problem ?
Left by Preeti on Aug 12, 2014 7:14 AM

# re: [Walkthrough] Updating Partial Views with Unobtrusive AJAX in MVC 3
Requesting Gravatar...
Thanks for this usefulful post.I also refer helpful article related from Auto Refresh Partial View in ASP.NET MVC

check this

https://www.mindstick.com/Articles/1132/auto-refresh-partial-view-in-asp-dot-net-mvc

http://www.jlum.ws/post/2014/1/27/auto-refresh-partial-view-in-aspnet-mvc

Left by markdevid on Jun 27, 2016 4:50 AM

Your comment:
 (will show your gravatar)


Copyright © blachniet | Powered by: GeeksWithBlogs.net