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

_AddCustomer

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

_CustomerCollection

@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


[HttpPost]

        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>;
            }
            else
            {
                vModel.CustomerCollection = CustomersVM.BuildCustomerDetailsList();
            }

            vModel.CustomerCollection.Add(model);

            Session["customer_collection"] = vModel.CustomerCollection;

            return PartialView("_CustomersCollection", vModel);
        }