Tuesday, 20 October 2015

Updating collection in partial view from main view using Unobtrusive Ajax call in ASP.NET

So we have partial view that holds collection of customers. We want to increase the size of this collection by adding new customer on other partial view.
Using unobtrusive ajax call to controller action method we can achieve it quickly and without having to reload the whole page.

Expected results

In order for ajax helper to work we need to include unobtrusive-ajax js. In case it is not compatible with your version of jquery, install latest version by typing Install-Package Microsoft.jQuery.Unobtrusive.Ajax
More details on nuget page

After you load the page go to developer tools(F12 on most browsers - yes even on IE and go to network to find out if libraries have been loaded correctly).

Basically you will need jquery and  jquery.unobtrusive-ajax

Add jquery.unobtrusive.ajax to your _layout page

 <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>

So main Index page

@model TestFacility.View_Models.CustomersVM

    ViewBag.Title = "Index";

Customer List

@using (Ajax.BeginForm("AddCustomer", "Collection", new AjaxOptions{UpdateTargetId = "customers_collection",InsertionMode = InsertionMode.Replace})) { @* @Html.ValidationSummary(true) *@ @Html.Partial("_AddCustomer", new TestFacility.Models.CustomerDetails()) }

Available customers

@Html.Partial("_CustomersCollection", Model.CustomerDisplayVM)

Partial views


@model TestFacility.Models.CustomerDetails

Add new customer

CustomerDetails @Html.HiddenFor(model => model.ID)
@Html.LabelFor(model => model.Name)
@Html.EditorFor(model => model.Name) @Html.ValidationMessageFor(model => model.Name)
@Html.LabelFor(model => model.Surname)
@Html.EditorFor(model => model.Surname) @Html.ValidationMessageFor(model => model.Surname)


@model TestFacility.View_Models.CustomerDisplay

@Html.DropDownList("CustomerCollection", new SelectList(Model.CustomerCollection, "ID", "Name", "-- Select Customers --"))

Models and View models

public class CustomersVM
        public CustomersVM()
            // Create dummy list for test purpose
            this.CustomerDisplayVM = new CustomerDisplay
                CustomerCollection = BuildCustomerDetailsList()

        public CustomerDisplay CustomerDisplayVM { get; set; }

        // Helper methods
        public static List<CustomerDetails> BuildCustomerDetailsList()
            return new List<CustomerDetails>()
                    new CustomerDetails{
                    ID = 1,
                    Name = "Adam",
                    Surname = "Bielecki"
                    new CustomerDetails{
                    ID = 2,
                    Name = "Joe",
                    Surname = "Blog"


    public partial class CustomerDisplay
        public CustomerDisplay()
            this.CustomerCollection = new List<CustomerDetails>();

        public IListList<CustomerDetails> CustomerCollection { get; set; }


public class CustomerDetails
        public int ID { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }

Finally controller


        public ActionResult Index()
            // Reset session - for demo purpose only
            Session["customer_collection"] = null;
            CustomersVM vModel = new CustomersVM();
            return View(vModel);

        public ActionResult AddCustomer(CustomerDetails model)
            // Get this data from DB or external service etc, for demo purpose add customers to session object

            CustomerDisplay vModel = new CustomerDisplay();

            if (Session["customer_collection"] != null)
                vModel.CustomerCollection = Session["customer_collection"] as List<CustomerDetails>;
                vModel.CustomerCollection = CustomersVM.BuildCustomerDetailsList();


            Session["customer_collection"] = vModel.CustomerCollection;

            return PartialView("_CustomersCollection", vModel);