値を入力されポストされた時のデータ渡し(Modelを使用している時)
前項では、1つのテキストボックスに入力された値のみのデータ渡しについてでしたが、例えば、レコードを作成するCreateページ内のテキストボックスの値を全て同じようにして値渡しをするのはあまり現実的ではありません。もし、入力項目の全てがModelで設定したレコードであった場合は、Modelそのものをパラメタとして渡すことができます。
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(titles Titles, FormCollection collection) { }
上記コードでは、ViewPage作成時に型付けたtitlesエンティティをそのままパラメタとして記述しました。これだけでOKです。ViewPage側で入力されたtitlesエンティティのレコードが格納されているので、そのまま処理内に利用できます。ただし、これはレコードを新規作成する時に利用できるだけで、レコードの一部を編集したい場合は、別途LINQによる詳細なレコード抽出などが必要になります。
なお、上記コードでは第2パラメタにFormCollection型を指定しています。FormCollection型は、ViewPage側で入力された項目全てのデータをNameValueCollection型と扱い、基本的な利用方法はNameValueCollectionクラスと変わりません。String型のキーとデータを同時に指定することで、データを格納します。このFormCollectionを利用すると、ViewPage側で、Model項目以外のデータも含めた全ての入力データを取得できます。ただし、Modelと次項で解説する自動バインドを利用すると効率的に解決できてしまうので、余り利用することはないかもしれません。
ハイパーリンククリック時(パラメタの自動バインド)
HtmlHelperクラスのActionLinkメソッドなどを活用して、別ページへルーティングされた時に、何らかの値を持たせ、それを利用してルーティング先のデータを取得したい場合があります。
例えば、タイトルID(title_id)をトリガーにし、Controller側でそのタイトルIDと一致する項目をLINQで取得するなどが考えられます。この時、汎用的にするためにはハイパーリンクのテキストを共通名(たとえばEdit、Details)に設定し、あくまでハイパーリンクのURLにタイトルIDを設定することが多いでしょう(例:/Pubs/Details/BU1032)。
この場合View側では以下のように記述します。
<%= Html.ActionLink("Details", "Details", new { id=item.title_id })%>
ActionLinkメソッドの第1パラメタにハイパーリンクのテキストを、第2パラメタにControllerのメソッド名、第3パラメタに匿名型を宣言し、title_idの値をController側へ値渡ししています。複数パラメタを渡したい場合は、渡すプロパティ名を文字列配列で指定します。
実行時は以下のようなソースに変換されます。
<a href="/Pubs/Details/BU1032">Details</a>
URLのパラメタにtitle_idの値が埋め込まれていることが確認できます。
Controller側では、このtitle_idをパラメタに記述することで値を受け取れます(パラメタの自動バインド)。
public ActionResult Details(string id) { // 処理 }
受け取った値は通常のメソッド同様にメソッド内で利用できるようになります。
以上がASP.NET MVCにおけるViewからControllerへのデータ渡しです。
UpdateModelメソッドとTryUpdateModelメソッド
UpdateModelメソッドとTryUpdateModelメソッドは、現在のModelを更新する機能を持ちます。例えば、フォーム全体の入力値でModelを更新する場合か、入力された値を基に新規レコードを作成する場合などに利用します。UpdateModelメソッド、TryUpdateModelメソッド共に、第1パラメタにModelの型を指定します。第2パラメタはModel内で更新したいプロパティを匿名型で指定すると、そのプロパティのみ更新されます。
UpdateModelメソッドは更新に失敗した場合例外が発生しますが、TryUpdateModelメソッドは例外ではなく、Boolean型を返して、エラーが起きたかどうかを示します。処理の結果から見ると、String型のParseメソッドとTryParseメソッドと同じといえます。
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create(titles Titles, FormCollection collection) { pubsEntities pubs = new pubsEntities(); try { // UpdateModel使用例 // 入力された内容をモデルの新規レコードとして更新 UpdateModel(Titles); <UpdateModelかTryUpdateModelどちらかを記述> // TryUpdateModelと特定プロパティのみ更新する例 // 入力された内容から幾つかの項目をモデルの新規レコードとして更新 TryUpdateModel(Titles, new[] { "advance", "price", "pubdate", "title", "title_id", "type" }); <中略> // 更新を反映させる pubs.SaveChanges(); return RedirectToAction("Index"); } catch { return View(); } }
UpdateModelとTryUpdateModelの使い方は上記のとおりです。ただし、それぞれ、Modelを更新はしますが、DBへの反映は行えません。DBへの反映はSaveChangesメソッド(EDM)や、SubmitChangesメソッド(LINQ to SQL)を使う必要があります。