Note that there are some explanatory texts on larger screens.

plurals
  1. POAsp.Net MVC - How to reload form data if 'Save' of data fails in a view containing mutilple forms
    primarykey
    data
    text
    <p>I have a page which allows a user to edit the details of a Contact. It shows basic details (name, address etc.), a list of known email addresses and a list of telephone numbers and allows them to add/edit email and telephone details. My view has three forms, one for the basic details, one for the email details and one for the telephone details - each one posts to a different controller action (SaveDetails, SaveEmail, SaveTelephone). The problem is if the user goes to add a new email and the ModelState is not valid then once I return to the main Details (HttpGet) controller method to show the page and the model state error then I have lost the data that the user entered into the email form. </p> <p>I don't really want to have one big form containing all the details and I want to avoid using TempData to store/pass the form input back to the main page - does anyone have any suggestions for how to achieve this? </p> <p>Here is my view model ContactDetailsViewModel which contains the EmailDetailsViewModel and TelephoneFaxDetailsViewModel:</p> <pre><code>public class ContactDetailsViewModel : MasterViewModel { public int ContactId { get; set; } public int? EmailId { get; set; } public int? TelephoneFaxId { get; set; } [DisplayName("First Name")] [StringLength(30, ErrorMessage = "First Name cannot be more than 30 characters")] public string FirstName { get; set; } [DisplayName("Last Name")] [StringLength(30, ErrorMessage = "Last Name cannot be more than 30 characters")] public string LastName { get; set; } public IList&lt;EmailSummary&gt; EmailSummaries { get; set; } public IList&lt;TelephoneFaxSummary&gt; TelephoneFaxSummaries { get; set; } public EmailDetailsViewModel EmailDetails { get; set; } public TelephoneFaxDetailsViewModel TelFaxDetails { get; set; } } </code></pre> <p>and my view which contains 3 separate forms and is strongly typed to the ContactDetailsViewModel:</p> <pre><code>&lt;%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage&lt;SPP.Portal.ViewModels.Contacts.ContactDetailsViewModel&gt;" %&gt; &lt;% using (Html.BeginForm("Details","Contact", FormMethod.Post)) {%&gt; &lt;%: Html.ValidationSummary() %&gt; &lt;fieldset&gt; &lt;%: Html.HiddenFor(m =&gt; m.EmailId) %&gt; &lt;%: Html.HiddenFor(m =&gt; m.TelephoneFaxId) %&gt; &lt;div class="editor-field"&gt; &lt;div class="left"&gt; &lt;%: Html.LabelFor(model =&gt; model.FirstName) %&gt; &lt;%: Html.TextBoxFor(model =&gt; model.FirstName)%&gt; &lt;%: Html.ValidationMessageFor(model =&gt; model.FirstName)%&gt; &lt;/div&gt; &lt;div class="right"&gt; &lt;%: Html.LabelFor(model =&gt; model.LastName) %&gt; &lt;%: Html.TextBoxFor(model =&gt; model.LastName)%&gt; &lt;%: Html.ValidationMessageFor(model =&gt; model.LastName)%&gt; &lt;/div&gt; &lt;/div&gt; &lt;p&gt; &lt;input type="button" onclick="addEmail();" id="email" value="Add New Email" /&gt; &lt;input type="button" onclick="addTelephoneFax();" id="telFax" value="Add New Telephone/Fax" /&gt; &lt;input name="button" id="Save"type="submit" value="Save" /&gt; &lt;input name="button" id="Return" type="submit" value="Return" /&gt; &lt;/p&gt; &lt;% } %&gt; &lt;fieldset&gt; &lt;legend&gt;All Email Details&lt;/legend&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Edit&lt;/th&gt; &lt;th&gt;Email Address&lt;/th&gt; &lt;th&gt;Email Type&lt;/th&gt; &lt;th&gt;Delete&lt;/th&gt; &lt;/tr&gt; &lt;% foreach (var emailSummary in Model.EmailSummaries) { %&gt; &lt;tr&gt; &lt;%: Html.Hidden(emailSummary.EmailId.ToString()) %&gt; &lt;td&gt; &lt;a href="&lt;%: ResolveUrl(emailSummary.EditUrl.OriginalString) %&gt;"&gt;Edit&lt;/a&gt; &lt;/td&gt; &lt;td&gt; &lt;%: emailSummary.EmailAddress %&gt; &lt;/td&gt; &lt;td&gt; &lt;%: emailSummary.EmailType %&gt; &lt;/td&gt; &lt;td&gt; &lt;a href="&lt;%: ResolveUrl(emailSummary.DeleteUrl.OriginalString) %&gt;" class="confirmDelete"&gt;Delete&lt;/a&gt; &lt;/td&gt; &lt;/tr&gt; &lt;% } %&gt; &lt;/table&gt; &lt;/fieldset&gt; &lt;% using (Html.BeginForm("EmailDetails", "Contact", FormMethod.Post)) {%&gt; &lt;div id="EmailDetails"&gt; &lt;fieldset&gt; &lt;legend&gt;Email&lt;/legend&gt; &lt;%: Html.HiddenFor(m =&gt; m.EmailDetails.Id)%&gt; &lt;%: Html.HiddenFor(m =&gt; m.EmailDetails.ContactId)%&gt; &lt;div class="editor-field"&gt; &lt;div class="right"&gt; &lt;%: Html.LabelFor(m =&gt; m.EmailDetails.EmailAddress)%&gt; &lt;%: Html.TextBoxFor(m =&gt; m.EmailDetails.EmailAddress)%&gt; &lt;%: Html.ValidationMessageFor(model =&gt; model.EmailDetails.EmailAddress)%&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="editor-field"&gt; &lt;div class="left"&gt; &lt;%: Html.LabelFor(m =&gt; m.EmailDetails.EmailType)%&gt; &lt;%: Html.DropDownListFor(m =&gt; m.EmailDetails.EmailType, Model.EmailDetails.EmailTypeCodes)%&gt; &lt;%: Html.ValidationMessageFor(model =&gt; model.EmailDetails.EmailType)%&gt; &lt;/div&gt; &lt;p&gt; &lt;input type="submit" id="EmailSave" value="Save" /&gt; &lt;input type="submit" name="button" id="EmailCancel" value="Cancel" /&gt; &lt;/p&gt; &lt;/fieldset&gt; &lt;% } %&gt; &lt;/div&gt; &lt;fieldset&gt; &lt;legend&gt;All Telephone/Fax Details&lt;/legend&gt; &lt;table&gt; &lt;tr&gt; &lt;th&gt;Edit&lt;/th&gt; &lt;th&gt;Dialing Code&lt;/th&gt; &lt;th&gt;Telephone/Fax Number&lt;/th&gt; &lt;th&gt;Delete&lt;/th&gt; &lt;/tr&gt; &lt;% foreach (var telFaxSummary in Model.TelephoneFaxSummaries) { %&gt; &lt;tr&gt; &lt;%: Html.Hidden(telFaxSummary.TelephoneFaxId.ToString())%&gt; &lt;td&gt; &lt;a href="&lt;%:ResolveUrl(telFaxSummary.EditUrl.OriginalString)%&gt;" &gt;Edit&lt;/a&gt; &lt;/td&gt; &lt;td&gt; &lt;%: telFaxSummary.DialingCode%&gt; &lt;/td&gt; &lt;td&gt; &lt;%: telFaxSummary.TelephoneFaxNumber%&gt; &lt;/td&gt; &lt;td&gt; &lt;a href="&lt;%:ResolveUrl(telFaxSummary.DeleteUrl.OriginalString)%&gt;" class="confirmDelete"&gt;Delete&lt;/a&gt; &lt;/td&gt; &lt;/tr&gt; &lt;% } %&gt; &lt;/table&gt; &lt;/fieldset&gt; &lt;% using (Html.BeginForm("TelephoneFaxDetails", "Contact", FormMethod.Post)) {%&gt; &lt;div id="TelephoneFaxDetails"&gt; &lt;%: Html.HiddenFor(m =&gt; m.TelFaxDetails.TelephoneFaxId)%&gt; &lt;%: Html.HiddenFor(m =&gt; m.TelFaxDetails.ContactId)%&gt; &lt;fieldset&gt; &lt;legend&gt;Telephone/Fax&lt;/legend&gt; &lt;div class="editor-field"&gt; &lt;div id="left" class="left"&gt; &lt;%: Html.LabelFor(m =&gt; m.TelFaxDetails.InternationalDialingCode)%&gt; &lt;%: Html.TextBoxFor(m =&gt; m.TelFaxDetails.InternationalDialingCode)%&gt; &lt;%: Html.ValidationMessageFor(model =&gt; model.TelFaxDetails.InternationalDialingCode)%&gt; &lt;/div&gt; &lt;div id="middle" class="right"&gt; &lt;%: Html.LabelFor(m =&gt; m.TelFaxDetails.TelephoneFaxNumber)%&gt; &lt;%: Html.TextBoxFor(m =&gt; m.TelFaxDetails.TelephoneFaxNumber)%&gt; &lt;%: Html.ValidationMessageFor(model =&gt; model.TelFaxDetails.TelephoneFaxNumber)%&gt; &lt;/div&gt; &lt;/div&gt; &lt;p&gt; &lt;input type="submit" id="TelephoneSave" value="Save" /&gt; &lt;input type="submit" name="button" id="TelephoneCancel" value="Cancel" /&gt; &lt;/p&gt; &lt;/fieldset&gt; &lt;% } %&gt; &lt;/div&gt; </code></pre> <p></p> <p>And then my controller method to add a new Email:</p> <pre><code> [HttpPost] public ActionResult EmailDetails(ContactDetailsViewModel contactViewModel) { var viewModel = contactViewModel.EmailDetails; if (ModelState.IsValid) { try { _viewModelService.UpdateEmail(User, viewModel); return RedirectToAction("Details"); } catch (Exception ex) { ModelState.AddModelError("Exception", "The Email was not updated."); return RedirectToAction("Details"); } } return View("Details", contactViewModel); } </code></pre> <p>So the idea is that if I take the whole ContactViewModel into the Email post then if the model is not valid then I should be able to return the whole Details ContactViewModel which would contain the basic contact details and the email details that the user had just input so they would not lose the data. The email details are passed to the controller fine however all of the basic contact data is null when passed into the controller - any ideas?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload