Я использую 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 и есть ли более подходящий способ решить эту проблему? Или я могу не смешивать данные модели с одной формой????
Прежде всего, использовать 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