Каков подходящий метод для передачи 2 разных моделей в контроллер из представления в MVC4?

1

Я использую MVC4 с SimpleMembership. MVC настроил мою таблицу UserProfile, и я изменил вид регистрации, чтобы разместить мой макет. Все отлично работало, пока я не решил, что хочу добавить некоторую дополнительную информацию от моего пользователя, которая лучше всего подходит в контексте другой уже существующей модели.

Обычно мой подход к передаче более одной модели из моего представления в контроллер - это использование Tuples. Исторически это сработало для меня отлично, и до сих пор у меня никогда не было реальных проблем.

Моя Регистрационная Форма напоминает это:

@model Tuple<MyNamespace.Models.RegisterModel,MyNamespace.Models.MembershipDetail>

@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
@Html.AntiForgeryToken()     
    <table style="border-collapse: collapse; border-spacing:0px; border-width:0px; margin: 0px; width:100px; padding: 0 0 0 0px; background-color:#2e2e2e;">
        <tr>
           <td>
              Profile Name
           </td>
           <td>
              @Html.TextBoxFor(m => m.Item2.ProfileName)
           </td>
        </tr> 
        <tr>
           <td>
              @Html.LabelFor(m => m.Item1.UserName)
           </td>
           <td>
              @Html.TextBoxFor(m => m.Item1.UserName)
           </td>
        </tr>
        <tr>
           <td>
              @Html.LabelFor(m => m.Item1.Password)
           </td>
           <td>
              @Html.PasswordFor(m => m.Item1.Password)
           </td>
        </tr>
        <tr>
           <td>
              @Html.LabelFor(m => m.Item1.ConfirmPassword)
           </td>
           <td>
              @Html.PasswordFor(m => m.Item1.ConfirmPassword)
           </td>
        </tr>                               
        <tr>
           <td>
              <button type="submit" id="btnSubmitForm" value="Register">Register</button>
           </td>
        </tr>
     </table>
     @Html.Partial("_ValidationSummary",ViewData.ModelState)                             
   }    

Метод Register моего контроллера аналогичен этому:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Register(RegisterModel model, MembershipDetail member)
    {
        if (ModelState.IsValid)
        {
            try
             {
                // Do something with the data
             }
            catch(MembershipCreateUserException e)
            {
               ModelState.AddModelError("",ErrorCodeToString(e.StatusCode));
            }
        }
        return View(model);
    }

Всякий раз, когда я отлаживаю этот код после нажатия кнопки "Отправить", я отмечаю, что обе модели, возвращенные контроллеру, пусты. Содержащиеся поля имеют значение null, 0 или Empty Strings, и я не могу понять, почему.

Чтобы добавить к этой загадке, если я удалю кортеж из верхней части представления и повторно назначу его как одну модель как таковую:

@model MyNamespace.Models.RegisterModel

И замените ссылки кортежа из кода (egmItem1.Property, m.Item2.Property) с 1-й выводной выводной ссылкой (m.Property и т.д.); то данные, переданные из помощников TextBox, соответствующим образом назначаются модели, и модель заполняется, когда я отлаживаю код.

Теперь я знаю, что могу просто добавить несколько других полей в таблицу UserProfile и использовать их в своей модели для полного устранения Tuple, но затем я дублирую данные в своей схеме, которая не является идеальным решением. И имея в виду, что хотя мой пример кода, представленный здесь, содержит только 1 элемент 2-й модели, он будет фактически больше 1.

Итак, почему модели не заполняются при использовании Tuple и есть ли более подходящий способ решить эту проблему? Или я могу не смешивать данные модели с одной формой????

Теги:
asp.net-mvc
asp.net-mvc-4
asp.net-mvc-3

1 ответ

4
Лучший ответ

Прежде всего, использовать Tuple в качестве модели не рекомендуется, потому что читать код сложно. Для этого вам нужно написать собственные модели просмотра. Для этого примера:

 public class SomeViewModel{
         public RegisterModel RegisterModel { get; set;}
         public MembershipDetail MembershipDetail {get; set;}
 } 

его легко реализовать и будет работать по вашему желанию.

Однако, если вы хотите использовать Tuples на представлении в качестве модели.

Вы должны получить свое действие post, как

   public ActionResult Register(Tuple<RegisterModel,MembershipDetail> model)
   {
     .... // do something..
   }

Поскольку форма html будет создана как:

  <input name="Item1.ProfileName" />  

Вы можете увидеть, что он попытается отправить имя Item1.Profile, которое не поддерживается стандартным связующим устройством, чтобы преобразовать его в свои собственные классы.. он ожидает, что Tuple или класс вроде:.

   public class TheClass {
    public RegisterModel Item1 {get; set;}
    public MemberhipDetail Item2 {get; set;}
 }

которые в основном так же, как viewmodel

  • 0
    Благодарю. Я изменил свой код, используя ваше предложение, объединив обе модели в ViewModel, а затем изменил параметры контроллеров, чтобы они отображались следующим образом: public ActionResult Register (модель VMRegistration) {// Сделаем что-то здесь с model.RegisterModel.Property и model.MembershipDetail.Property} И данные сейчас присутствуют. Я приму этот ответ, так как он выглядит более элегантным способом обработки данных, но я бы хотел немного больше пояснить, почему метод Tuple не передал соответствующие данные в контроллер или, может быть, я что-то упустил.
  • 0
    Модуль связывания использует имена свойств для привязки данных, поэтому он ищет свойство, определенное как Item1 (которое у вас не было на первом месте в вашем методе actionresult), и привязывает к нему значения Item1.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню