Asp.Net MVC - Как перезагрузить данные формы, если «Сохранить» данных не удается в представлении, содержащем несколько форм - PullRequest
2 голосов
/ 09 декабря 2010

У меня есть страница, которая позволяет пользователю редактировать детали контакта. Он показывает основные сведения (имя, адрес и т. Д.), Список известных адресов электронной почты и список телефонных номеров и позволяет им добавлять / редактировать данные электронной почты и телефон. В моем представлении есть три формы: одна для основных сведений, одна для деталей электронной почты и одна для подробностей телефона - каждая отправляет сообщение на другое действие контроллера (SaveDetails, SaveEmail, SaveTelephone). Проблема в том, что если пользователь идет, чтобы добавить новое электронное письмо, а ModelState недействителен, то, как только я возвращаюсь к основному методу контроллера Details (HttpGet), чтобы показать страницу и ошибку состояния модели, я теряю данные, введенные пользователем. в форму электронной почты.

Я действительно не хочу иметь одну большую форму, содержащую все детали, и я хочу избегать использования TempData для хранения / передачи ввода формы обратно на главную страницу - есть ли у кого-нибудь какие-либо предложения о том, как этого добиться?

Вот моя модель просмотра ContactDetailsViewModel, которая содержит EmailDetailsViewModel и TelephoneFaxDetailsViewModel:

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<EmailSummary> EmailSummaries { get; set; }
    public IList<TelephoneFaxSummary> TelephoneFaxSummaries { get; set; }

    public EmailDetailsViewModel EmailDetails { get; set; }
    public TelephoneFaxDetailsViewModel TelFaxDetails { get; set; }
}

и мое представление, которое содержит 3 отдельные формы и строго напечатано в ContactDetailsViewModel:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SPP.Portal.ViewModels.Contacts.ContactDetailsViewModel>" %>
<% using (Html.BeginForm("Details","Contact", FormMethod.Post))
   {%>
        <%: Html.ValidationSummary() %>
<fieldset>
    <%: Html.HiddenFor(m => m.EmailId) %>
    <%: Html.HiddenFor(m => m.TelephoneFaxId) %>

    <div class="editor-field">
        <div  class="left">
            <%: Html.LabelFor(model => model.FirstName) %>
            <%: Html.TextBoxFor(model => model.FirstName)%>
            <%: Html.ValidationMessageFor(model => model.FirstName)%>
        </div>
        <div class="right">
            <%: Html.LabelFor(model => model.LastName) %>
            <%: Html.TextBoxFor(model => model.LastName)%>
            <%: Html.ValidationMessageFor(model => model.LastName)%>
        </div>
    </div>

    <p>
        <input type="button" onclick="addEmail();" id="email" value="Add New Email" />
        <input type="button" onclick="addTelephoneFax();" id="telFax" value="Add New Telephone/Fax" />
        <input name="button" id="Save"type="submit" value="Save" />
        <input name="button" id="Return" type="submit" value="Return" />
    </p>

    <%
        } %>
    <fieldset>
        <legend>All Email Details</legend>
        <table>
            <tr>
                <th>Edit</th>
                <th>Email Address</th>
                <th>Email Type</th>
                <th>Delete</th>
            </tr>
            <% foreach (var emailSummary in Model.EmailSummaries)
               { %>
            <tr>
                <%: Html.Hidden(emailSummary.EmailId.ToString()) %>
                <td>
                   <a href="<%: ResolveUrl(emailSummary.EditUrl.OriginalString) %>">Edit</a>
                </td>
                <td>
                    <%: emailSummary.EmailAddress %>
                </td>
                <td>
                    <%: emailSummary.EmailType %>
                </td>
                <td>
                 <a href="<%: ResolveUrl(emailSummary.DeleteUrl.OriginalString) %>" class="confirmDelete">Delete</a>
                </td>
            </tr>
            <% } %>
        </table>
    </fieldset>

    <% using (Html.BeginForm("EmailDetails", "Contact", FormMethod.Post))
     {%>
    <div id="EmailDetails">
    <fieldset>
        <legend>Email</legend>

        <%: Html.HiddenFor(m => m.EmailDetails.Id)%>
        <%: Html.HiddenFor(m => m.EmailDetails.ContactId)%>
        <div class="editor-field">
            <div class="right">
                <%: Html.LabelFor(m => m.EmailDetails.EmailAddress)%>
                <%: Html.TextBoxFor(m => m.EmailDetails.EmailAddress)%>
                <%: Html.ValidationMessageFor(model => model.EmailDetails.EmailAddress)%>
            </div>
        </div>
        <div class="editor-field">
            <div class="left">
                <%: Html.LabelFor(m => m.EmailDetails.EmailType)%>
                <%: Html.DropDownListFor(m => m.EmailDetails.EmailType, Model.EmailDetails.EmailTypeCodes)%>
                <%: Html.ValidationMessageFor(model => model.EmailDetails.EmailType)%>
            </div>
        <p>
            <input type="submit" id="EmailSave" value="Save" />
            <input type="submit" name="button" id="EmailCancel" value="Cancel" />
        </p>
        </fieldset> 
    <% } %> 
    </div>

    <fieldset>
        <legend>All Telephone/Fax Details</legend>
        <table>
            <tr>
                <th>Edit</th>
                <th>Dialing Code</th>
                <th>Telephone/Fax Number</th>
                <th>Delete</th>
            </tr>
            <% foreach (var telFaxSummary in Model.TelephoneFaxSummaries)
               { %>
            <tr>
                <%: Html.Hidden(telFaxSummary.TelephoneFaxId.ToString())%>
                <td>
                   <a href="<%:ResolveUrl(telFaxSummary.EditUrl.OriginalString)%>" >Edit</a>
                </td>
                <td>
                    <%: telFaxSummary.DialingCode%>
                </td>
                <td>
                    <%: telFaxSummary.TelephoneFaxNumber%>
                </td>
                <td>
                  <a href="<%:ResolveUrl(telFaxSummary.DeleteUrl.OriginalString)%>" class="confirmDelete">Delete</a>
                </td>
            </tr>
            <% } %>
        </table>
    </fieldset>

    <% using (Html.BeginForm("TelephoneFaxDetails", "Contact", FormMethod.Post))
       {%>
        <div id="TelephoneFaxDetails">
        <%: Html.HiddenFor(m => m.TelFaxDetails.TelephoneFaxId)%>
        <%: Html.HiddenFor(m => m.TelFaxDetails.ContactId)%>
        <fieldset>
                <legend>Telephone/Fax</legend>
        <div class="editor-field">
            <div id="left" class="left">
                <%: Html.LabelFor(m => m.TelFaxDetails.InternationalDialingCode)%>
                <%: Html.TextBoxFor(m => m.TelFaxDetails.InternationalDialingCode)%>
                <%: Html.ValidationMessageFor(model => model.TelFaxDetails.InternationalDialingCode)%>
            </div>
            <div id="middle" class="right">
                <%: Html.LabelFor(m => m.TelFaxDetails.TelephoneFaxNumber)%>
                <%: Html.TextBoxFor(m => m.TelFaxDetails.TelephoneFaxNumber)%>
                <%: Html.ValidationMessageFor(model => model.TelFaxDetails.TelephoneFaxNumber)%>
            </div>
        </div>
            <p>
                <input type="submit" id="TelephoneSave" value="Save" />
                <input type="submit" name="button" id="TelephoneCancel" value="Cancel" />
            </p>
        </fieldset> 
    <% } %>
    </div>

