簡體   English   中英

不能從局部視圖發布強類型模型

[英]Strongly-Typed Model Not Posting from Partial View

我有一個包含以下組件的MVC3頁面:

ProfileController-包含所有操作並加載下面的所有視圖

/ Profile / Index-此操作方法創建UserViewModel的實例,該實例包含多個屬性和嵌套集合,包括一個名為“ PrefPrograms”的類型為“ PreferencePrograms”的對象,其定義為:

public class PreferencePrograms : List<PreferenceProgram>

“索引”操作方法將填充PrefPrograms集合和UserViewModel的其余部分,並將該模型傳遞到強類型的“ Index.cshtml”視圖中。

Index.cshtml-這是類型為“ UserViewModel”的強類型視圖。 它由多個局部視圖組成。 此頁面中的一個名為“ Preferences.cshtml”的局部視圖提供了PrefPrograms集合的格式化顯示。 Index.cshtml的相關部分如下。

@model ProfilePreferenceCenterProto.Models.UserViewModel

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

Preferences.cshtml-此強類型的部分視圖由Index.cshtml使用Html.RenderPartial加載(上述)。 在Preferences.cshtml中,我具有一個Begin.AjaxForm()方法用於發布到“ PreferenceSubmit”操作,並且輸入提交按鈕位於此局部視圖的底部。 在局部視圖中,我調用@ 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方法?

從表單提交的值將基於模型的屬性名稱和HTML中的字段名稱綁定到模型的屬性。 在您的代碼中:

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

HtmlHelper不知道UserViewModel中屬性的名稱是什么。 它使用“ TabPrograms”局部變量名稱來生成HTML中的字段名稱,例如:

<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”屬性? 如果不是,則應創建它,並將這些字段中的數據綁定到它。 另一個更好的解決方案是使用“ PrefPrograms”局部變量名稱代替“ TabPrograms”

現在,我已經解決了這個問題,但是最終必須添加幾個隱藏字段,並在將數據發布到我的接收操作方法之后,通過調用我的數據源來重建模型。

因為試圖解析我的集合以便在界面的單獨分組區域中顯示特定的集合項,所以我在Preferences.cshtml視圖中確實遇到了另一個問題。 @ Html.EditorFor helper方法導致自動生成的表單ID相互重疊,因為我從特定循環中多次在集合上調用@ Html.EditorFor。 通過從Html.EditorFor切換到Html.RenderPartial並使用Steve Sanderson的BeginCollectionItem幫助器(如下所述),我可以解決此問題:

http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/

如有任何疑問或想了解我是如何做到的,請隨時直接與我聯系。

非常感謝你的幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM