MVCラーニングシリーズ-フォームデータ提出
Asp.Net MVCプロジェクトでは、Viewがページの展示・収集を担当し、展示されたデータはControllerのActionから取得し、収集したデータをControllerのActionに提出する.ここでのデータは、ベースタイプ、モデル、モデルの一部、リストやDictionaryなどの集合である可能性があります.
データがViewからControllerのActionに渡される場合、以下のようになります.
1.ルートデータ
2.QueryString(http getのクエリパラメータは?page=2など)
3.Forms(フォームpostのデータ)、
4.またはajaxインタラクションのjsonデータ.
ControllerのActionでは、これらのViewが渡すデータを常に取得し、Actionが望むタイプにバインドすることが望ましい.これらのタイプは、Actionのベースタイプパラメータであるか、更新する必要があるModelであるか、Modelの一部のみを更新するか、リストやDictionaryのようないくつかの集合の構造である可能性があります.
以下に、ViewTransferのデータを取得する方法をいくつか挙げます.
方法1.
Asp.Net Mvcビルド機能(DefaultModelBinder)は、単純タイプ、複雑タイプ、集合タイプ、辞書タイプの自動バインドを実現します.
1.単純タイプ
次のBookクラスを単純なタイプと呼びます.
データがViewからControllerのActionに渡される場合、以下のようになります.
1.ルートデータ
2.QueryString(http getのクエリパラメータは?page=2など)
3.Forms(フォームpostのデータ)、
4.またはajaxインタラクションのjsonデータ.
ControllerのActionでは、これらのViewが渡すデータを常に取得し、Actionが望むタイプにバインドすることが望ましい.これらのタイプは、Actionのベースタイプパラメータであるか、更新する必要があるModelであるか、Modelの一部のみを更新するか、リストやDictionaryのようないくつかの集合の構造である可能性があります.
以下に、ViewTransferのデータを取得する方法をいくつか挙げます.
方法1.
public ActionResult Create()
{
Recipe recipe = new Recipe();
recipe.Name = Request.Form["Name"];
// ...
return View();
}
方法2.public ActionResult Create(FormCollectionvalues)
{
Recipe recipe = new Recipe();
recipe.Name = values["Name"];
// ...
return View();
}
方法3.Asp.Net Mvcビルド機能(DefaultModelBinder)は、単純タイプ、複雑タイプ、集合タイプ、辞書タイプの自動バインドを実現します.
1.単純タイプ
次のBookクラスを単純なタイプと呼びます.
<pre name="code" class="csharp"><pre name="code" class="csharp">public class Book
{
public int BookId { get; set; }
public string BookName { get; set; }
public string Author { get; set; }
public DateTime PublishedDate { get; set; }
}
public ActionResult Create(Book book) {
//TO DO
//Insert book into Database
return RedirectToAction("Index");
}
对应的View页面代码如下:
<div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book Name: <%=Html.TextBox("BookName")%> </div> <div> Author: <%=Html.TextBox("Author")%> </div> <div> Published Date: <%=Html.TextBox("PublishedDate")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
注意TextBoxのnameは、バインドタイプに対応するPropertyName(大文字と小文字を区別しない)である必要があります.これにより、ページフォームsubmitの後、BookControllerの「Create」アクションで自動的にバインドされたbookオブジェクトを得ることができます.ここ、Asp.Net Mvcは、TextBoxのnameに変数名の接頭辞を付ける場合もサポートします.<pre name="code" class="html"><pre name="code" class="html"><div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book Name: <%=Html.TextBox("book.BookName")%> </div> <div> Author: <%=Html.TextBox("book.Author")%> </div> <div> Published Date: <%=Html.TextBox("book.PublishedDate")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
2. 复杂类型
现在对Book类作些许改动,并引入Author类
public class Book { public int BookId { get; set; } public string BookName { get; set; } public Author Author { get; set; } public DateTime PublishedDate { get; set; } } public class Author { public int AuthorId { get; set; } public string AuthorName { get; set; } public string Nation { get; set; } }
対応するViewページのコードは次のとおりです.<div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book Name: <%=Html.TextBox("BookName")%> </div> <div> Published Date: <%=Html.TextBox("PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("Author.AuthorName")%> </div> <div> Author's Nation: <%=Html.TextBox("Author.Nation")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
3.集合タイプ
問題の複雑化を避けるために、元の簡単なBookタイプに戻ります.<span style="font-size:12px;">public class Book { public int BookId { get; set; } public string BookName { get; set; } public string Author { get; set; } public DateTime PublishedDate { get; set; } }</span><span style="font-size: 14px;"> </span>
次に、BookControllerの「Create」アクションをIListを受信するパラメータに変更します. public ActionResult Create(IList<Book> books) { //TO DO //Insert book into Database return RedirectToAction("Index"); }
Viewでは、IListタイプを自動的にバインドするために、次の命名規則を使用します. <div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book Name: <%=Html.TextBox("books[0].BookName")%> </div> <div> Published Date: <%=Html.TextBox("books[0].PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("books[0].Author")%> </div> <div> Book Name: <%=Html.TextBox("books[1].BookName")%> </div> <div> Published Date: <%=Html.TextBox("books[1].PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("books[1].Author")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
Actionの変数名「books」に接頭辞として括弧とインデックスを付け、インデックスは0から開始し、連続しなければならないというルールが表示されます.この命名規則により、IList、ICollection 、IEnumerable 、List 、Book[]など、任意の集合タイプをバインドできます.
4.辞書の種類
単純なBookタイプを例にとり、「Create」アクションを受信IDictionaryタイプに変更しました. 対応するViewページのコードは次のとおりです.public ActionResult Create(IDictionary<string, Book> books) { //TO DO //Insert book into Database return RedirectToAction("Index"); }
<pre name="code" class="html"><pre name="code" class="html"><pre name="code" class="html"><div> <%using (Html.BeginForm("Create", "Book")) { %> <div> Book SN: <%=Html.TextBox("books[0].Key") %> </div> <div> Book Name: <%=Html.TextBox("books[0].Value.BookName")%> </div> <div> Published Date: <%=Html.TextBox("books[0].Value.PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("books[0].Value.Author")%> </div> <div> Book SN: <%=Html.TextBox("books[1].Key") %> </div> <div> Book Name: <%=Html.TextBox("books[1].Value.BookName")%> </div> <div> Published Date: <%=Html.TextBox("books[1].Value.PublishedDate")%> </div> <div> Author's Name: <%=Html.TextBox("books[1].Value.Author")%> </div> <div> <input type="submit" id="submit" name="submit" value="submit" /> </div> <%} %> </div>
可以看出,对于IDictioinary<Book>类型,在命名规则上,相比于集合类型,多了"Key"和"Value”的字眼。另,此规则也适用于Action参数类型为Dictionary<Book>的情形。简单类型、复杂类型、集合类型,以及字典类型 还能混合着用,而且绑定的数据来源也不局限于Form提交的表达数据,还可以是RouteData(url中的路由数据),QueryString(http get的查询参数如?page=2),或者ajax交互的json数据。
所以,只要我们遵循一定的命名规则,灵活的运用DefaultModelBinder 就可以轻松实现各种类型的自动绑定了。
5.TryUpdateModel/UpdateModel
Mvc中经常遇到的一个典型用例是View通过From或者Ajax提交数据更新相应的Model,或者更新Model的部分内容,并且需要检查提交的数据对于Model的数据约束是否有效。这个时候TryUpdateModel就有用武之地了,它可以设置需要更新模型属性列表的(白名单)或要排除属性的列表(黑名单) 先看更新相关模型的所有属性:
publicActionResult Edit(int id, FormCollection collection) { var oldData = _r.GetSingleData(id); if(TryUpdateModel(oldData, collection.AllKeys)) { _r.Save(); } }
ID、Name以外のModel属性を更新するには:publicActionResult Edit(Guid id, FormCollection collection) { var oldData = _r.GetSingleData(id); if(TryUpdateModel(oldData,"", collection.AllKeys,newstring[]{"ID","Name"})) { _r.Save(); } } publicActionResult Save() { Customer customer =newCustomer(); try { UpdateModel(customer,new[] {"Name","Email", "Phone","Deposit"}); return RedirectToAction("..."); } catch(InvalidOperationException) { returnView(customer); } }
UpdateModelとTryUpdateModelには、さまざまな柔軟な運用のために多くのリロード形式があり、モデルバインドデータにエラーがあるかどうかを自動的にチェックし、エラーがあれば自動的にModelStateに追加し、ページにヒントを与えます.
参照先:https://msdn.microsoft.com/zh-cn/library/system.web.mvc.controller_methods(v=vs.118).aspx
MVC学習シリーズ-Urlのルーティングルールを理解する
MVC学習シリーズ-HTMLヘルプの使用
MVCラーニングシリーズ-フォームの非同期コミット
MVCラーニングシリーズ-ViewDataとViewBag
MVCラーニングシリーズ-フォームデータの検証