Реализация ViewModel в ASP.NET MVC - является ли этот код лучшей практикой?
Я только начал использовать ViewModels. Вы можете проверить этот код, чтобы узнать, следую ли я лучшей практике? Есть что-то необычное? Вы бы сделали проверку по-другому?
Извините, если код длинный (есть так много частей к нему). Я пытался сделать так, чтобы это было так же легко понять, как вероятный.
спасибо!
модель
public class CustomerModel
{
[Required(ErrorMessage="Primer nombre!")]
public string FirstName { get; set; }
[Required(ErrorMessage="Segundo nombre!")]
public string LastName { get; set; }
[Required(ErrorMessage="Edad")]
public int? Age { get; set; }
public string State { get; set; }
public string CountryID { get; set; }
[Required(ErrorMessage="Phone Number")]
public string PhoneNumber { get; set; }
}
ViewModel
public class CustomerViewModel
{
public CustomerModel Customer { get; set; }
public string Phone1a { get; set; }
public string Phone1b { get; set; }
public string Phone1c { get; set; }
}
контроллер
public ActionResult Index()
{
CustomerViewModel Customer = new CustomerViewModel()
{
Customer = new CustomerModel(),
};
return View(Customer);
}
[HttpPost]
public ActionResult Index(CustomerViewModel c)
{
//ModelState.Add("Customer.PhoneNumber", ModelState["Phone1a"]);
// Let's manually bind the phone number fields to the PhoneNumber properties in
// Customer object.
c.Customer.PhoneNumber = c.Phone1a + c.Phone1b + c.Phone1c;
// Let's check that it's not empty and that it's a valid phone number (logic not listed here)
if (!String.IsNullOrEmpty(c.Customer.PhoneNumber))
{
// Let's remove the fact that there was an error!
ModelState["Customer.PhoneNumber"].Errors.Clear();
} // Else keep the error there.
if (ModelState.IsValid)
{
Response.Write("<H1 style'background-color:white;color:black'>VALIDATED</H1>");
}
return View("Index", c);
}
}
посмотреть
@model MVVM1.Models.CustomerViewModel
@using (Html.BeginForm("Index", "Detail"))
{
<table border="1" cellpadding="1" cellspacing="1">
<tr>
<td>@Html.LabelFor(m => m.Customer.FirstName)</td>
<td>
@Html.TextBoxFor(m => m.Customer.FirstName)
@Html.ValidationMessageFor(m => m.Customer.FirstName)
</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Customer.LastName)</td>
<td>
@Html.TextBoxFor(m => m.Customer.LastName)
@Html.ValidationMessageFor(m => m.Customer.LastName)
</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Customer.Age)</td>
<td>
@Html.TextBoxFor(m => m.Customer.Age)
@Html.ValidationMessageFor(m => m.Customer.Age)
</td>
</tr>
<tr>
<td>@Html.LabelFor(m => m.Customer.PhoneNumber)</td>
<td width="350">
@Html.TextBoxFor(m => m.Phone1a, new { size="4", maxlength="3" })
@Html.TextBoxFor(m => m.Phone1b)
@Html.TextBoxFor(m => m.Phone1c)
<div>
@Html.ValidationMessageFor(m => m.Customer.PhoneNumber)
</div>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Submit" /></td>
</tr>
</table>
}
3 ответов
одна вещь, которая выскакивает на меня это:
if (ModelState.IsValid)
{
Response.Write("<H1 style'background-color:white;color:black'>VALIDATED</H1>");
}
return View("Index", c);
помните, что модели просмотра хороши для передачи данных на контроллер и обратно в модель. Я рекомендую добавить свойство IsValid в модель представления, а затем установить значение true вместо вызова ответа.Писать. Затем просто добавьте это в верхнюю часть вашего частичного представления:
@if (Model.IsValid)
{
<H1 style'background-color:white;color:black'>VALIDATED</H1>
}
вы также можете получить в ModelState, на ваш взгляд, но некоторые утверждают, что это не лучшая практика. Однако, если вы не хотите добавить свойство в свою модель для чего-то, что вы можете просто увидеть в своем представлении, вы можете просто сделать это:
@if (ViewData.ModelState.IsValid)
еще одна nitpicky вещь заключается в том, что атрибуты проверки MVC являются обычно используется для проверки в пользовательском интерфейсе. Эта проверка может быть повторно использован в других областях, но в некоторых случаях является неоптимальным. Кроме того, вы не всегда сможете изменять модели домена. Поэтому, чтобы сохранить всю мою проверку пользовательского интерфейса в одном месте, я обычно обертываю свои модели домена в своем представлении моделей, так что вы получите что-то вроде этого:
public class CustomerViewModel
{
public CustomerModel Customer { get; set; }
[Required(ErrorMessage="Primer nombre!")]
public string FirstName
{
get { return Customer.FirstName; }
set { Customer.FirstName = value; }
}
...
это может показаться излишним и не всегда стоит усилий, но рекомендуется учитывать при использовании моделей домена Entity Framework или других классов, которые трудно или невозможно изменить.
Я просто получаю повесить MVC сам, но я исследовал эту же тему вчера и пришел к выводу, что не следует напрямую включать объект модели в ViewModel. Поэтому я понимаю, что было бы плохой практикой включать вашу CustomerModel непосредственно в CustomerViewModel.
вместо этого вы хотите перечислить каждое из свойств CustomerModel, которые вы хотите включить в свою ViewModel. Тогда вы либо хотите вручную сопоставить данные из CustomerModel к CustomerViewModel или использовать инструмент, как AutoMapper, который делает это автоматически со строкой кода, как это внутри вашего метода действия:
public ViewResult Example()
{
// Populate/retrieve yourCustomer here
Customer yourCustomer = new CustomerModel();
var model = Mapper.Map<CustomerModel, CustomerViewModel>(yourCustomer);
return View(model);
}
В этом случае, маппер.Map вернет CustomerViewModel, который вы можете передать в свой вид.
Вам также нужно будет включить следующее В метод Application_Start:
Mapper.CreateMap<CustomerModel, CustomerViewModel>();
В общем, я нашел AutoMapper довольно легко добраться до работы. Это автоматически, когда имена полей матч, если они не Или у вас есть вложенный объект, вы можете указать эти сопоставления в строке CreateMap. Поэтому, если ваша CustomerModel использует объект Address вместо отдельных свойств, вы должны сделать следующее:
Mapper.CreateMap<CustomerModel, CustomerViewModel>()
.ForMember(dest => dest.StreetAddress, opt => opt.MapFrom(src => src.Address.Street));
пожалуйста, кто-нибудь поправьте меня, если я ошибаюсь, так как я просто получаю свою голову вокруг MVC.
Я бы сказал, что ваша реализация ViewModel довольно стандартная. ViewModel используется в качестве промежуточного объекта между представлением и моделью домена. Что является хорошей практикой.
единственное, что я бы устал от того, как вы обрабатываете ошибки модели, а также ваша ViewModel должна иметь некоторые атрибуты. Например, вы можете использовать RegularExpressionAttribute
класс:
public class CustomerViewModel
{
public CustomerModel Customer { get; set; }
[RegularExpression(@"^\d{3}$")]
public string Phone1a { get; set; }
[RegularExpression(@"^\d{3}$")]
public string Phone1b { get; set; }
[RegularExpression(@"^\d{4}$")]
public string Phone1c { get; set; }
}