ASP.NET MVC 2 プレビュー 1 - 複雑なモデル オブジェクトを使用した DataAnnotation 検証
-
21-09-2019 - |
質問
モデルに独自の検証を処理させる機能のおかげで、私は MVC 2 プレビュー リリースを試し始めることになりました。今のところ、検証スキームのシンプルさが気に入っています。しかし、障害に遭遇してしまいました。この検証スタイルは、単純な View Model オブジェクトに対しては適切に機能します。たとえば、という名前のモデルオブジェクトがあるとします。 車 新しい車を作成するためのビューを作成しようとしています。
- - -モデル - - - -
public class Car
{
public string Id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
}
- - -コントローラ - - - - -
public class CarController : Controller
{
public ActionResult Create()
{
Car myCar = new Car();
return View("Create", myCar);
}
[HttpPost]
public ActionResult Create(Car myCar)
{
if (!ModelState.IsValid)
{
return View("Create", myCar);
}
//Do something on success
return View("Index");
}
}
- - - -ビュー - - - - - - -
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Car>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<%
using (Html.BeginForm()) {%>
<fieldset>
<legend>Edit User Profile</legend>
<p>
<label for="Id">Id:</label>
<%= Html.TextBox("Id", Model.Id)%>
<%= Html.ValidationMessage("Id") %>
</p>
<p>
<label for="Name">Name:</label>
<%= Html.TextBox("Name", Model.Name)%>
<%= Html.ValidationMessage("Name") %>
</p>
<p>
<label for="Color">Color:</label>
<%= Html.TextBox("Color", Model.Color)%>
<%= Html.ValidationMessage("Color") %>
</p>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
</asp:Content>
これは魔法のように機能します。しかし、私の見解、さらに言えばモデルオブジェクトのすべてが単純であるわけではありません。次のような車のモデル オブジェクトがあるとします。
- - -モデル - - - -
public class PaintScheme
{
public int Red { get; set; }
public int Blue { get; set; }
public int Green { get; set; }
}
public class Car
{
public string Id { get; set; }
public string Name { get; set; }
public PaintScheme Paint{ get; set; }
}
- - - -ビュー - - - - - - -
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Car>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<%
using (Html.BeginForm()) {%>
<fieldset>
<legend>Edit User Profile</legend>
<p>
<label for="Id">Id:</label>
<%= Html.TextBox("Id", Model.Id)%>
<%= Html.ValidationMessage("Id") %>
</p>
<p>
<label for="Name">Name:</label>
<%= Html.TextBox("Name", Model.Name)%>
<%= Html.ValidationMessage("Name") %>
</p>
<p>
<label for="Red">Color Red:</label>
<%= Html.TextBox("Red", Model.Paint.Red)%>
<%= Html.ValidationMessage("Red") %>
</p>
<p>
<label for="Blue">Color Blue:</label>
<%= Html.TextBox("Blue", Model.Paint.Blue)%>
<%= Html.ValidationMessage("Blue") %>
</p>
<p>
<label for="Green">Color Green:</label>
<%= Html.TextBox("Green", Model.Paint.Green)%>
<%= Html.ValidationMessage("Green") %>
</p>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
</asp:Content>
を追加すると、 ペイントスキーム 私のビューにプロパティを追加しても、コントローラー アクションに渡される「myCar」オブジェクトには引き継がれません。フォームコレクションからオブジェクトを再構築してModelStateをチェックすることなく、これを解決する方法はありますか?
解決
- 持っているはずです パブリックセッター バインドしたいプロパティの場合。すべてが非公開であるため、最初のサンプルがどのように機能するのか疑問に思います。
- あなたがしなければならない 少なくとも 1 つの値を投稿します PaintScheme プロパティをバインドできるようにします。
- すべての子プロパティには接頭辞を付ける必要があります。 パス それに。どこ パス *(PropertyName.)** として定義できます。
View では 3 の点が満たされていないようです。ビューの適切な部分を次のように変更します。
<p>
<label for="Red">Color Red:</label>
<%= Html.TextBox("Paint.Red")%>
<%= Html.ValidationMessage("Red") %>
</p>
<p>
<label for="Blue">Color Blue:</label>
<%= Html.TextBox("Paint.Blue")%>
<%= Html.ValidationMessage("Blue") %>
</p>
<p>
<label for="Green">Color Green:</label>
<%= Html.TextBox("Paint.Green")%>
<%= Html.ValidationMessage("Green") %>
</p>
さらに、NullReferenceException の発生を避けるために、TextBox ヘルパーから明示的な値を削除したことに注意してください。
他のヒント
これに対処する最も簡単な方法は、DTOを使用してモデルを平坦化することです。次に、あなたのビューモデルにあなたのドメインオブジェクトをマップするためにautomapperを使用しています。この変換は、文字列や背中に列挙型を変換するような方法で定義することができます。そして、検証が動作すると、あなたのBOMはかなりよく懸念のあなたの別離を維持するビューには触れません。
色の部分については、あなたがこのようなものを持つことができ、 私はあなたがテキストボックスを使用すると思ういけないint型であることが、これはあなたの赤い色をバインドします(入力値が数値の場合)
<p>
<label for="Red">Color:</label>
<%= Html.TextBox("Red", Model.Paint.Red)%>
<%= Html.ValidationMessage("Red") %>
</p>