更新日: 2011 年 1 月 14 日

執筆者: moonmile solutions、増田 智明

本連載では、日経 BP 社から発売された「ひと目でわかる ASP.NET MVC アプリケーション開発入門」をもとにして、執筆時に気づいたことや紙面の都合で書ききれなかった技術を紹介します。

目次

1. はじめに

2. ViewData プロパティはどこに使われている?

3. メッセージを変えてみる

4. ViewData を使わずに Model だけで書くと

5. カテゴリ名を表示させる

6. エラー メッセージを表示させる

7. ViewData プロパティの注意点

8. おわりに


1. はじめに

連載の第 3 回目は、コントローラー (Controller) からビュー (View) に直接データを渡すための ViewData プロパティ (ViewDataDictionary クラス) についてお話していきましょう。

MVC パターンでは、各コンポーネントの独立性を保つためにコントローラーからビューにデータを渡す場合は、モデルを使うことになっています。コントローラーでモデルに値を設定し、ビューがモデルを参照して画面に表示する手順になります。

このパターンを使うと、厳密にコンポーネントの独立性が高まる利点とともに、実際にプログラミングをするときに若干コードが冗長になってしまう欠点をあわせ持ってしまいます。

この弱点を補うための仕組みが ASP.NET MVC では、ViewData プロパティとして組み込まれています。

ページのトップへ


2. ViewData プロパティはどこに使われている?

では、早速 ViewData プロパティがどこに使われているのかを調べていきましょう。

実は、すでに知っていらっしゃる読者もおられると思いますが、Visual Studio 2010 で ASP.NET MVC 2 Web アプリケーションを作成すると、トップページ (Home/Index.aspx) には ViewData プロパティが使われています。

ASP.NET MVC 2 アプリケーションを作成して、ソリューション エクスプローラーで、Views/Home/Index.aspx というファイルを開いてみてください。

