Нам всегда говорят, что Controller
должен быть тощим и что валидация должна быть выполнена в Model
, а не Controller
. Но рассмотрим следующий пример.Лучшая практика для проверки сложных случаев в ASP.NET/MVC?
Вот простой Model
и Controller
для обработки POST
с экрана редактирования, на котором можно отредактировать Person
объект.
public class PersonEditModel
{
[Required(ErrorMessage = "No ID Passed")]
public int ID { get; set; }
[Required(ErrorMessage = "First name Required")]
[StringLength(50,ErrorMessage = "Must be under 50 characters")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last name Required")]
[StringLength(50,ErrorMessage = "Must be under 50 characters")]
public string LastName { get; set; }
}
public class PersonController : Controller
{
// [HttpGet]View, [HttpGet]Edit Controller methods omitted for brevity
[HttpPost]
public ActionResult Edit(PersonEditModel model)
{
// save changes to the record
return RedirectToAction("View", "Person", new { ID = model.ID});
}
}
Model
выполняет здесь два вида проверки. Он проверяет FirstName
и LastName
, но он также проверяет закрытый ключ (ID
), используемый для доступа к записи, которую мы хотим изменить. Должна ли эта проверка быть сделана и в Model
?
Что делать, если мы хотим расширить проверку (как мы должны), чтобы включить проверку, чтобы увидеть, существует ли эта запись?
Обычно, я бы проверить это в контроллере:
[HttpPost]
public ActionResult Edit(PersonEditModel model)
{
using(DatabaseContext db = new DatabaseContext())
{
var _person = db.Persons.Where(x => x.ID == model.ID);
if(_person == null)
{
ModelState.AddError("This person does not exist!");
// not sure how we got here, malicious post maybe. Who knows.
// so since the ID is invalid, we return the user to the Person List
return RedirectToAction("List", Person");
}
// save changes
}
// if we got here, everything likely worked out fine
return RedirectToAction("View", "Person", new { ID = model.ID});
}
ли это плохая практика? Должен ли я проверять, существует ли запись в каком-то сложном пользовательском методе проверки в модели? Должен ли я разместить его где-то еще в другом месте?
UPDATE
На соответствующую записку. Должны ли в ViewModel
методы для заполнения данных?
Какой из них лучше практика - это
public class PersonViewModel
{
public Person person { get; set; }
public PersonViewModel(int ID){
using(DatabaseContext db = new DatabaseContext())
{
this.person = db.Persons.Where(x => x.ID == ID);
}
}
}
[HttpPost]
public ActionResult View(int ID)
{
return View("View", new PersonViewModel(ID));
}
Или это?
public class PersonViewModel
{
public Person person { get; set; }
}
[HttpPost]
public ActionResult View(int ID)
{
PersonViewModel model = new PersonViewModel();
using(DatabaseContext db = new DatabaseContext())
{
model.person = db.Persons.Where(x => x.ID == ID);
}
return View("View", model);
}
Что вы делаете в последнем примере, это не то, что я бы назвал валидацией. «PersonEditModel» по-прежнему действует. Проблема в том, что человека не существует. Это другая ошибка и правильно обрабатывается в контроллере. –
Это выглядит хорошо, никаких проблем. Если кто-то говорит «нет», спросите причину PLS :) –
Итак, это должно быть в контроллере? – roryok