none
ASP.NET MVC3 の@ModelTypeについて RRS feed

  • 質問

  • asp.net(mvc3)で@ModelTypeは1つしか使用できないのでしょうか?

    表示用データ部とtextarea入力データ部と1ページ内に配置はできないのでしょうか?

    また、@Html.EditorForのtextareaの幅指定はどのようにするのでしょうか?

    モデル部

    Public Class Movie DBからの表示用データ部)
        Public Property ID() As Integer

        Public Property Title() As String

    End Class

    Public Class Newinput  (textarea入力データ部)
        Public Property Title() As String
        Public Property Name() As String
        Public Property Mail() As String
        <Required()>
        Public Property Comment() As String
    End Class

    VIEW部

    textarea入力データ部)
    @ModelType bbs.Newinput 

    @Html.EditorFor(Function(model) model.Title)
    @Html.ValidationMessageFor(Function(model) model.Title)

        <table>
    @ModelType IEnumerable(Of bbs.Movie)
     @For Each item In Model
        @<tr>
           <td>
                @item.Title
            </td>

        </tr>
    Next
            </table>


    2011年8月3日 11:25

回答

  • @Html.Partial()で部分ビューとして読み込み、その部分ビューに@ModelTypeを指定すればいいのかな?
    ASP.NET MVC3 Web Applicationプロジェクトを作成するとデフォルトで生成されるビューのうち Views/Shared/_Layout.cshtml が Views/Shared/_LogOnPartial.cshtml を読み込んでいます。

    幅指定はMVCに関係なく、HTML / CSSの書き方を知っているかどうかです。

    <div class="title-editor">
      @Html.EditorFor(Function(model) model.Title)
    </div>

    とした場合にCSSで

    .title-editor textarea{
      width: 300px;
    }

    等指定できます。

    • 回答としてマーク 山本春海 2011年8月9日 8:26
    2011年8月3日 16:40
  • 次のスレッドが参考になると思うのですが、

    asp.net mvc - Multiple models in a view - Stack Overflow
    http://stackoverflow.com/questions/4764011/multiple-models-in-a-view

    やっていることはザクッと以下のような手順です。(ちょっと内容は古くなっているかもしれません。)

    ・2つのモデル クラスを別々に定義する。(内側のモデルとでも呼びます)
    ・2つのモデル クラスをまとめるモデル クラスを1つ定義する。(外側のモデルとでも呼びます)
    ・コントローラーのアクションは、外側のモデルをモデル データとして返却する。
    ・ビューで使用するモデルに、外側のモデルから自分用のモデルを取り出すコードを書く。Index.vbhtml にたとえば @model 外側のモデルクラス.内側のモデル名
    ・Index.vbhtml では model 変数を使って、自分用の内側のモデルにアクセスできます。
    ・@Html.Partial を呼び出すときに、第 2 引数に model.Newinput のモデル名 を追加します。
    ・Partial_Newinput.vbhtml で model にアクセスすると、自分用の型になっているはずです。

    ポイントとしては、部分ビューを使ってもコントローラーのアクションとしては1回しか走らないので、2つのモデルを1つにまとめて扱うことでしょうか。
    • 回答としてマーク 山本春海 2011年8月9日 8:26
    2011年8月4日 7:30
  • 何だかうまく伝わらないようですので、順を追って説明してみます。
    学習の機会&問題解決の楽しみを奪わなように、なるべくコードは書かないようにします。

    まずはじめに、1回のアクション メソッドが返せる Model は1つだけです。
    今回は2つの Model を1度に返したいということですので、Model クラスを少し工夫しないといけません。
    1つの Model クラスの中に2つの Model クラスを保持することになります。
    (決して、1つの List の要素として、IEnumerable(Of Movie) 型と Newinput 型を詰め込むわけではありません。)

    仮に今回作成する Model クラスの名前を HybridModel クラスとします。
    HybridModel クラスのメンバーは、既存の2つの Model になります。(つまり、IEnumerable(Of Movie) 型と Newinput 型の2つのプロパティを持たせます。)
    ここまでで HybridModel クラスを作成してみてください。(Model のクラス名はお好きなものに変えてください。)

    さて、アクション メソッドが Model として HybridModel クラスを返すようになりましたので、Index.vbhtml の @ModelType の定義と合わなくなりました。
    Index.vbhtml の @ModelType の定義を "IEnumerable(Of Movie)" から "HybridModel" に変更しないといけません。
    私が以前、
    2 つのモデルを 1 つに統合できてない現状では、です。以降の対応をしていくと、この部分も変更しないといけなくなります。


    と書きましたが、それはこういうことです。

    Index.vbhtml の @ModelType を変更しましたので、View の中でアクセスできる Model 変数の型も今までとは異なっています。
    Index.vbhtml で Movies コレクションにアクセスするには、ただ Model 変数にアクセスするのではなくて、Model.Movies などのように HybridModel クラスの IEnumerable(Of Movie) 型のプロパティとしてアクセスすることが必要です。

    次に Index.vbhtml で @Html.Partial を呼び出す部分ですが、引数の model に引き渡すのは HybridModel の Newinput 型のプロパティの方になります。
    @Html.Partial("Partial_Newinput", model := Model.newinput) などといった具合に、Model 変数のプロパティを渡せばいいですが、ここはあまり問題にはならないでしょう。

    最後に Partial_Newinput.vbhtml の @ModelType 定義ですが、ここには @Html.Partial を呼び出す側で Newinput 型の Model を引き渡していますので、ここはそのままでいいです。
    • 回答としてマーク 山本春海 2011年8月9日 8:26
    2011年8月7日 1:46
  • 返信ありがとうございます。

    bbs.HybridModel bbs.newinput<-----勝手に文字が表示されてしまう
    <!DOCTYPE html>
    <html>
    ↑なんで表示されるのでしょうか?

    _Layout.vbhtml<------原因がわかりました。いろいろやってる間にレイアウトにモデルの@MODELTYPEを指定して

    いました。失礼しました。

    いろいろとご指導ありがとうございました。2つモデル場合とか、@Html.Partialのモデルの指定の仕方など学習になりました。

    その他補足、例Html.TextBoxFor,@Html.TextAreaFor

     @Html.TextBoxFor(Function(Model) Model.Name, New With {.id = "Name", .maxlength = "20", .size = "30"})

     @Html.TextAreaFor(Function(Model) Model.Comment, New With {.id = "Comment", .maxlength = "400", .cols = "70", .rows = "7"})

    ありがとうございました。

    • 回答としてマーク winwin333 2011年8月9日 3:19
    2011年8月9日 3:19

