問題
MVC 内でモデルの検証を行う方法はたくさんあり、このトピックに関するドキュメントもたくさんあります。ただし、同じタイプの「サブモデル」であるモデルのプロパティを検証するための最良のアプローチが何であるかはよくわかりません。
次のことに注意してください
TryUpdateModel/TryValidateModel
私はまだメソッドの利益を得たいです- これらの「サブモデル」にはそれぞれ、厳密に型指定されたビューがあります
MainModel
全体的な表示ビューをレンダリングする、クラスの厳密に型指定されたビューが 1 つあります。
少し混乱するかもしれませんが、明確にするためにいくつかのコードを挿入します。例として、次のクラスを取り上げます。
メインモデル:
class MainModel{
public SomeSubModel Prop1 { get; set; }
public SomeSubModel Prop2 { get; set; }
}
一部のサブモデル:
class SomeSubModel{
public string Name { get; set; }
public string Foo { get; set; }
public int Number { get; set; }
}
メインモデルコントローラー:
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
。
問題はここにあります。最適な場所はどこか、また、Edit メソッドを条件付きステートメントで埋めずに利用しながら、 andにさまざまな検証制約を設定するための最良かつ最も洗練された方法はどこにあるでしょうか。Prop1
Prop2
TryValidateModel()
ModelState.AddModelError()
通常、クラスに検証属性を含めることができますがSomeSubModel
、この場合は機能しません。プロパティごとに異なる制約があるためです。
他のオプションは、クラスにカスタム検証属性が存在する可能性があることですが、オブジェクトがビューに直接渡され、検証時にそのオブジェクトへの参照がないMainModel
ため、この場合も機能しません。SomeSubModel
MainModel
私が考えることができる唯一の残されたオプションは、各プロパティの ValidationModel ですが、これに対する最善のアプローチが何であるかはよくわかりません。
解決
@MrMindorの回答に基づいて、私が実装したソリューションを次に示します。
基本 ValidationModel クラス:
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);
}