Ответ 1
Мы имеем аналогичную ситуацию в одном из наших приложений, где каждый SomeSubModel
представляет параметр для задания. Поскольку каждый тип задания имеет различное количество и типы параметров, наша модель задания имеет набор этих параметров, а не только заданные свойства.
У нас есть JobParameter
, который подклассифицирован в различные доступные типы (StringParameter
, BoolParameter
, DoubleParameter
,...). Эти подклассы имеют свои собственные атрибуты проверки.
Для передачи параметров в представление используется общий "JobParameterModel".
Для проверки возвращенная модель преобразуется в ее конкретный параметр JobParameter.
ParameterTypes:
public enum ParameterType
{
Empty = 0,
Boolean = 1,
Integer = 2,
String = 3,
DateTime = 4,
...
}
JobParameter:
class JobParameter
{
[AValidationAttributeForAllParamters]
public string Name { get; set; }
public virtual string Foo { get; set; }
public int Number { get; set; }
public ParameterType Type {get;set;}
private static readonly IDictionary<ParameterType, Func<object>> ParameterTypeDictionary =
new Dictionary<ParameterType, Func<object>>{
{ParameterType.Empty, () => new EmptyParameter() },
{ParameterType.String, ()=>new StringParameter()},
{ParameterType.Password, ()=>new PasswordParameter()},
...
};
public static ScriptParameter Factory(ParameterType type)
{
return (ScriptParameter)ParameterTypeDictionary[type]();
}
}
BoolParameter:
[ABoolClassLevelValidationAttribute]
class BoolParameter:JobParameter
{
[AValidationAttribute]
public override string Foo {get;set;}
}
....
В нашей структуре проверки (которая, как мне сказали, очень хорошо моделируется с MS), ViewModel всегда преобразуется обратно в объект своего домена для проверки.
ПараметрМодель:
class ParameterModel: JobParameter
{
public JobParameter ToDomain()
{
var domainObject = JobParameter.Factory(Type);
Mapper.Map(this, domainObject);
return domainObject;
}
public bool Validate()
{
var dom = ToDomain();
return TryValidate(dom);
}
}
Контроллер:
class Controller(){
[HttpPost]
public ActionResult SaveParameter(JobParameter model){
if(TryValidateModel(model)){
//persist stuff to db.
//when succesfully saved return to main display page
return RedirectToAction("MainDisplay");
}
return View(main.Prop1);
}
}
Для вашей конкретной ситуации вам не нужно усложнять эту сложность (или доверять тому, что специфика нашей системы проверки будет работать для вас).
Редактировать/Сохранить действия для каждого Prop:
Создайте модель проверки для каждой опоры. Prop1ValidationModel
, Prop2ValidationModel
[HttpGet]
public ActionResult EditProp1()
{
var main = db.retrieveMainModel();
db.Prop1.SubmitUrl = Url.Action("SaveProp1","Controller");
return View(main.Prop1);
}
[HttpPost]
public ActionResult SaveProp1(SomeSubModel model){
var validationModel = new Prop1ValidationModel{
///copy properties
};
if(TryValidateModel(validationModel)){
var main = db.retrieveMainModel();
main.Prop1 = model;
db.Save();
//when succesfully saved return to main display page
return RedirectToAction("MainDisplay");
}
return View(main.Prop1);
}
С этим вы можете использовать тот же строго типизированный вид для Prop1 и Prop2.