Проблема
Я знаю, что существует много способов проверки модели в 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);
}