Проблема
Я знаю, что существует много способов проверки модели в MVC, и есть довольно много документации по этой теме. Однако я не совсем уверен, что лучший подход для проверки свойств Model, которые являются "Sub Model" того же типа.
Помните следующее
- Я все еще хочу получать прибыль от методов
TryUpdateModel/TryValidateModel - Каждая из этих "подмодулей" имеет строго типизированные представления
- Существует один строго типизированный вид для класса
MainModel, который отображает общий вид отображения
Это может показаться немного запутанным, но я пролью код, чтобы уточнить. Возьмем в качестве примера следующие классы:
MainModel:
class MainModel{
public SomeSubModel Prop1 { get; set; }
public SomeSubModel Prop2 { get; set; }
}
SomeSubModel:
class SomeSubModel{
public string Name { get; set; }
public string Foo { get; set; }
public int Number { get; set; }
}
MainModelController:
class MainModelController{
public ActionResult MainDisplay(){
var main = db.retrieveMainModel();
return View(main);
}
[HttpGet]
public ActionResult EditProp1(){
//hypothetical retrieve method to get MainModel from somewhere
var main = db.retrieveMainModel();
//return "submodel" to the strictly typed edit view for Prop1
return View(main.Prop1);
}
[HttpPost]
public ActionResult EditProp1(SomeSubModel model){
if(TryValidateModel(model)){
//hypothetical retrieve method to get MainModel from somewhere
var main = db.retrieveMainModel();
main.Prop1 = model;
db.Save();
//when succesfully saved return to main display page
return RedirectToAction("MainDisplay");
}
return View(main.Prop1);
}
//[...] similar thing for Prop2
//Prop1 and Prop2 could perhaps share same view as its strongly
//typed to the same class
}
Я считаю, что этот код имеет смысл до сих пор (исправьте меня, если это не так), потому что TryValidateModel() проверяет модель без ValidationAttribute.
Проблема здесь, где было бы лучшее место, или что было бы лучшим и самым элегантным способом иметь различные ограничения проверки для Prop1 и Prop2, все еще пользуясь преимуществами TryValidateModel() и не заполняя метод Edit условными операторами и ModelState.AddModelError()
Обычно вы можете иметь атрибуты проверки в классе SomeSubModel, но в этом случае это не сработает, потому что для каждого свойства существуют разные ограничения.
Другой вариант заключается в том, что в классе MainModel может быть атрибут пользовательской проверки, но он также не будет работать в этом случае, потому что объект SomeSubModel передается непосредственно в представление, и когда проверка не имеет ссылки на его MainModel объект.
Единственная левая опция, о которой я могу думать, - это ValidationModel для каждого свойства, но я не совсем понимаю, какой был бы лучший подход для этого.
Решение
Здесь решение я реализовано на основе ответа @MrMindor.
Base ValidationModel class:
public class ValidationModel<T> where T : new()
{
protected ValidationModel() {
this.Model = new T();
}
protected ValidationModel(T obj) {
this.Model = obj;
}
public T Model { get; set; }
}
Модель валидации для Prop1
public class Prop1ValidationModel:ValidationModel<SomeSubModel>
{
[StringLength(15)]
public string Name { get{ return base.Model.Name; } set { base.Model.Name = value; } }
public Prop1ValidationModel(SomeSubModel ssm)
: base(ssm) { }
}
Модель валидации для Prop2
public class Prop2ValidationModel:ValidationModel<SomeSubModel>
{
[StringLength(70)]
public string Name { get{ return base.Model.Name; } set { base.Model.Name = value; } }
public Prop2ValidationModel(SomeSubModel ssm)
: base(ssm) { }
}
Действие
[HttpPost]
public ActionResult EditProp1(SomeSubModel model){
Prop1ValidationModel vModel = new Prop1ValidationModel(model);
if(TryValidateModel(vModel)){
//[...] persist data
//when succesfully saved return to main display page
return RedirectToAction("MainDisplay");
}
return View(model);
}