0

次のコンポーネントで構成される MVC3 ページがあります。

ProfileController - すべてのアクションを含み、以下のすべてのビューをロードします

/Profile/Index - このアクション メソッドは、UserViewModel のインスタンスを作成します。このインスタンスには、いくつかのプロパティとネストされたコレクションが含まれます。これには、次のように定義されるタイプ「PreferencePrograms」の「PrefPrograms」と呼ばれるものが含まれます。

public class PreferencePrograms : List<PreferenceProgram>

"Index" アクション メソッドは、PrefPrograms コレクションと残りの UserViewModel を設定し、そのモデルを厳密に型指定された "Index.cshtml" ビューに渡します。

Index.cshtml - これは、"UserViewModel" 型の厳密に型指定されたビューです。複数の部分ビューで構成されています。このページ内の 1 つの部分ビュー ("Preferences.cshtml" という名前) は、PrefPrograms コレクションの書式設定された表示を提供します。Index.cshtml の関連部分を以下に示します。

@model ProfilePreferenceCenterProto.Models.UserViewModel

@{ Html.RenderPartial("Preferences", Model); }

Preferences.cshtml - この厳密に型指定された部分ビューは、Html.RenderPartial (上記) を使用して Index.cshtml によって読み込まれます。Preferences.cshtml 内には、「PreferenceSubmit」アクションに投稿するための Begin.AjaxForm() メソッドがあり、入力送信ボタンはこの部分ビューの下部にあります。部分ビュー内で、@Html.EditorFor() ヘルパーを呼び出して、"PrefPrograms" コレクション内の各 "PreferenceProgramModel" アイテムのエディター テンプレートを読み込みます。

ここに私の問題があります-すべてのアイテムが正しくロードされます(コンポーネントの部分ビューとエディターを含む)が、Preferences.cshtmlのフォームを「PreferencesSubmit」アクションに投稿すると、モデルの値が渡されません(モデルはインスタンス化されますが、値は初期化されるだけです - プロパティとコレクションの値は実際にはコントローラーに戻されません)。

Preferences.cshtml の部分ビューを以下に示します。

@model ProfilePreferenceCenterProto.Models.UserViewModel

<div id="accordian">
@using(Ajax.BeginForm("PreferencesSubmit", "Profile", new AjaxOptions{ UpdateTargetId = "accordian" })){

  <div id="accordion">

  <ul class="tabs">

  </ul>

  <div class="panes">
  <div> 
  @{
      List<string> AffiliateNames = new List<string>();
      foreach(ProfilePreferenceCenterProto.Models.PreferenceProgramModel list in Model.PrefPrograms)
      {
          AffiliateNames.Add(list.SubcategoryName);
      }

      IEnumerable<string> listNames = AffiliateNames.Distinct();
      int counter = 0;
  }

  @foreach (string AccordionTabName in listNames)
  {
     <h2>@AccordionTabName</h2>
      <div class="pane" @if (counter == 0){ <text>style="display:block;"</text> } >
      <table>
        <tr class="row">
            <th class="name">Subscription</th>
            <th class="icon">Email</th>            
            <th class="icon">SMS</th>
            <th class="icon">Facebook</th>
            <th class="icon">Mail</th>
            <th class="icon">Phone</th>
        </tr>

    @{ 
    counter++;
    var TabPrograms = (from l in Model.PrefPrograms
                       where l.SubcategoryName == @AccordionTabName
                       select l);
    }                              
    @Html.EditorFor(m => TabPrograms)                     
      </table>
      </div>
  }
  </div>

      </div>
    </div>
       <div align="center"><input type="submit" value="Save Preferences" /></div>

}

/Shared/EditorTemplates/PreferenceProgramModel.cshtml - 次のように定義された「PreferenceProgramModel」項目のエディター テンプレート:

@model ProfilePreferenceCenterProto.Models.PreferenceProgramModel

<tr class="row">
<td class="name">@Model.ListName</td>                
<td class="icon">
@if (Model.EmailEnabled)
{    
    <a id="@Model.EmailFilterID" href="#" onclick="ImageClick(@Html.IdFor(m => m.EmailStatus));"><img height="25" width="28" src="@Model.Email_Icon_NotSelected" /></a>
}
</td>
<td class="icon">
@if (Model.SMSEnabled)
{
    <a id="@Model.SMSFilterID" href="#"><img height="25" width="28" src="@Model.SMS_Icon_NotSelected" /></a>
}
</td>
<td class="icon">
@if (Model.FBEnabled)
{
    <a id="@Model.FBFilterID" href="#"><img height="25" width="28" src="@Model.FB_Icon_NotSelected" /></a>
}
</td>
<td class="icon">
@if (Model.MailEnabled)
{
    <a id="@Model.MailFilterID" href="#"><img height="25" width="28" src="@Model.Mail_Icon_NotSelected" /></a>
}
</td>
<td class="icon">
@if (Model.PhoneEnabled)
{
    <a id="@Model.PhoneFilterID" href="#"><img height="25" width="28" src="@Model.Phone_Icon_NotSelected" /></a>
}
</td>
</tr>  

