1つのオプションは、異なるサブクラスを渡してビューを再利用することです。 Razorはアトリビュートを認識して、ビューに送信された具体的なタイプに従ってhtmlを生成します。
サブクラス化は、ソリューションの一部に過ぎません。 2番目の部分は、フォームがポストされると発生する必要があるモデルバインディングです。 コメントのいずれかで説明されているように、カスタムモデルバインダーを作成することで対応できます。 もう1つは、フォームのアクションを微調整して、フォームが正しいビューモデルタイプを処理できるアクションに投稿されるようにすることです。複数のアクションを持つことの利点は、アクションに対してカスタム検証を実装することが簡単になります。
複数のアクションを使用するのは、最も洗練された方法ではないかもしれません。悪い副作用があるかどうかはわかりません。
// This is the base class declared as the view's @model
// This one would have all the common validations
public class TestViewModel
{
public string ModelType { get; set; }
public virtual string Prop1 { get; set; }
public virtual string Prop2 { get; set; }
public virtual string Prop3 { get; set; }
}
public class TestViewModel1 : TestViewModel
{
[Required]
public override string Prop1 { get; set; }
}
public class TestViewModel2 : TestViewModel
{
[Required]
public override string Prop1 { get; set; }
[Required]
public override string Prop2 { get; set; }
}
とコントローラ:以下
は、サンプルビューモデルである
:
public class TestController : Controller
{
// GET: Test
public ActionResult Edit(string modelType)
{
if (modelType == "1") return View(new Models.TestViewModel1() {ModelType = "1"});
if (modelType == "2") return View(new Models.TestViewModel2() {ModelType = "2" });
return View(new Models.TestViewModel() { ModelType = "" });
}
[HttpPost]
public ActionResult Edit(Models.TestViewModel model)
{
if (model.Prop1 == null) ModelState.AddModelError("Prop1", "Please type something");
if (ModelState.IsValid) return RedirectToAction("Edit");
return View(model);
}
[HttpPost]
public ActionResult Edit1(Models.TestViewModel1 model)
{
if (model.Prop1 == null || !model.Prop1.Contains("1")) ModelState.AddModelError("Prop1", "Please type at least one character 1");
if (ModelState.IsValid) return RedirectToAction("Edit", new { modelType = "1" });
return View("Edit", model);
}
[HttpPost]
public ActionResult Edit2(Models.TestViewModel2 model)
{
if (model.Prop2 == null || !model.Prop1.Contains("2")) ModelState.AddModelError("Prop2", "Please type at least one character 2");
if (ModelState.IsValid) return RedirectToAction("Edit", new { modelType = "2"});
return View("Edit", model);
}
}
とビュー(@using(Html.BeginForm ..)を見て
@model WebApplication1.Models.TestViewModel
@{
Layout = null;
}
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
@using (Html.BeginForm("Edit" + Model.ModelType, "Test", new {Model.ModelType}))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>TestModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@DateTime.Now.ToString("o")
<br/>
@Html.LabelFor(m => m.ModelType)
@Html.DisplayFor(m => m.ModelType)
<hr />
<div class="form-group">
@Html.LabelFor(model => model.Prop1, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Prop1, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Prop1, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Prop2, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Prop2, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Prop2, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Prop3, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Prop3, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Prop3, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
1つのオプションは、条件付き検証属性を持つ単一のモデル/ビュー/アクションメソッドを使用することです。 e [foolproof](http://foolproof.codeplex.com/) '[RequiredIf]'またはそれに類する型の属性を使用します。別の方法は、モデルに '基本'クラス/インターフェースを使用し、カスタム 'ModelBinder'を作成して、POSTメソッドで具象クラスを生成することです。 –
恐ろしい!みんなありがとう!締め切り期限が過ぎたために私は完璧な道を進みましたが、これらはすべて良い提案でした。 – bigtri