4

私は次のモデルを持っています:

public class ConfigurationPolicyModel
{
    public ConfigurationPolicyModel()
    {
        Properties = new List<Property>();
    }

    public List<Property> Properties { get; set; }

    public class Property
    {
        public Property()
        {
            Value = new List<ValueItem>();
        }

        public List<ValueItem> Value { get; set; }

        public class ValueItem
        {
            public string Data { get; set; }
        }
    }
}

単純化されたコントローラーは次のとおりです。

[HttpPost]
public ActionResult EditPolicy(ConfigurationPolicyModel model)
{
    foreach (var prop in model.Properties)
    {
        var n = prop.Value.Count; // The problem is here: prop.Value is empty
    }
    ...
}

問題のコンテキストは次のとおりです。

  • EditPolicy ビューは非常に複雑で、動的に値項目を追加/削除するために Knockout.JS が使用されます。入力要素は次のようになります。
<input class="text-box single-line" type="text" data-bind="value: Data" name="Properties[@i].ValueItem" />

しかし、フォームの送信時に、JavaScript コードは次のような正しい名前を持つように name 属性を更新しますProperties[0].Value[0].Data

for (var i = 0; i < viewModel.properties().length; ++i)
{
    var valueItems = $('input[name="Properties[' + i + '].ValueItem"]');

    for (var j = 0; j < valueItems.length; ++j)
    {
        $(valueItems[j]).attr("name", "Properties[" + i + "].Value[" + j + "].Data");
    }
}

Fiddler での HTTP 要求のフォーム データは次のようになります (WebForms モード)。

プロパティ値項目

HTTP 要求の生のペイロードは次のとおりです。

Id=00000000-0000-0000-0000-000000000000&Level=Platform&Name=SmsPolicy&InheritanceLevels[0].Level=SafeCenter&InheritanceLevels[0].InheritanceType=Force&InheritanceLevels[1].Level=TeamSafe&InheritanceLevels[1].InheritanceType=Force&Properties[0].Name=Providers&Properties[0].ValueIsSequence=True&Properties[0].Value[0].Data=O2&Properties[0].Value[1].Data=Telecom&Properties[0].Value[2].Data=&Properties[0].Value[3].Data=&Properties[0].Minimum=&Properties[0].Maximum=&Targets[0].Level=Platform&Targets[0].Name=Platform&Targets[0].Selected=true&Targets[0].Selected=false&Targets[1].Level=SafeCenter&Targets[1].Name=SafeCenters&Targets[1].Selected=true&Targets[1].Selected=false&Targets[1].Items[0].Level=SafeCenter&Targets[1].Items[0].OwnerId=7292f9aa-b168-43ab-83a7-db193599d02f&Targets[1].Items[0].Name=Google+Inc.&Targets[1].Items[0].Selected=true&Targets[1].Items[0].Selected=false&Targets[1].Items[1].Level=SafeCenter&Targets[1].Items[1].OwnerId=6c481d66-0ece-4269-8256-c02d3b8c5109&Targets[1].Items[1].Name=SC11&Targets[1].Items[1].Selected=true&Targets[1].Items[1].Selected=false&Targets[1].Items[2].Level=SafeCenter&Targets[1].Items[2].OwnerId=9afd1968-6742-435d-919e-36068ff4b235&Targets[1].Items[2].Name=SC2&Targets[1].Items[2].Selected=true&Targets[1].Items[2].Selected=false&Targets[1].Items[3].Level=SafeCenter&Targets[1].Items[3].OwnerId=995813e1-91d4-4fad-bf10-fbafa0354cbb&Targets[1].Items[3].Name=SC4&Targets[1].Items[3].Selected=true&Targets[1].Items[3].Selected=false&Targets[1].Items[4].Level=SafeCenter&Targets[1].Items[4].OwnerId=acbd68a8-cb9b-4e50-8eeb-59b374fedae0&Targets[1].Items[4].Name=SC5&Targets[1].Items[4].Selected=true&Targets[1].Items[4].Selected=false&Targets[2].Level=TeamSafe&Targets[2].Name=TeamSafes&Targets[2].Selected=true&Targets[2].Selected=false
  • フォームがサーバーに投稿されている場合、フォーム データには実際にそのようなフィールドが含まれており、Fiddler はそれを確認します。ModelBinderAttributeさらに、フィールドが実際にモデル バインダーに到達するのを監視するために、(経由で) カスタム モデル バインダーを割り当てました。
  • しかし、デフォルトのバインダーがモデルのインスタンスを作成すると、インスタンスのリストPropertyには項目がありません。Value
  • そして最も奇妙な点: この問題は時々発生し、値アイテムの数に依存しているようです。プロパティに値項目が 1 つある場合、Valueリストはおそらくいっぱいになりますが、値項目が 6 つの場合、項目はValueリストに挿入されません。

誰でも問題を解決する方法を教えてもらえますか? 事前にどうもありがとうございました。

4

2 に答える 2

1

番号付けが連続していることを確認してください。スキップされるすべての Id により、それよりも大きいすべての Id がモデルに取り込まれなくなります。

具体的には、MVC Web サイトで同様のテストを行ったところ、次のことがわかりました。

  • クライアントに ID 1、2、3、4、5、6、7 がある場合、すべての要素がモデルに正しく入力されます
  • ID 1、2、3、5、6、7 の場合、エレメント 1、2、および 3 のみが取り込まれます (4 がないため、5、6、および 7 は失われます)。
于 2012-11-02T08:54:09.920 に答える
1

以下はうまくいきます:

@using (Html.BeginForm())
{
    <input type="text" name="Properties[0].Value[0].Data" value="O2" />
    <input type="text" name="Properties[0].Value[1].Data" value="Telecom" />
    <input type="text" name="Properties[0].Value[2].Data" value="" />
    <input type="text" name="Properties[0].Value[3].Data" value="" />

    <button type="submit">OK</button>
}

次のアクションに正しくバインドします。

[HttpPost]
public ActionResult EditPolicy(ConfigurationPolicyModel model)
{
    return View();
}

次のペイロードがネットワーク経由で送信されます。

Properties[0].Value[0].Data = O2
Properties[0].Value[1].Data = Telecom
Properties[0].Value[2].Data =
Properties[0].Value[3].Data =

したがって、これがうまくいかない場合は、カスタム モデル バインダーがデフォルトの規則に干渉している、またはリクエスト ペイロードがここに示すように見えないなど、他の理由が考えられます。

于 2012-11-02T11:09:47.947 に答える