<ソース (C#)>

C#
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    ホーム ページ
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%: ViewData["Message"] %></h2>
    <p>
        ASP.NET MVC の詳細については、<a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a> を参照してください。
    </p>
</asp:Content>

<ソース (VB)>

Visual Basic
<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server">
    ホーム ページ
</asp:Content>

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%: ViewData("Message") %></h2>
    <p>
        ASP.NET MVC の詳細については、<a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a> を参照してください。
    </p>
</asp:Content>

ビューの中で、ViewData["Message"] (VB の場合は、ViewData("Message")) と記述されています。これが、ViewData プロパティを使って、コレクションから「Message」という名前で値を取り出しているところです。

同じように、ソリューション エクスプローラーで、Controllers/HomeController.cs (VB の場合は、HomeController.vb) を開いてみてください。

<ソース (C#)>

C#
public ActionResult Index() 
{ 
    ViewData["Message"] = "ASP.NET MVC へようこそ"; 
 
    return View(); 
} 
 

<ソース (VB)>

Visual Basic
Function Index() As ActionResult
    ViewData("Message") = "ASP.NET MVC へようこそ"

    Return View()
End Function

Index メソッドで、ViewData プロパティに「Message」という名前で値を代入していることがわかります。

これを実行すると、以下の図になります。

図 1. 実行結果

結果は見てわかるとおりです。「ASP.NET MVC へようこそ」というメッセージが出てきました。

ViewData プロパティの使い方は非常に簡単で、ViewData[ 名前 ] (VBasic では ViewData(名前)) という形式で、値を保存しておきます。コントローラーに値を入れておいて、ビューで同じ名前で値を取り出すという使い方になります。

もう少し詳しく MSDN のヘルプを使って調べてみましょう。

コントローラーの ViewData プロパティに値を入れておくと、ビューの ViewData プロパティに値がコピーされて、ビューから参照できるという仕組みになります。

図 2. 値のコピーの図

ASP.NET アプリケーションを作る方法として、もうひとつ Web フォーム ベースで作るアプリケーションがあります。Web フォーム ベースのアプリケーションでは、ビューと動作のコード (コード ビハイド) が同じクラスに属しているので、クラスにプロパティを作ることによってコードからビューへの値の受け渡しが簡単にできます。

ASP.NET MVC アプリケーションでは、ビュー (View) とモデル (Model) が別のクラスになるために、Web フォーム ベースのようにはいきませんが、上記のように ViewData プロパティを使うことにより、フォーム ベースと同じように値を渡すことが可能になっています。

ページのトップへ


3. メッセージを変えてみる

では、Index.aspx で表示するメッセージを変えてみましょう。

定番の「Hello ASP.NET MVC 2 World.」を表示させる場合は、次のようにコントローラーを書き換えます。

<ソース (C#)>

C#
public ActionResult Index() 
{ 
    ViewData["Message"] = "Hello ASP.NET MVC 2 World."; 
 
    return View(); 
} 
 

<ソース (VB)>

Visual Basic
Function Index() As ActionResult
    ViewData("Message") = "Hello ASP.NET MVC 2 World."

    Return View()
End Function

ビューのソース コードはそのままです。

これを Visual Studio 2010 で実行すると次の図になります。

図 3. 実行結果

これも予想通り、ViewData プロパティの値がうまく引き渡されていますね。

試しに Index.aspx の VIewData プロパティに指定している名前を「Message」から「MessageMiss」に変えてみましょう。名前が見つからないときには ViewData プロパティはどのような動作をするのでしょうか?

図 4. 実行結果 (Miss)

結果は、空白になります。「MessageMiss」のようにコントローラーで設定されていない名前をビューで指定してしまった時には、ViewData プロパティは null (VB の場合は Nothing) を返します。ここでは、「<%: ... %>」の表記の中で、自動で空白に変換されています。

このように、ViewData プロパティを使うと名前を間違ったときに、ミスが起こりやすいので注意してください。

ページのトップへ


4. ViewData を使わずに Model だけで書くと

今度は、あえて ViewData プロパティを使わずに、モデルを使ってメッセージを引き渡してみましょう。

まずは、HomeModels.cs (VB の場合は HomeModel.vb) を追加します。

モデルを追加する場合は、ソリューション エクスプローラーで Models フォルダーを右クリックして、「追加」→「クラス」を選択してください。クラス名は「HomeModels」にします。

図 5. モデルの追加

HomeModels クラスは以下のように Message プロパティだけを持つ簡単なクラスにします。

<ソース (C#)>

C#
namespace MvcApplication1.Models 
{ 
    public class MessageModels 
    { 
        public string Message { getset; } 
    } 
} 
 

<ソース (VB)>

Visual Basic
Public Class HomeModels
    Public Property Message As String
End Class

次のコントローラーで、HomeModel クラスの Message プロパティを使った方法を追記します。

<ソース (C#)>

C#
public ActionResult Index() 
{ 
    ViewData["Message"] = "Hello ASP.NET MVC 2 World."; 
 
    Models.HomeModels model = new Models.HomeModels(); 
    model.Message = "これはモデルを使ったメッセージです"; 
 
    return View(model); 
} 
 

<ソース (VB)>

Visual Basic
Function Index() As ActionResult
    ViewData("Message") = "Hello ASP.NET MVC 2 World."

    Dim model As New HomeModels
    model.Message = "これはモデルを使ったメッセージです"

    Return View(model)
End Function

HomeModels オブジェクトを作成して、Message プロパティにメッセージを代入しておきます。
モデルを使うために、アクション メソッドの戻り値の View クラスには model を渡しています。

最後に、ビューを書き換えて、HomeModels クラスの Message プロパティの内容を表示させます。
Views/Home/Index.aspx を削除して、ビューを追加してもよいですし、元の Index.aspx を手動で修正してもよいでしょう。


ビューを追加する場合は、「厳密に型指定されたビューを作成する」にチェックを入れて、ビュー データ クラスで「MvcApplication1.HomeModels」を選択してください。

図 6. ビューの追加

ビューを追加する場合は、「厳密に型指定されたビューを作成する」にチェックを入れて、ビュー データ クラスで「MvcApplication1.HomeModels」を選択してください。

コントローラーでビューを作成する処理 (return View(model)) の部分で、ビューに引き渡すモデルの型を指定します。ここで指定されたモデルは、ビューの先頭部分にある
Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.HomeModels>"
(VB の場合は、Inherits="System.Web.Mvc.ViewPage(Of
MvcApplication1.HomeModels)")
に記述されます。

これは、ビューで使う Model プロパティの型が「MvcApplication1.Models.HomeModels」であることを示しています。

<ソース (C#)>

C#
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.HomeModels>" %> 
 
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 
    ホーム ページ 
</asp:Content> 
 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 
    <h2><%: ViewData["Message"] %></h2> 
    <h2><%: Model.Message %></h2> 
    <p> 
        ASP.NET MVC の詳細については、<a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a> を参照してください。 
    </p> 
</asp:Content> 
 

<ソース (VB)>

Visual Basic
<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of MvcApplication1.HomeModels)" %>

<asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server">
    ホーム ページ
</asp:Content>

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%: ViewData("Message") %></h2>
    <h2><%: Model.Message%></h2>
    <p>
        ASP.NET MVC の詳細については、<a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a> を参照してください。
    </p>
</asp:Content>

「<%: Model.Message %>」の行を追加して、ViewData プロパティとの表示と並べておきます。

これを実行した結果が次の図になります。

図 7. 実行結果

このようにビューにメッセージを表示するたびに、モデルを変更するとだんだんとモデル自体が肥大化してしまいます。例えば、同じモデルを複数のビューで扱う場合、他のビューで使われないメッセージがプロパティとしてモデルに加わり見通しが悪くなります。

ビュー特有のメッセージなどは ViewData プロパティを通して表示し、ビューとは別の独立性の高いデータをモデルとするとコードの保守性がよくなります。

ページのトップへ


5. カテゴリ名を表示させる

ViewData プロパティの利点を更に紹介していきます。

モデルに Entity Data Model を直接利用している場合や自作のモデルに手を加えたくない場合にも ViewData プロパティは有効に働きます。

例えば、ショッピング サイトで、指定したカテゴリにある商品の一覧を表示させてみましょう。

まずは、ソリューション エクスプローラーを使って、モデルのクラスを作ります。
ソリューション エクスプローラーの「Models」フォルダーを右クリックし、「追加」→「新しい項目」を選択して、「新しい項目の追加」ダイアログを開きます。

このダイアログで、「インストールされたテンプレート」から「データ」を選択して、「ADO.NET Entity Data Model」を追加します。

ここで利用するデータベースは、日経 BP 社よりサンプル プログラムに入っています。サンプルをダウンロードして mvcdb.sql のスクリプトを使って、あらかじめ SQL Server 上にデータベースを作成しておいてください。

図 8. 新しい項目の追加ダイアログ ボックス

ここでは「Entity Data Model ウィザード」を使って、データベースから直接クラスを生成しました。

図 9. Entity Data Model ウィザード

正常に完了すると、モデルで使えるクラスが自動的に作られます。ここで一度ビルドをしておいてください。このビルドは、あとでコントローラーやビューでモデル参照を作るときに必要なものです。

ビルドが終わったら、Controllers/HomeController.cs (VB の場合は HomeController.vb) を開き Category アクション メソッドを作成します。

<ソース (C#)>

C#
public ActionResult Category( int id) 
{ 
    mvcdbEntities ent = new mvcdbEntities(); 
    // 指定したカテゴリ内の商品を取得 
    var model = from t in ent.TProduct 
                where t.cateid == id 
                select t; 
    // カテゴリの名称を取得 
    var name = (from c in ent.TCategory 
                where c.id == id 
                select c.name).Single(); 
    // ViewData に保存 
    ViewData["CategoryName"] = name; 
 
    return View(model); 
} 
 

<ソース (VB)>

Visual Basic
Function Category(ByVal id As Integer) As ActionResult
    Dim ent As New mvcdbEntities
    ' 指定したカテゴリ内の商品を取得
    Dim model = From t In ent.TProduct
                Where t.cateid = id
                Select t
    ' カテゴリ名称を取得
    Dim cname = (From c In ent.TCategory
                Where c.id = id
                Select c.name).Single
    ' ViewData に保存
    ViewData("CategoryName") = cname

    Return View(model)
End Function

ビューに引き渡す model には、データベースから検索した商品の一覧を設定しています。
追加の情報として、カテゴリの名称を ViewData プロパティを使ってビューに表示させることにします。

最後に、商品一覧を表示させる Views/Home/Category.aspx を作成します。
ビューの追加ダイアログ ボックスで、ビュー コンテンツから「List」を選択すると、一覧の表示が簡単にできます。

図 10. ビューの追加

ビューのタイトルには、カテゴリの名称を「<%: ViewData["CategoryName"] %>」で表示できるようにしておきます。

<ソース (C#)>

C#
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcApplication1.Models.TProduct>>" %> 
 
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 
    Category 
</asp:Content> 
 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 
 
    <h2><%: ViewData["CategoryName"] %></h2> 
 
    <table> 
        <tr> 
            <th></th> 
            <th> 
                id 
            </th> 
            <th> 
                name 
            </th> 
            <th> 
                price 
            </th> 
            <th> 
                cateid 
            </th> 
        </tr> 
 
    <% foreach (var item in Model) { %> 
     
        <tr> 
            <td> 
                <%: Html.ActionLink("Edit""Edit"new { id=item.id }) %> | 
                <%: Html.ActionLink("Details""Details"new { id=item.id })%> | 
                <%: Html.ActionLink("Delete""Delete"new { id=item.id })%> 
            </td> 
            <td> 
                <%: item.id %> 
            </td> 
            <td> 
                <%: item.name %> 
            </td> 
            <td> 
                <%: item.price %> 
            </td> 
            <td> 
                <%: item.cateid %> 
            </td> 
        </tr> 
     
    <% } %> 
 
    </table> 
 
    <p> 
        <%: Html.ActionLink("Create New""Create") %> 
    </p> 
 
</asp:Content> 
 

<ソース (VB)>

Visual Basic
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of MvcApplication1.TProduct))" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
	Category
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2><%: ViewData("CategoryName") %></h2>

    <p>
        <%: Html.ActionLink("Create New", "Create")%>
    </p>
    
    <table>
        <tr>
            <th></th>
            <th>
                id
            </th>
            <th>
                name
            </th>
            <th>
                price
            </th>
            <th>
                cateid
            </th>
        </tr>

    <% For Each item In Model%>
    
        <tr>
            <td>
                <%: Html.ActionLink("Edit", "Edit", New With {.id = item.id})%> |
                <%: Html.ActionLink("Details", "Details", New With {.id = item.id})%> |
                <%: Html.ActionLink("Delete", "Delete", New With {.id = item.id})%>
            </td>
            <td>
                <%: item.id %>
            </td>
            <td>
                <%: item.name %>
            </td>
            <td>
                <%: item.price %>
            </td>
            <td>
                <%: item.cateid %>
            </td>
        </tr>
    
    <% Next%>

    </table>

</asp:Content>

カテゴリ ID を指定して実行すると、次の図のようになります。
アドレスは、http://localhost/Home/Category/1 のように指定します。

図 11. 実行結果

商品の一覧とカテゴリの名称を同時に表示させたい場合、本来ならば新しいモデルを作成して、検索した商品の結果 (TProduct オブジェクトのリスト) とカテゴリの名称をビューに引き渡すところです。しかし、カテゴリの名称のような追加情報であれば、ViewData プロパティを使ったほうがコードが見やすくなります。

ページのトップへ


6. エラー メッセージを表示させる

もうひとつ、ViewData プロパティの使いどころを解説しておきます。

前回の記事で、商品の詳細ページを表示するときに商品 ID が指定されなかったときは、Redirect メソッドを使って指定のエラー メッセージを表示させていました。しかし、間違った商品番号などを指定した時には、エラー メッセージを変えたほうが利用者にとって便利ですよね。

今回は、カテゴリ内の商品を表示するときに、カテゴリ ID を指定しなかったり、間違えていたりしたときのメッセージを ViewData プロパティを使って変えていきましょう。

先ほど作成した、Category アクション メソッドを以下のように書き換えます。

<ソース (C#)>

C#
public ActionResult Category(int id = -1) 
{ 
    if (id == -1 ) 
    { 
        // カテゴリを指定しなかった場合 
        ViewData["ErrorMessage"] = "カテゴリIDを指定してください"; 
        return View("Error"); 
    } 
    mvcdbEntities ent = new mvcdbEntities(); 
     // カテゴリの名称を取得 
    var count = (from c in ent.TCategory 
                 where c.id == id 
                 select c.name).Count(); 
    if ( count == 0 )  
    { 
        // カテゴリIDが範囲を超えている場合 
        ViewData["ErrorMessage"] = 
            string.Format("カテゴリID({0})が正しくありません", id); 
        return View("Error"); 
    } 
    // 指定したカテゴリ内の商品を取得 
    var model = from t in ent.TProduct 
                where t.cateid == id 
                select t; 
    var name = (from c in ent.TCategory 
                 where c.id == id 
                 select c.name).Single(); 
    // ViewData に保存 
    ViewData["CategoryName"] = name; 
 
    return View(model); 
} 
 

<ソース (VB)>

Visual Basic
Function Category(Optional ByVal id As Integer = -1) As ActionResult
    If id = -1 Then
        ' カテゴリを指定しなかった場合
        ViewData("ErrorMessage") = "カテゴリIDを指定してください"
        Return View("Error")
    End If
    Dim ent As New mvcdbEntities
    ' カテゴリ名称を取得
    Dim count = (From c In ent.TCategory
                Where c.id = id
                Select c.name).Count
    If count = 0 Then
        ' カテゴリIDが範囲を超えている場合
        ViewData("ErrorMessage") =
            String.Format("カテゴリID({0})が正しくありません", id)
        Return View("Error")
    End If
    ' 指定したカテゴリ内の商品を取得
    Dim model = From t In ent.TProduct
                Where t.cateid = id
                Select t
    ' カテゴリ名称を取得
    Dim cname = (From c In ent.TCategory
                Where c.id = id
                Select c.name).Single
    ' ViewData に保存
    ViewData("CategoryName") = cname

    Return View(model)
End Function

このアクション メソッドでは、通常の表示のほかに、以下のエラーをチェックします。

  • カテゴリ ID が指定されなかった場合、
    http://localhost/Home/Category
  • カテゴリ ID が範囲を超えている場合
    http://localhost/Home/Category/9999

Category アクション メソッドでは、カテゴリ ID が指定されなかったときは、id の値が「-1」になります。データベースでは、カテゴリ ID は、0 以上としていますので、これでカテゴリ ID が指定されなかったときの判別がつきます。

カテゴリを指定しなかった場合と、カテゴリ ID が範囲を超えていた場合 (データベースにマッチする ID が見つからなかった場合) は、ViewData プロパティにエラー メッセージを設定して、エラー ページを表示させています。

エラー ページを表示する場合は、View("Error") のように直接ページ名を指定できます。

エラー ページは、Views/Home/Error.aspx として作成しておきます。

<ソース (C#)>

C#
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %> 
 
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 
    Error 
</asp:Content> 
 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 
 
    <h2>Error</h2> 
 
    <p><%: ViewData["ErrorMessage"] %></p> 
</asp:Content> 
 

<ソース (VB)>

Visual Basic
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
	Error
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Error</h2>

    <p><%: ViewData("ErrorMessage") %></p>
</asp:Content>

エラー ページのビューで、コントローラーで設定した ViewData["ErrorMessage"] を表示させます。

これを実行した結果が次の図になります。

図 12. 実行結果

このように、ひとつの Category アクション メソッドから、通常のビュー (Category.aspx) と、エラー用のビュー (Error.aspx) を切り分けて表示させることができます。

ViewData プロパティを使うことによって、不必要なモデルの拡張を防ぐことができます。

ページのトップへ


7. ViewData プロパティの注意点

ViewData プロパティを使うとコントローラーからビューに、手軽にデータを渡すことができます。その反面で ViewData プロパティを使いすぎてしまうと、コントローラーとビューが密接にかかわり過ぎて、本来の MVC (Model-View-Controller) の利点が失われてしまいます。

次の例では、本来はモデルを使ってビューを表示するところを、あえて ViewData プロパティを使っています。ビューのコードが、かえって複雑になってしまうことが分かります。

<ソース (C#)>

C#
// ViewData だけを使って渡す例 
public ActionResult CategoryBad(int id) 
{ 
    mvcdbEntities ent = new mvcdbEntities(); 
    // 指定したカテゴリ内の商品を取得 
    var model = from t in ent.TProduct 
                where t.cateid == id 
                select t; 
    // カテゴリの名称を取得 
    var name = (from c in ent.TCategory 
                where c.id == id 
                select c.name).Single(); 
    // ViewData に保存 
    ViewData["CategoryName"] = name; 
    ViewData["TProduct"] = model; 
 
    return View(); 
} 
 

<ソース (VB)>

Visual Basic
Function CategoryBad(ByVal id As Integer) As ActionResult
    Dim ent As New mvcdbEntities
    ' 指定したカテゴリ内の商品を取得
    Dim model = From t In ent.TProduct
                Where t.cateid = id
                Select t
    ' カテゴリ名称を取得
    Dim cname = (From c In ent.TCategory
                Where c.id = id
                Select c.name).Single
    ' ViewData に保存
    ViewData("CategoryName") = cname
    ViewData("TProduct") = model

    Return View()
End Function

ViewData プロパティだけを使ってビューを作成します。

<ソース (C#)>

C#
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %> 
 
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 
    CategoryBad 
</asp:Content> 
 
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 
 
    <h2><%: ViewData["CategoryName"] %></h2> 
 
    <table> 
        <tr> 
            <th>id</th> 
            <th>name</th> 
            <th>price</th> 
            <th>cateid</th> 
        </tr> 
    <% 
        var model = ViewData["TProduct"as IEnumerable<MvcApplication1.Models.TProduct>; 
        foreach ( var item in model ) { 
         %> 
        <tr> 
            <td><%: item.id %></td> 
            <td><%: item.name %></td> 
            <td><%: item.price %></td> 
            <td><%: item.cateid %></td> 
        </tr> 
        <% } %> 
    </table> 
 
</asp:Content> 
 

<ソース (VB)>

Visual Basic
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
	CategoryBad
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2><%: ViewData("CategoryName")%></h2>

    <table>
        <tr>
			<th>id</th>
            <th>name</th>
            <th>price</th>
            <th>cateid</th>
        </tr>
    <%
        For Each item In ViewData("TProduct")
         %>
        <tr>
            <td><%: item.id %></td>
            <td><%: item.name %></td>
            <td><%: item.price %></td>
            <td><%: item.cateid %></td>
        </tr>
        <% Next%>
    </table>

</asp:Content>

次の図が実行結果になります。

図 13. 実行結果

このような使い方でも、モデルを使った場合と同じ画面が作れはしますが、それぞれのコンポーネントの独立性は低くなってしまいます。データの受け渡しのために ViewData コレクションでの名前 (CategoryName、TProduct) を統一する必要もあり、ビュー側では ViewData から指定の型へのキャストが発生しています。この程度の数ならば ViewData プロパティでも可能ですが、実際にはもっと多くの連携が発生してしまうでしょう。

ViewData プロパティを使う場面は、追加の情報をビューに表示させたいときや、エラー メッセージを別のビューに表示するときなどに限っておくとよいでしょう。

ページのトップへ


8. おわりに

いかがだったでしょうか。

ViewData プロパティを使うと、手軽にコントローラーからビューに値を渡せます、しかし、使いすぎると MVC パターンのよいところが失われてしまいます。もろ刃の剣であることがご理解頂けたでしょうか。

図 14. 使いどころの図

使いどころによってはコードを整理した形で作成することができます。エラー メッセージなどの簡単な部分は、ViewData プロパティを使って表示し、商品一覧などの主要な部分は MVC パターンのモデル (Model) を使うといった、使い分けをするとすっきりとしたコードになります。


Code Recipe ASP.NET デベロッパーセンター

ページのトップへ