@Html.HiddenFor(m => m.EmailStatus)
@Html.HiddenFor(m => m.SMSStatus)
@Html.HiddenFor(m => m.FBStatus)
@Html.HiddenFor(m => m.MailStatus)
@Html.HiddenFor(m => m.PhoneStatus)

<script type="text/javascript">
$(document).ready(function () {

    function ImageClick(Resource) {
        alert(Resource.attr("value"));
        if (Resource.attr("value") != 1) {
            Resource.val("1");
        }
        else {
            Resource.val("2");
        }
        alert(Resource.attr("value"));
    }

    if ("@Model.EmailEnabled" == "True") {
        $("#@Model.EmailFilterID").click(function () {

            ImageClick($("#@Html.IdFor(m => m.EmailStatus)"));
            return false;
        });
    }

    if ("@Model.SMSEnabled" == "True") {
        $("#@Model.SMSFilterID").click(function () {
            ImageClick($("#@Html.IdFor(m => m.SMSStatus)"));
            return false;
        });
    }

    if ("@Model.FBEnabled" == "True") {
        $("#@Model.FBFilterID").click(function () {
            ImageClick($("#@Html.IdFor(m => m.FBStatus)"));
            return false;
        });
    }

    if ("@Model.MailEnabled" == "True") {
        $("#@Model.MailFilterID").click(function () {
            ImageClick($("#@Html.IdFor(m => m.MailStatus)"));
            return false;
        });
    }

    if ("@Model.PhoneEnabled" == "True") {
        $("#@Model.PhoneFilterID").click(function () {
            ImageClick($("#@Html.IdFor(m => m.PhoneStatus)"));
            return false;
        });
    }

});
</script>

PreferencesSubmit コントローラ アクションは、次のシグネチャで定義されています。

public ActionResult PreferencesSubmit(Models.UserViewModel model)

ページからレンダリングされたフォーム タグは次のとおりです。

<form action="/Profile/PreferencesSubmit" data-ajax="true" data-ajax-mode="replace" data-ajax-update="#accordian" id="form0" method="post"> 

レンダリングされた非表示フィールドの一部を以下に示します。

<input data-val="true" data-val-number="The field EmailStatus must be a number." data-val-required="The EmailStatus field is required." id="TabPrograms_0__EmailStatus" name="TabPrograms[0].EmailStatus" type="hidden" value="0" />
<input data-val="true" data-val-number="The field SMSStatus must be a number." data-val-required="The SMSStatus field is required." id="TabPrograms_0__SMSStatus" name="TabPrograms[0].SMSStatus" type="hidden" value="0" />
<input data-val="true" data-val-number="The field FBStatus must be a number." data-val-required="The FBStatus field is required." id="TabPrograms_0__FBStatus" name="TabPrograms[0].FBStatus" type="hidden" value="0" />
<input data-val="true" data-val-number="The field MailStatus must be a number." data-val-required="The MailStatus field is required." id="TabPrograms_0__MailStatus" name="TabPrograms[0].MailStatus" type="hidden" value="0" />
<input data-val="true" data-val-number="The field PhoneStatus must be a number." data-val-required="The PhoneStatus field is required." id="TabPrograms_0__PhoneStatus" name="TabPrograms[0].PhoneStatus" type="hidden" value="0" />

PreferencesSubmit が呼び出されたときに ModelState.IsValid が true であることを確認しましたが、モデル自体にはページからの実際の値が含まれていません。送信時に、厳密に型指定されたモデル値を部分ビューから Action メソッドに戻すにはどうすればよいですか?

4

2 に答える 2

1

フォームから送信された値は、モデルのプロパティの名前と HTML のフィールドの名前に基づいて、モデルのプロパティにバインドされます。あなたのコードで:

var TabPrograms = (from l in Model.PrefPrograms
                   where l.SubcategoryName == @AccordionTabName
                   select l);
}                              
@Html.EditorFor(m => TabPrograms)    

HtmlHelper は、UserViewModel のプロパティの名前を認識していません。次のような HTML でフィールドの名前を生成するために、「TabPrograms」ローカル変数名を使用します。

<input name="TabPrograms[0].EmailStatus" data-val="true" data-val-number="The field EmailStatus must be a number." data-val-required="The EmailStatus field is required." id="TabPrograms_0__EmailStatus"  type="hidden" value="0" />

したがって、MVC は上記のフィールドの値を UserViewModel の「TabPrograms」という名前のプロパティにバインドしようとします (これは PreferenceProgramModel オブジェクトのコレクションである必要があります)。UserViewModel クラスに「TabPrograms」プロパティはありますか? そうでない場合は、作成する必要があり、これらのフィールドからのデータがバインドされます。別のより良い解決策は、「TabPrograms」の代わりに「PrefPrograms」ローカル変数名を使用することです

于 2012-06-05T13:24:16.517 に答える