Reputation: 2030
Extension to: How do you handle multiple submit buttons in ASP.NET MVC Framework?
Let us say a view is composed of partial views bound with related models, let's say a student is required to provide multiple contact persons(partial view bound to Person model) and multiple contact numbers(partial view bound to a model) to get registered, sorry for the bad example. Once a contact person or number is added, an action (child postback or whatever) is called which validates the related model (not student model), adds it in a list and returns to the same page for further processing. Once all are added, the parent/master action validates whole student model and processes it.
How to validate the specific model for which an action is being called, add it to the page and return the same student view with added values in response?
Upvotes: 0
Views: 1004
Reputation:
This solution uses #2 (Session) since its simpler to code however this demonstrates the principles.
Views
Index View:
@using StackOverflow.Models <div> @{ Html.RenderPartial("PersonGrid", Model.Persons, new ViewDataDictionary()); } @Html.Partial("NewPerson", new Person()) @{ Html.RenderPartial("ContactGrid", Model.Contacts, new ViewDataDictionary()); } @Html.Partial("NewContact", new Contact()) @using(Html.BeginForm("Validate", "Home", FormMethod.Post)) { <input type="submit" value="Validate" /> } </div>
Person Grid
@model IList <table> <thead> <tr> <td>First Name</td> <td>Last Name</td> </tr> </thead> <tbody> @if (Model != null && Model.Any()) { foreach (var person in Model) { <tr> <td>@person.FirstName</td> <td>@person.LastName</td> </tr> } } else { <tr> <td colspan="2" style="text-align: center">No persons available</td> </tr> } </tbody> </table>
Contact Grid
@model IList <table> <thead> <tr> <td>Phone</td> </tr> </thead> <tbody> @if (Model != null && Model.Any()) { foreach (var contact in Model) { <tr> <td>@contact.Phone</td> </tr> } } else { <tr> <td>No contacts available</td> </tr> } </tbody> </table>
New Person
@model StackOverflow.Models.Person @using (Html.BeginForm("NewPerson", "Home", FormMethod.Post)) { <div> @Html.Hidden("PersonViewState", TempData["PersonViewState"]) @Html.LabelFor(m => m.FirstName)<br /> @Html.TextBoxFor(m => m.FirstName)<br /> <br /> @Html.LabelFor(m => m.LastName)<br /> @Html.TextBoxFor(m => m.LastName)<br /> <br /> <input type="submit" value="Submit" /> </div> }
New Contact
@model StackOverflow.Models.Contact @using (Html.BeginForm("NewContact", "Home", FormMethod.Post)) { <div> @Html.LabelFor(m => m.Phone)<br /> @Html.TextBoxFor(m => m.Phone)<br /> <br /> <input type="submit" value="Submit" /> </div> }
Models
public class Person
{
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
}
public class Contact
{
[Display(Name = "Phone")]
public string Phone { get; set; }
}
public class HomeModel
{
public IList<Person> Persons { get; set; }
public IList<Contact> Contacts { get; set; }
}
Helpers
public static class PersistenceMechanism
{
public static IList GetPersons()
{
return (IList<Person>) HttpContext.Current.Session["__Persons"];
}
public static IList GetContacts()
{
return (IList<Contact>) HttpContext.Current.Session["__Contacts"];
}
public static void Update(IList<Person> persons)
{
HttpContext.Current.Session["__Persons"] = persons;
}
public static void Update(IList<Contact> contacts)
{
HttpContext.Current.Session["__Contacts"] = contacts;
}
}
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new HomeModel
{
Persons = PersistenceMechanism.GetPersons(),
Contacts = PersistenceMechanism.GetContacts()
};
return View(model);
}
[HttpGet]
public ActionResult PersonGrid()
{
var persons = PersistenceMechanism.GetPersons();
return PartialView(persons);
}
[HttpGet]
public ActionResult ContactGrid()
{
var contacts = PersistenceMechanism.GetContacts();
return PartialView(contacts);
}
[HttpPost]
public ActionResult NewPerson(Person model)
{
var persons = PersistenceMechanism.GetPersons() ?? new List<Person>();
persons.Add(model);
PersistenceMechanism.Update(persons);
return RedirectToAction("Index");
}
[HttpPost]
public ActionResult NewContact(Contact model)
{
var contacts = PersistenceMechanism.GetContacts() ?? new List<Contact>();
contacts.Add(model);
PersistenceMechanism.Update(contacts);
return RedirectToAction("Index");
}
[HttpPost]
public ActionResult Validate()
{
var persons = PersistenceMechanism.GetPersons();
var contacts = PersistenceMechanism.GetContacts();
// validate
// ...
return RedirectToAction("Index");
}
}
Upvotes: 1
Reputation:
To repeat the question to ensure that I have the idea of what you are asking.
Your page page is build from two partial views with different models. Both of these partial views contain a form which will on submit build a grid of records on the UI. The main page will have a further validate button which will then validate the entire contents of both grids on postback?
In this situation I will like to have two forms where the submit event is powered by Ajax. Either jQuery / Microsoft Ajax. Both forms will submit to two separate actions which will accept their respective models, Person and Contact. Each submit button will return its respective partial view which will be a grid showing the collection of items that have been submitted so far. The partial view returned will update a specified target (e.g. div) since we are using AJAX.
Of course it will be necessary to remember the previous items that were submitted so far in order reconstruct the grid with the new item added. This will mean some soft of persistent storage is required. Some options available are:
Validation now becomes simple as the model are available server side through your persistent storage mechanism on postback.
Upvotes: 0