Menu

Monday 15 September 2014

Partial View Result Return Type in MVC 5 with sample Web application


About:

 

PartialView is the one of  the ActionResult type in MVC. This is also inherited from the ViewresultBase clas.  You can use Partial View is kind of user control in MVC.

So, This PartialView is mostly used for to reduce the repetitive code and also for easy code maintainability.   

 

How Can you Call/Display Partial View:

you can call or display partial view with in the view mainly in four types with the use of html helper methods.

Those are

1. Html.Partial
2. Html.RenderPartial
3. Html.Action
4. Html.RenderAction

I can discuss more about these types in a later post.

Example:

A customer having the details of customer Id, Customer Name and address like Present and Permanent address details.

Key Points to Cover:

  1. Display the customer details using partial view
  2. Edit, update the details using partial view
  3. Create the customer details by using partial view
  4. Delete the customer details by using partial view
  5. How to use Partial view in a view more than once (As I discussed it is kind of user control in MVC)
  6. Strongly typed Partial Views
Note:  This demo is being prepared with Visual Studio 2013 and MVC 5.

you can download the sample project source from the link Download Project

Step 1:

I am going to create new project in Visual Studio 2013 application.
Add a New project from the visual studion, then the displayed screen is as follows.


As, you can see in Visual Studio 2013, you are having only one type of Web application, But if you are selected in VS 2012 template it looks like below.























In this example, I am using Visual Studio 2013 with MVC5.

Step 2:


you can type the Name as “MvcPartialViewResultDemo” and then click on Ok button then the resultant screen displayed as below.




Here, you can select the project template as “MVC” and also select the “Add unit tests”  at the left most corner of the the template then the Test project name displayed as “MvcPartialViewResultDemo.Tests”. 

Its always better practice to select the Unit test project in MVC as it supports TDD (Test Data Driven) approach.

Step 3:

Click on Ok button, then it would create beautiful MVC application with addition of so many features like Login, Register, sample Layout with Responsive design approach (Bootstrap), claim based authentication template (Like login through gmail, facebook etc).  You can simply say that this is the power of visual studio. The displayed project home screen is as follows.


Now, Just click on F5 button, to see the sample MVC application till now what you have created. 



you, can just click on “Restore Down” button or just reduce the browser width then you can identify the resultant responsive design as follows.


So, Sample MVC web application is ready even with out writing single line of code.
Step 4:
The web application solution explorer looks like below.

 

 The highlighted parts of solution explorer as Model, View and Controller, you mainly work on those following components in this example.
Now, you can add one class named as CustomerModel.cs in the Model folder by right click on Model folder then Add and choose the class.
 


By clicking on “class” the template looks like below.

