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.
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:
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.
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.