すべての返信

  • @Html.Partial()で部分ビューとして読み込み、その部分ビューに@ModelTypeを指定すればいいのかな?
    ASP.NET MVC3 Web Applicationプロジェクトを作成するとデフォルトで生成されるビューのうち Views/Shared/_Layout.cshtml が Views/Shared/_LogOnPartial.cshtml を読み込んでいます。

    幅指定はMVCに関係なく、HTML / CSSの書き方を知っているかどうかです。

    <div class="title-editor">
      @Html.EditorFor(Function(model) model.Title)
    </div>

    とした場合にCSSで

    .title-editor textarea{
      width: 300px;
    }

    等指定できます。

    • 回答としてマーク 山本春海 2011年8月9日 8:26
    2011年8月3日 16:40
  • 返信ありがとうございます。

    VIEW部を @Html.Partialを使いページ部(Index.vbhtml)とパーチャル部(Partial_Newinput.vbhtml)

    に分けました。

    Index.vbhtmlの内容

    @ModelType IEnumerable(Of bbs.Movie)

    <div> @Html.Partial("Partial_Newinput")</div>

    <table>

    @For Each item In Model
        @<tr>
           <td>
                @item.Title
            </td>

        </tr>
    Next
    </table>

    Partial_Newinput.vbhtmlの内容

    @ModelType bbs.Newinput 

    @Html.EditorFor(Function(model) model.Title)
    @Html.ValidationMessageFor(Function(model) model.Title)

    コンテナ

    Function Index() As ActionResult
                Dim movies = From m In db.Movies
                            Where m.ReleaseDate > New Date(1934, 6, 1)
                            Select m

                Return View(movies.ToList())
     End Function
     Function Partial_Newinput() As ActionResult
                Dim NewIn As New Newinput
                Return View(NewIn)
     End Function

    ディクショナリに型 'System.Collections.Generic.List`1[bbs.Movie]' のモデル項目が渡されましたが、このディクショナリには型 'bbs.Newinput' のモデル項目が必要です。

    のエラーになってしまいます。何故でしょうか?

     

     

    2011年8月4日 2:28
  • 次のスレッドが参考になると思うのですが、

    asp.net mvc - Multiple models in a view - Stack Overflow
    http://stackoverflow.com/questions/4764011/multiple-models-in-a-view

    やっていることはザクッと以下のような手順です。(ちょっと内容は古くなっているかもしれません。)

    ・2つのモデル クラスを別々に定義する。(内側のモデルとでも呼びます)
    ・2つのモデル クラスをまとめるモデル クラスを1つ定義する。(外側のモデルとでも呼びます)
    ・コントローラーのアクションは、外側のモデルをモデル データとして返却する。
    ・ビューで使用するモデルに、外側のモデルから自分用のモデルを取り出すコードを書く。Index.vbhtml にたとえば @model 外側のモデルクラス.内側のモデル名
    ・Index.vbhtml では model 変数を使って、自分用の内側のモデルにアクセスできます。
    ・@Html.Partial を呼び出すときに、第 2 引数に model.Newinput のモデル名 を追加します。
    ・Partial_Newinput.vbhtml で model にアクセスすると、自分用の型になっているはずです。

    ポイントとしては、部分ビューを使ってもコントローラーのアクションとしては1回しか走らないので、2つのモデルを1つにまとめて扱うことでしょうか。
    • 回答としてマーク 山本春海 2011年8月9日 8:26
    2011年8月4日 7:30
  • 返信ありがとうございます。

    >・Index.vbhtml では model 変数を使って、自分用の内側のモデルにアクセスできます。
        Index.vbhtml のモデル  @ModelType IEnumerable(Of bbs.Movie)でモデルにアクセスできています。

    >@Html.Partial を呼び出すときに、第 2 引数に model.Newinput のモデル名 を追加します。
       @Html.Partial("Partial_Newinput", model:=New bbs.Newinput) としてモデルを定義しました。

    Partial_Newinput.vbhtmlの内容

    @ModelType bbs.Newinput 

    @Html.EditorFor(Function(model) model.Title)
    @Html.ValidationMessageFor(Function(model) model.Title)

    でもbbs.Newinput クラスには値が設定されていません。

    また実行するとHPの先頭に 「System.Collections.Generic.List`1[bbs.Movie] bbs.newinput 」 の文字が

    表示されてしまいます。

    @Html.Partial("Partial_Newinput", model:=New bbs.Newinput) の定義の仕方がまずいのでしょうか?

    またモデルを1つにまとめるのはどのようにするのでしょうか?

    2011年8月4日 11:05
  • >・Index.vbhtml では model 変数を使って、自分用の内側のモデルにアクセスできます。
        Index.vbhtml のモデル  @ModelType IEnumerable(Of bbs.Movie)でモデルにアクセスできています。


    2 つのモデルを 1 つに統合できてない現状では、です。以降の対応をしていくと、この部分も変更しないといけなくなります。

    >@Html.Partial を呼び出すときに、第 2 引数に model.Newinput のモデル名 を追加します。
       @Html.Partial("Partial_Newinput", model:=New bbs.Newinput) としてモデルを定義しました。

    Partial_Newinput.vbhtmlの内容

    @ModelType bbs.Newinput 

    @Html.EditorFor(Function(model) model.Title)
    @Html.ValidationMessageFor(Function(model) model.Title)

    でもbbs.Newinput クラスには値が設定されていません。


    @Html.Partial に bbs.Newinput のインスタンスを New して渡しているので、値が設定されていないのは当然だと思います。

    @Html.Partial("Partial_Newinput", model:=New bbs.Newinput) の定義の仕方がまずいのでしょうか?

    またモデルを1つにまとめるのはどのようにするのでしょうか?


    モデルを 1 つにまとめるというのは、先に挙げました URL にもあります通り、モデル クラスのメンバーをそれぞれ別のクラスにするということです。
    今回のケースでいうと、IEnumeratable(Of bbs.Movie) と bbs.Newinput の 2 つのメンバーを持ちます。
    2011年8月4日 15:26
  • 返信ありがとうございます。いろいろ試したのですがわかりませんでした。

    System.Collections.Generic.List(N)にbbs.Movie、bbs.Newinput の 2 つのメンバーが設定されないと駄目の

    ような気がします。

    その設定の仕方がわかりません。

    @Html.Partial("Partial_Newinput", model as object)の model as objectは

    Index.vbhtml(主)の@ModelType IEnumerable(Of bbs.Movie)のモデルを使用するときのみで

    Partial_Newinput.vbhtml(パーチャル部)の@ModelType bbs.Newinputの定義はいいようか気がします。

     @Html.Partial("Partial_Newinput")の部分でエラー

    ディクショナリに型 'System.Collections.Generic.List`1[bbs.Movie]' のモデル項目が渡されましたが、このディクショナリには型 'bbs.Newinput' のモデル項目が必要です。

    だからHPの先頭にHPの先頭に 「System.Collections.Generic.List`1[bbs.Movie] bbs.newinput 」と表示され

    System.Collections.Generic.List(0)のlistはbbs.Movie

    System.Collections.Generic.List(1)のlistはbbs.Newinput にならないからではないでしょうか?

    でもその設定の仕方がわかりません。またModelの値をみるとLIST形式になっており

    Model(0):モデルクラス、Model(1):モデルクラスとなっており、Modelも複数定義できるように思えますが、その設定方法がわかりません

     

    2011年8月6日 12:20
  • 何だかうまく伝わらないようですので、順を追って説明してみます。
    学習の機会&問題解決の楽しみを奪わなように、なるべくコードは書かないようにします。

    まずはじめに、1回のアクション メソッドが返せる Model は1つだけです。
    今回は2つの Model を1度に返したいということですので、Model クラスを少し工夫しないといけません。
    1つの Model クラスの中に2つの Model クラスを保持することになります。
    (決して、1つの List の要素として、IEnumerable(Of Movie) 型と Newinput 型を詰め込むわけではありません。)

    仮に今回作成する Model クラスの名前を HybridModel クラスとします。
    HybridModel クラスのメンバーは、既存の2つの Model になります。(つまり、IEnumerable(Of Movie) 型と Newinput 型の2つのプロパティを持たせます。)
    ここまでで HybridModel クラスを作成してみてください。(Model のクラス名はお好きなものに変えてください。)

    さて、アクション メソッドが Model として HybridModel クラスを返すようになりましたので、Index.vbhtml の @ModelType の定義と合わなくなりました。
    Index.vbhtml の @ModelType の定義を "IEnumerable(Of Movie)" から "HybridModel" に変更しないといけません。
    私が以前、
    2 つのモデルを 1 つに統合できてない現状では、です。以降の対応をしていくと、この部分も変更しないといけなくなります。


    と書きましたが、それはこういうことです。

    Index.vbhtml の @ModelType を変更しましたので、View の中でアクセスできる Model 変数の型も今までとは異なっています。
    Index.vbhtml で Movies コレクションにアクセスするには、ただ Model 変数にアクセスするのではなくて、Model.Movies などのように HybridModel クラスの IEnumerable(Of Movie) 型のプロパティとしてアクセスすることが必要です。

    次に Index.vbhtml で @Html.Partial を呼び出す部分ですが、引数の model に引き渡すのは HybridModel の Newinput 型のプロパティの方になります。
    @Html.Partial("Partial_Newinput", model := Model.newinput) などといった具合に、Model 変数のプロパティを渡せばいいですが、ここはあまり問題にはならないでしょう。

    最後に Partial_Newinput.vbhtml の @ModelType 定義ですが、ここには @Html.Partial を呼び出す側で Newinput 型の Model を引き渡していますので、ここはそのままでいいです。
    • 回答としてマーク 山本春海 2011年8月9日 8:26
    2011年8月7日 1:46
  • 返信ありがとうございます。

     モデル-------------------------------------------------------------------------------------------------

    Public Class Movie DBからのモデル部)

        Public Property ID() As Integer

        Public Property Title() As String

    End Class

    Public Class Newinput  (入力データのモデル部)
        Public Property Title As String
        Public Property Name As String
        Public Property Mail As String
        <Required()>
        Public Property Comment As String
    End Class

    Class Movie とClass Newinput  を1つにしたモデルClassを作成

    Public Class HybridModel

        Public Property dbmodel() As IList(Of Movie)
        Public Property Newmodel As Newinput
    End Class

    コンテナ---------------------------------------------------------------------------------------------------

    Function Index() As ActionResult
                Dim mymodel As HybridModel = New HybridModel()
                mymodel.dbmodel = New List(Of Movie)
                mymodel.Newmodel = New Newinput
                Dim movies = From m In db.Movies
                            Where m.ReleaseDate > New Date(1934, 6, 1)
                            Select m
                mymodel.Newmodel.Title = "test"
                mymodel.dbmodel = movies.ToList()
                Return View(mymodel)
    End Function

    <HttpPost()>
    Function Index(ByVal model As HybridModel) As ActionResult

                Return View(model)
    End Function

    ページ部(Index.vbhtml)とパーチャル部(Partial_Newinput.vbhtml)

    Index.vbhtml (ページ部)-------------------------------------------------------------------------

    @ModelType bbs.HybridModel(モデル定義)

       パーチャル部呼び出し@Html.Partial("Partial_Newinput", Model.Newmodel)   <---二つにしたモデルの1部

    Partial_Newinput.vbhtml(パーチャル部)------------------------------------------------------------

    @ModelType bbs.Newinput(モデル定義)

    モデルの受け渡しは(2つのモデル)はうまくいきました。ありがとうございました。

    また問題がでてしまいました。それはコンテナにPOSTバックした時のVIEWモデルが受け取れません。

    <HttpPost()>
    Function Index(ByVal model As HybridModel) As ActionResult

                Return View(model)
    End Function

    ByVal model As HybridModel <----------受け取っていない

    @Using Html.BeginForm() End Using 間に定義してsubmitでPOSTしてるのですが?

    <form action="/" method="post">    と作成されます。

     

     

     

     

    2011年8月8日 1:41
  • ちょっとインチキくさい方法かもしれませんが、@Using Html.BeginForm() と End Using を Partial_Newinput.vbhtml の方に書くのではなくて、Index.vbhtml の方に移すと受け取れます。

    @Using Html.BeginForm()
      @Html.Partial("Partial_Newinput", Model.Newmodel)
    End Using
    


    EditorTemplates にカスタム テンプレートを置くのが正攻法なのかもしれませんが、Model クラスがネストしていると何だかうまくいかない...。
    2011年8月8日 2:50
  • 返信ありがとうございます。

    @Using Html.BeginForm()

    @<fieldset>

    </fieldset>

    End Using とし@Using Html.BeginForm()と@<fieldset>がセットになってないと<div>,<span>タグがエラーになってしまいますね。なのでIndex.vbhtml (ページ部)で定義することにしました。

     

    コンテナ部

    Dim mymodel As HybridModel = New HybridModel()
    <HttpPost()>(POSTバックするモデルのみのコンテナ
    Function Index(ByVal model As newinput) As ActionResult

          mymodel.dbmodel  = DBからの表示データ(Function Index() As ActionResultと同じ処理)
               mymodel.Newmodel = model

                Return View(mymodel)
    End Function

    一応モデルとVIEWのやり取りはうまく行ったのですが、HPの先頭に@ModelType の定義が表示されてしまいます。

    bbs.HybridModel bbs.newinput<-----勝手に文字が表示されてしまう
    <!DOCTYPE html>
    <html>
    ↑なんで表示されるのでしょうか?
    2011年8月8日 12:17
  • 一応モデルとVIEWのやり取りはうまく行ったのですが、HPの先頭に@ModelType の定義が表示されてしまいます。

    bbs.HybridModel bbs.newinput<-----勝手に文字が表示されてしまう
    <!DOCTYPE html>
    <html>
    ↑なんで表示されるのでしょうか?

    手元の環境ではそのような余計なものは表示されていません。
    レイアウトに余計な記述があるとか、どこかにデバッグ情報が残っているとか、そのようなことに心当たりはありませんか?
    2011年8月9日 1:32
  • 返信ありがとうございます。

    bbs.HybridModel bbs.newinput<-----勝手に文字が表示されてしまう
    <!DOCTYPE html>
    <html>
    ↑なんで表示されるのでしょうか?

    _Layout.vbhtml<------原因がわかりました。いろいろやってる間にレイアウトにモデルの@MODELTYPEを指定して

    いました。失礼しました。

    いろいろとご指導ありがとうございました。2つモデル場合とか、@Html.Partialのモデルの指定の仕方など学習になりました。

    その他補足、例Html.TextBoxFor,@Html.TextAreaFor

     @Html.TextBoxFor(Function(Model) Model.Name, New With {.id = "Name", .maxlength = "20", .size = "30"})

     @Html.TextAreaFor(Function(Model) Model.Comment, New With {.id = "Comment", .maxlength = "400", .cols = "70", .rows = "7"})

    ありがとうございました。

    • 回答としてマーク winwin333 2011年8月9日 3:19
    2011年8月9日 3:19