3

私はMVC 3でWebアプリケーションを構築していますが、これはおそらくモデルバインディングを理解する上で問題があります。ASP.Net MVCは部分的なビューと継承されたプロパティを強く型付けしました

はまず、私は(名前は無実のオブジェクトのプライバシーを保護するために変更簡潔にするために省略無関係なもの、)かなり標準的なモデルを持っている:

public class ModelBase 
{ 
    public int Id { get; set; } 
} 

public class Order : ModelBase 
{ 
    public List<Product> Products { get; set; } 
} 

public class Product : ModelBase 
{ 
    public int OrderId { get; set;} 
} 

これらの表示や編集のために、私は強くに型付けされたビューを持っていますProductクラスに厳密に型指定された部分ビューを含むOrderクラス。部分図の上部は、次のようになります。

@model Product 

@Html.ValidationSummary(true) 
@Html.HiddenFor(model => model.Id) 
@Html.HiddenFor(model => model.OrderId) 
//loads of actual editable properties 

私はこのようなメインビューに部分的に挿入します。

@Html.Partial("EditorTemplates/Product", Model.Products.First()) 

...とビューがブラウザに表示されたとき、 " Idは」隠された入力は、私が何をしないのです注文ではなく、私は期待して:(

を必要とする製品のIDのIDが含まれています?それは、モデルとビューの構造を変更せずに固定することができますか?

+0

あなたはIdが注文であることをどうやって知っていますか? OrderIdは正しく表示されていますか? – Wil

+1

OrderIdは正しく表示され、Idフィールドには同じ値が表示されます。私は、値がOrder url(/ Order/Step2/10、10はOrder Id)の一部としても存在するため、Orderから来る値であるかどうかはわかりません。 IDフィールドを上書きするのはこの値ですか? – Atrieos

+0

注文IDがこのレコードのIDと同じかどうかは、DBを介して確認できますか? – Wil

答えて

3

私が確認できる

/ホーム/インデックス?ID = 33

または

/ホーム/インデックス/ 33

は、モデル値を上書きします。このパラメータをURLから削除できますか?

+2

それだけです!バインダーは、大文字と小文字を区別しない方法でフィールドにルート値を設定し、モデルの値を上書きします。'" Orders/{StepNo}/{OrderId} "' ...のように、アプリケーションのOrder-editing部分にGlobal.Asaxという新しいルートを追加しました。デフォルトルート値{id}を自分の "Id"フィールドに追加します。新しい経路と私の行動パラメータの新しい名前がありました。構造的な変更は必要ありません。MVCは最初に恐れていたように継承に問題はありません。ありがとう助けを束ねる:) – Atrieos

1

構造を変更する必要があります。

メインビューに部分コンテンツを配置するか、製品ではなくオーダーに強く入力するか、Html.Hidden()を使用して非表示フィールドを作成します。 MVCは、あなたのポストアクションのモデルに対して、HiddenFor内のアイテムへのパス全体を入れません。

ie。 HTMLでは、あなたは

<input type="hidden" name="Id" /> 

を参照してくださいだろうが、あなたは本当にフィールドやアイテムを区別するために

<input type="hidden" name="Products[0].Id" /> 

をしたいです。


同じ名前を持つ2つの異なる隠し入力をPOSTしようとすると上記の問題はまだしかし、私も限り、クライアントとして動作するテストプロジェクトを書いて、残っています。

希望はこのことができます:

コントローラ

public ActionResult Index() 
     { 
      Order order = new Order() { Id = 1 }; 
      order.Products = new List<Product>() { new Product() { Id = 3, OrderId = 1 } }; 
      return View("Order",order); 
     } 

モデル

public class Order : IdentityBase 
    { 
     public List<Product> Products { get; set; } 
    } 

    public class Product : IdentityBase 
    { 
     public int OrderId { get; set; } 
    } 

public class IdentityBase 
    { 
     public int Id { get; set; } 
    } 

ビュー

@model MvcApplication1.Models.Order 

@{ 
    Layout = null; 
} 

<!DOCTYPE html> 

<html> 
<head> 
    <title>Order</title> 
</head> 
<body> 
    <div> 
     @Html.HiddenFor(model => model.Id) 
     @foreach (MvcApplication1.Models.Product product in Model.Products) 
     { 
      <div class="product"> 
       @Html.Partial("Product", product) 
      </div> 
     } 
    </div> 
</body> 
</html> 

パーシャルビュー

@model MvcApplication1.Models.Product 

@Html.ValidationSummary(true) 
@Html.HiddenFor(model => model.Id) 
@Html.HiddenFor(model => model.OrderId) 

私のテストプロジェクトを変更するにはクライアントHTML

<!DOCTYPE html> 
<html> 
<head>  
    <title>Order</title>  
</head>  
<body>  
    <div>  
     <input id="Id" name="Id" type="hidden" value="1" />  
     <div class="product"> 
       <input id="Id" name="Id" type="hidden" value="3" />  
       <input id="OrderId" name="OrderId" type="hidden" value="1" />  
     </div> 
    </div> 
</body> 

+0

ここで私たちはこの洞察を得ました: http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx – Kaido

+0

私はコレクションのコントロールを構成する方法を理解していますが、やってみたいです。それは私が編集しようとしている最初の要素です。あなたがおそらく部分的な道から分かるように、私はアプリケーション全体を通して部分的な製品編集を再利用しようとしています。 '@ Html.Hidden(" Id "、Model.Id)'を使用しようとすると、HiddenForと同じ(間違った)結果が生成されました。 '@Html.Hidden(" P_Id "、Model.Id)'を実行すると期待値が得られますが、正しい値が部分ビューに存在していることは明らかですが、ある時点では単に上書きされています。 – Atrieos

+0

あなたのHtmlフォームの範囲は何ですか?名前「Id」の2つの要素をポストバックすることは可能でしょうか?これは、ページのHTMLまたはPOSTアクションのフォーム値コレクションで確認できます。 – Kaido

関連する問題