Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Multiple Actions from a Single VIEW Page in MVC

0.00/5 (No votes)
18 Mar 2014 1  
This is developed for using Index, Create, Edit and Delete operations in a Single View Page
Sample Image - maximum width is 600 pixels

Introduction

MVC was originally developed to map the traditional input, processing, output roles into the GUI. URL routes the controller, then it checks does any stuff talk to database, talk to model then it takes information packages, sends them to view, view creates the HTML or whatever you want to create for presentation. Here Controller talks to model, model sends information to view then view has links and calls to controller. View is responsible for presenting models in the format that end users desire. Controllers often contain few lines of code to implement in View page. MVC is the Model View Controller Design Pattern. Design Pattern depends on multiple views and controllers can interface with the same model. Where my thought is that a method is responsible for a view page. Normally methods like Index, Details, Create, Edit and Delete are responsible for a single web page for each of them. Here I am trying to use different operations for a single view page.

flow

Background

This tip is focused on how to have multiple submit buttons in the same ASP.NET MVC form, and how to differentiate them in action method. I’m creating a class that inherits from ActionMethodSelectorAttribute which is a help of internet sites. The first parameter is controllerContext. This parameter will contain, amongst other objects, the FormValueProvider object. This contains values posted in the form in a NameValueCollection object. This is what I’ll check to see which button submitted the form. Here’s the code below:

onAction

Using the Code

The next step is to create action methods in HomeController viz Create and Edit. To ensure that either of these actions will be invoked, I’m going to decorate them with the ActionName attribute. This gives you the flexibility of having different actions, but still allowing you to access them with a common name. The common name is PersonDetails. Here PersonDetails is the main page name.

System.Reflection.AmbiguousMatchException: The current request for action 'PersonDetails' on controller type 'HomeController' is ambiguous between the following action methods. This is because we have two actions decorated with the same ActionName. That isn’t allowed. We need to restrict access to one action only, and we’ll use the OnActionAttribute class for this. I want to decorate my actions with this attribute and supply a ButtonName.

When the Submit button is clicked, a new input named Create will be injected into the form and that will be sent in the forms collection. This is why when you click on the Create submit button, you’ll be directed to the Create action. The same rule applies for the Update submit button.

Methods and Views

In this tip, PersonDetails method is taking a leading page or implemented for a single view purpose for this application. Here in PersonDetails id is a nullable parameter.

public ActionResult PersonDetails(int? id)
{
    ViewData["Operation"] = id;
    ViewData["users"] = db.Persons.ToList();
    Person p = db.Persons.Find(id);
    return View(p);
}

At the time of page load, id is null and it indicates to create the data. In PersonDetails View page checking id value is null or with some value from "ViewData["Operation"]" viewdata dictionary. ViewData["users"] keeps a list of persons to load list of data. And see Person p is filtered by id object and if id is not null, then it will return people detail to VIEW page, mainly this will be required for the time of edit data.

create button

In design page, two submit buttons are available; one for Create Data and another for Update data. But they will be visible under the razor condition and data is checked from "ViewData["Operation"]" viewdata dictionary with conditional operator. When Create button will fire, it will call the following method of Home controller.

Create

[HttpPost]
[ActionName("PersonDetails")]
[OnAction(ButtonName = "Create")]
public ActionResult Create(Person p)
{
    if (ModelState.IsValid)
    {
        db.Persons.Add(p);
        db.SaveChanges();
    }
    return RedirectToAction("PersonDetails");
}

When the Create button is clicked, a new input named Create will be injected into the form and that will be sent in the forms collection. This is why when you click on the Create submit button, you’ll be directed to the Create action. The same rule applies for the Update submit button.

List Data

A ViewData["users"] object in PersonDetails method of HomeController takes list of data to the View "PersonDetails.cshtml" page. The same things are explained below.

@foreach (var item in (IEnumerable<MultiActionWithSingleView.Models.Person>)ViewData["users"])
{ 
    @Html.DisplayFor(modelItem => item.Name) 
    @Html.DisplayFor(modelItem => item.DOB) 

    @Html.ActionLink("Edit", "PersonDetails", new { id = item.ID }) |
    @Html.ActionLink("Delete", "Delete", new { id = item.ID }) 
}         

Edit

Next for edit data, it links PersonDetails method of HomeController. At this time, we pass id of selected item due to load data in textbox as well. Then, you will change your data and update as per top description.

@Html.ActionLink("Edit", "PersonDetails", new { id = item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ID })        

Update

When Update button is clicked, a new input named Update will be injected into the form and that will be sent in the forms collection. This is why when you click on the Update submit button, you’ll be directed to the Edit action. See the following code:

[HttpPost]
[ActionName("PersonDetails")]
[OnAction(ButtonName = "Update")]
public ActionResult Edit(Person per)
{
    if (ModelState.IsValid)
    {
        db.Entry(per).State = EntityState.Modified;
        db.SaveChanges();
    }
    return RedirectToAction("PersonDetails", new { id = 0 });
}        

Delete

On click of Delete button, it simply sends seleted item id to Delete(int id) method of HomeController. Person will filter from id parameter and seleted person will be removed from the database.

public ActionResult Delete(int id)
{
    Person p = db.Persons.Find(id);
    db.Persons.Remove(p);
    db.SaveChanges();
    return RedirectToAction("PersonDetails", new { id = 0 });
}        

Points of Interest

At the time of coding, I got the concept of ActionMethodSelectorAttribute. And this really helped me to know new things in MVC application. I got to know that sometime developers want to work with multiple things in a single page, actions like create, update, delete and listing of records in a single VIEW page. This tip will help you if you have this requirement. Please let me know whether this has helped you or not.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here