А затем мой метод контроллера, чтобы добавить новый адрес электронной почты:

    [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);
    }

Таким образом, идея заключается в том, что если я возьму всю ContactViewModel в сообщение электронной почты, то, если модель недействительна, тогда я смогу вернуть все детали ContactViewModel, которые будут содержать основные контактные данные и данные электронной почты, которые пользователь просто ввод, чтобы они не потеряли данные. Детали электронной почты передаются в контроллер в порядке, однако все основные контактные данные при передаче в контроллер равны нулю - есть идеи?

Ответы [ 2 ]

1 голос
/ 09 декабря 2010

IMO, это будет неосуществимо в том, что касается вашего сценария, я имею в виду, что когда вы публикуете 2-ю форму (EmailDetails), вы публикуете только эту ФОРМУ, так что, что бы ни попадало в СФЕРУ ее использования, она переходила только на СЕРВЕР.

Таким образом, в таком случае вы можете выбрать Ajax для сохранения / проверки отдельного набора полей (Электронная почта, Все данные телефона / факса) или отдельного ascx.

0 голосов
/ 30 декабря 2010

Ваши параметры ограничены, я боюсь:

  • Вы должны либо опубликовать одну большую форму, это единственная возможность сохранить все значения.
  • Или вы можете иметь только один из них редактируемый одновременно.Но заставлять пользователя публиковать три раза, вероятно, не то, что вам нужно.

Один из подходов, который сделает ваш код немного приятнее, - это перепроектировать модель, чтобы иметь три свойства.Один для каждой «формы»:

public class ContactDetailsViewModel
{
    public ContactDetails Basics { get; set; }
    public EmailDetails Email { get; set; }
    public PhoneDetails Phone { get; set; }
}

Затем можно создать частичное представление для каждого свойства.Или пользовательский шаблон редактора.Это сделает вашу основную разметку немного чище.

...