Click on “Add” button then the class will be created. Now, you can replace that class file code with the below code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcPartialViewResultDemo.Models
{
    public class CustomerModel
    {
        public int CustmerId { get; set; }
        public string CustomerName { get; set; }
        public CustomerAddress PermanantAddress { get; set; }
        public CustomerAddress PresentAddress { get; set; }
    }
    public class CustomerAddress
    {
        public string DoorNumber { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PinNumber { get; set; }
    }
}

Now, The Customer Model is ready in your application.

You can add a controller named as CustomerController.cs in the controller folder.
Right click on  Controllers folder then Add and the controller


 Click on “Controller” then the screen looks like below.






















This above template provides various types of controllers, In that you can choose the template named as “MVC 5 Controller with read/write actions” then click on “Add” button then another popup will appear its asks you about controller name. So, name it as “CustomerController” like the below.

Now, Just click on “Add” button, It would create CustomerController.cs file.

Are you bit surprised!!! while checking the code as it generates so much of code with all read/write actions. This is the power of template while creating a customer controller what you have chosen.

Note: Even you can define your own level of changes in that controller template by defining custom CodeTemplates (T4 Templates) in your project folder as well.

The CustomerController.cs  code file looks like below.




















Step 6:

Now, you are going to add a partial view which helps to display Address details of a customer. Partial Views can be added with in the parent controller or a shared folder. As a part of coding practice the partial view can be prefixed with “_”.

Add a partial view by following the below steps

  1. Go to Solution Explorer
  2. Views folder
  3. Inside Views folder right click on Shared folder
  4. Click on Add and then View
The resultant screen looks like follows.




Now, click on “View” it opens a popup and apply the changes as per below screen

Changes:

View Name: _CustomerAddressDetails
Template Name: List
Model class: CustomerAddress


select the Create as a Partial view option and then click on “Add” button to creates the partial view. Now, Replace the “_CustomerAddressDetails.cshtml” code with the below code.

@model MvcPartialViewResultDemo.Models.CustomerAddress
@Html.DisplayNameFor(model => model.DoorNumber)
@Html.DisplayFor(model => model.DoorNumber)
@Html.DisplayNameFor(model => model.City)
@Html.DisplayFor(model => model.City)
@Html.DisplayNameFor(model => model.State)
@Html.DisplayFor(model => model.State)
@Html.DisplayNameFor(model => model.PinNumber)
@Html.DisplayFor(model => model.PinNumber)
Step 7:

You can add view to the controller action method named as Index to display the list of all customer details.

 By Clicking on  “Add View” It displays popup and choose the setting as mentioned in the screen.

 Changes:

View name: Index
Template: List (As we are going to display list of customer details)
Model class: CustomerModel

Click on “Add” button then the view will be created  and the displayed screen is as follows.


 Now, update the Index.cshtml with the following design.

@model IEnumerable

@{
    ViewBag.Title = "Index";
}


Customer Details

@Html.ActionLink("Create New", "Create")

@*Headers*@ @*Customer Data*@ @foreach (var item in Model) { }
@Html.DisplayNameFor(model => model.CustmerId) @Html.DisplayNameFor(model => model.CustomerName) @Html.DisplayNameFor(model => model.PresentAddress) @Html.DisplayNameFor(model => model.PermanantAddress)
@Html.DisplayFor(modelItem => item.CustmerId) @Html.DisplayFor(modelItem => item.CustomerName) @Html.Partial("_CustomerAddressDetails",item.PresentAddress) @Html.Partial("_CustomerAddressDetails", item.PermanantAddress) @Html.ActionLink("Edit", "Edit", new { id=item.CustmerId }) | @Html.ActionLink("Details", "Details", new { id = item.CustmerId }) | @Html.ActionLink("Delete", "Delete", new { id = item.CustmerId })
The Index.cshtml file displays as follows.


 Step 8:

Now, open the CustomerController.cs file and add the code as follows to get the list of customer details.

Add a namespace as like below.


using MvcPartialViewResultDemo.Models;
to the CustomerController.cs file and then add the following method to CustomerController.cs file 

public List GetCustomerDetails()
        {
            var customerList = new List();
            for (int i = 1; i <= 2; i++)
            {
                var customer = new CustomerModel
                {
                    CustmerId = i,
                    CustomerName = string.Concat("Customer", i),
                    PermanantAddress = new CustomerAddress()
                    {
                        DoorNumber = string.Concat("Permanent-D.No:4-xx-", i),
                        City = string.Concat("Permanent-City", i),
                        State = string.Concat("Permanent-State", i),
                        PinNumber = string.Concat("Permanent-Pin", i)
                    },
                    PresentAddress = new CustomerAddress()
                    {
                        DoorNumber = string.Concat("Present-D.No:4-xx-", i),
                        City = string.Concat("Present-City", i),
                        State = string.Concat("Present-State", i),
                        PinNumber = string.Concat("Present-Pin", i)
                    }
                };
                customerList.Add(customer);
            }
            return customerList;
        }
and then update the Index action method code as follows. 

 // GET: Customer
        public ActionResult Index()
        {
            var customerDetails = GetCustomerDetails();
            return View(customerDetails);
        }
Now, you can build the application( Ctrl+Shift+B), After a few moments it should be “Build succeeded” then run the application by hitting F5 and then change browser URL (
http://localhost:60385/Customer/Index ) The output screen is as follows. 
















As of now, you are able to display the customer details. Now, you can work on Details of each specific customer.

Step 9:

Go to the CustomerController.cs file and add a “view” for the Action method Details.








The view template is as follows. 


Click on “Add” button and then delete and update the design html is as follows.
@model MvcPartialViewResultDemo.Models.CustomerModel
@{
    ViewBag.Title = "Details";
}

Customer Details

@Html.DisplayNameFor(model => model.CustmerId)
@Html.DisplayFor(model => model.CustmerId)
@Html.DisplayNameFor(model => model.CustomerName)
@Html.DisplayFor(model => model.CustomerName)
@Html.Partial("_CustomerAddressDetails", Model.PermanantAddress) @Html.Partial("_CustomerAddressDetails", Model.PresentAddress)
@Html.ActionLink("Edit", "Edit", new { id = Model.CustmerId }) | @Html.ActionLink("Back to List", "Index")

Step 10:

Now, Add the method GetCustomerById to the CustomerController.cs file is as follows.


public CustomerModel GetCustomerById(int customerId)
        {
            var customerDetails = GetCustomerDetails();
            var customer = (from cust in customerDetails
                where cust.CustmerId == customerId
                select cust).FirstOrDefault();
            return customer;
        }

Now, Update a details action method for CustomController.cs file.

// GET: Customer/Details/5
        public ActionResult Details(int id)
        {
            var customerModel = GetCustomerById(id);
            return View(customerModel);
        }
Build the solution and then hit the “F5” button to see the result by navigating to the URL http://localhost:60385/Customer/Details/1.













Step 11:

Now, Create another partial view to manage the edit/create operations for customer address. The flow for the screen shots is as below. 








By Clicking on "Add" button "_CustomerAddress.cshtml" file would be created and then replace the design with the following below.


@model MvcPartialViewResultDemo.Models.CustomerAddress
    

@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.DoorNumber, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.DoorNumber, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.DoorNumber, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.City, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.City, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.City, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.State, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.PinNumber, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.PinNumber, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.PinNumber, "", new { @class = "text-danger" })
Step 12:

Open CustomerController.cs file and update the Get Edit Action method with the below code.
// GET: Customer/Edit/5
        public ActionResult Edit(int id)
        {
            var customerModel = GetCustomerById(id);
            return View(customerModel);
        }
and then add a view for the Edit method like the below. 



After that, update the Edit.cshtml  with the following html design  


@model MvcPartialViewResultDemo.Models.CustomerModel
@{
    ViewBag.Title = "Edit";
}

Edit

@using (Html.BeginForm()) { @Html.AntiForgeryToken()
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.CustmerId, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.TextBoxFor(model => model.CustmerId, new { @class = "form-control", disabled = "disabled", @readonly = "readonly" })
@Html.LabelFor(model => model.CustomerName, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.CustomerName, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.CustomerName, "", new { @class = "text-danger" })

Permanent Address:

@Html.Partial("_CustomerAddress", Model.PermanantAddress)

Present Address:

@Html.Partial("_CustomerAddress", Model.PresentAddress)
}
@Html.ActionLink("Back to List", "Index")
Changes:
Disable the customer id
Include the _CustomerAddress.cshtml partial view

Now, update the Post method of Edit action in CustomerController.cs code as below.

Post method of Edit action controller code.

Build the application and hit F5, Navigate to  http://localhost:60385/Customer click on any Edit link of the customer and then update the data like the below.




After updating the details by click on “Save” button it goes to the  post action of Edit method and I have captured the field values while in debugging mode for reference. 
 
As, you observed the Post method of Edit contains two parameters one for CustomerId and another for get the all form control values.

So, FormCollection is being used to get all the control values. As you are used one partial view two times in a form to get the permanent and present address details. The FormCollection values are comes with “,” separator.

Step 13:

Add a view named as “Create.cshtml” from the get action method “Create” in customerController.cs file is as follows.



And then update the design by including Partial views is as follows.


@model MvcPartialViewResultDemo.Models.CustomerModel
@{
    ViewBag.Title = "Create";
}

Create

@using (Html.BeginForm()) { @Html.AntiForgeryToken()

CustomerModel


@Html.ValidationSummary(true, "", new { @class = "text-danger" }) @*
@Html.LabelFor(model => model.CustmerId, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.CustmerId, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.CustmerId, "", new { @class = "text-danger" })
*@
@Html.LabelFor(model => model.CustomerName, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.CustomerName, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.CustomerName, "", new { @class = "text-danger" })

Permanent Address:

@Html.Partial("_CustomerAddress")

Present Address:

@Html.Partial("_CustomerAddress")
}
@Html.ActionLink("Back to List", "Index")
After that, update the code in Post Create Action method is as follows.

// POST: Customer/Create
        [HttpPost]
        public ActionResult Create(FormCollection collection)
        {
            try
            {
                var customerModel = new CustomerModel
                {
                    CustmerId =  5, //Get the max+1 from customer list
                    CustomerName = collection["CustomerName"],
                    PermanantAddress = new CustomerAddress()
                    {
                        DoorNumber = collection["DoorNumber"].Split(',')[0],
                        City = collection["City"].Split(',')[0],
                        State = collection["State"].Split(',')[0],
                        PinNumber = collection["PinNumber"].Split(',')[0]
                    },
                    PresentAddress = new CustomerAddress()
                    {
                        DoorNumber = collection["DoorNumber"].Split(',')[1],
                        City = collection["City"].Split(',')[1],
                        State = collection["State"].Split(',')[1],
                        PinNumber = collection["PinNumber"].Split(',')[1]
                    }
                };
                // TODO: Add insert logic here
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }
Now, you are ready with the Create functionality of Customers as well. Just hit F5 and then click on “Create New” customer link then fill the details as you required. 



After entering the details, click on Save button to save the details.  


 
As you noticed in the above image, you would get the all details then you just need to send that customer model object to the database call to save the details.

Step 14:

Add a view named as “Delete.csthml”  from the get action method named as “Delete” in CustomerController.cs file.





And then update the design by including Partial views is as follows.


@model MvcPartialViewResultDemo.Models.CustomerModel
@{
    ViewBag.Title = "Delete";
}

Delete

Are you sure you want to delete this?


@Html.DisplayNameFor(model => model.CustmerId)
@Html.DisplayFor(model => model.CustmerId)
@Html.DisplayNameFor(model => model.CustomerName)
@Html.DisplayFor(model => model.CustomerName)
@Html.Partial("_CustomerAddressDetails", Model.PermanantAddress) @Html.Partial("_CustomerAddressDetails", Model.PresentAddress)
@using (Html.BeginForm()) { @Html.AntiForgeryToken()
| @Html.ActionLink("Back to List", "Index")
}

Update the code in get  Delete  action method is as follows.

 // GET: Customer/Delete/5
        public ActionResult Delete(int id)
        {
            var customerModel = GetCustomerById(id);
            return View(customerModel);
        }

Update the code in post delete action method is as follows.
// POST: Customer/Delete/5
        [HttpPost]
        public ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                if (id > 0)
                {
                    // TODO: Add delete logic here
                }
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

Build the application and hit F5 button then navigate to the “http://localhost:60385/Customer/Index” and then click on delete link to delete the customer as you desired. The delete customer output is as follows.





As you observed the above image you are getting the customer id then you can perform the database call to delete the customer.

Conclusion:

I hope this above example gives you a brief idea on usage of partial views with a sample application of customer related operations(Details, Display, Create, Edit and Delete) and also you can get some idea how can you create sample application by using MVC.

Please provide your valuable suggestions and feedback if  any.

4 comments:

  1. Thank you for your useful article.

    Considering that using ActionResult has exactly the same effect as using PartialResult as return of an Action behind a partial view, what is the main reason for using PartialResult? (by the way, you never use it in your code)

    ReplyDelete
  2. Hello Manuel Valenzuela,

    Thanks for your comments.

    ActionResult is the base class which supports different types of result types like (ActionResult, PartialViewResult, JsonResult) etc. Generally will use ActionResult as return type, so it would also support dynamic return types based on different conditions at code level.

    We can also use PartialViewResult as return type if we are going to return only partial view result.

    Thanks,
    Ramchand

    ReplyDelete
  3. Hello,
    I am in trouble with an easy partialview issue.
    I have Homecontroller (without model and with standart mvc views)
    I have post controller (with post model)
    I also have create, delete and view posts views for postcontroller.
    But I want to show my posts (like blog page) on my home/Index, under jumbotron.
    I added an ActionResult show post() method with return PartialView("_showpost", db.Post.ToList()) to my Home controller.
    I also added IENumerable to my Home/Index view.
    But unfortunately, I get object reference not set to an object error.
    I called partial from Home/Index : @Html.Partial("_showpost")
    Everything looks OK, There is no empty record on DB also.
    Why did I get this error?
    Thank you.

    ReplyDelete