C# 强类型模型未从局部视图过帐

C# 强类型模型未从局部视图过帐,c#,asp.net-mvc-3,asp.net-mvc-partialview,strong-typing,C#,Asp.net Mvc 3,Asp.net Mvc Partialview,Strong Typing,我的MVC3页面由以下组件组成: ProfileController-包含所有操作并加载以下所有视图 /Profile/Index-此操作方法创建UserViewModel的实例,该实例包含多个属性和嵌套集合,包括一个名为“PrefPrograms”的“PreferencePrograms”,类型为“PreferencePrograms”,定义为: public class PreferencePrograms : List<PreferenceProgram> Preferenc

我的MVC3页面由以下组件组成:

ProfileController-包含所有操作并加载以下所有视图

/Profile/Index-此操作方法创建UserViewModel的实例,该实例包含多个属性和嵌套集合,包括一个名为“PrefPrograms”的“PreferencePrograms”,类型为“PreferencePrograms”,定义为:

public class PreferencePrograms : List<PreferenceProgram>
Preferences.cshtml-Index.cshtml使用Html.RenderPartial(如上)加载此强类型局部视图。在Preferences.cshtml中,我有一个Begin.AjaxForm()方法用于发布到“PreferenceSubmit”操作,input submit按钮位于这个局部视图的底部。在部分视图中,我调用@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>
页面中的呈现表单标记如下所示:

<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,但模型本身不包含页面中的实际值。如何将强类型模型值从部分视图传递回提交时的操作方法?

从表单提交的值绑定到模型的属性基于模型属性的名称和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类中的属性?如果不是,您应该创建它,并且来自这些字段的数据将绑定到它。另一个更好的解决方案是使用“PrefPrograms”局部变量名而不是“TabPrograms”

我现在已经解决了这个问题,但最终不得不添加几个隐藏字段,并在将数据发布到我的接收操作方法后通过调用我的数据源来重建模型

我在Preferences.cshtml视图中遇到了另一个问题,因为我试图解析我的集合,以便在界面中的单独分组区域中显示特定集合项。@Html.EditorFor helper方法导致自动生成的表单ID相互践踏,因为我在集合上调用@Html.EditorFor在特定循环中多次使用。我可以通过从Html.EditorFor切换到Html.RenderPartial并使用Steve Sanderson的BeginCollectionItem帮助器来解决此问题,如下所述:

如果您有任何问题或想了解我是如何做到这一点的,请随时直接与我联系


非常感谢您的帮助!

这种方法确实有帮助-我将“var TabPrograms”改为“var PrefPrograms”现在在接收操作方法中识别集合。也就是说,完整模型没有填充,只有表单中包含的部分模型存在。有没有办法让完整模型发回?@Mike:只有HTML表单中包含的字段被发送到服务器。您可以向服务器添加隐藏字段使用Html.HiddenFor(m=>m.FieldName)的r表单,请注意,对于集合,您应该迭代所有元素,并对每个属性使用Html.HiddenFor(m=>m.CollectionField[i].Property1)。哦,没有像“回发”这样的东西在MVC中-如果您需要,您可以通过向表单添加隐藏字段来模拟它,但是MVC中的总体思路与WebForms中的不同谢谢!有没有办法将整个模型序列化为一个隐藏字段,而不是遍历所有属性和嵌套集合?那么也许我可以从FormCollection当action方法收到帖子时?非常感谢你的帮助!@Mike:据我所知,没有帮助方法可以将整个模型序列化到隐藏字段中,但你可以使用反射API自己编写一个。无论如何,我可以看出你是在考虑WebForms,而不是MVC。一般来说,你不应该在su上发布整个模型提交表单-只提交您需要的字段。PS:如果我的答案对您有帮助,您应该将其标记为已接受:)
<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" />
var TabPrograms = (from l in Model.PrefPrograms
                   where l.SubcategoryName == @AccordionTabName
                   select l);
}                              
@Html.EditorFor(m => 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" />