提交后ASP.Net MVC视图下拉列表未绑定到模型(帖子)

时间:2010-01-08 15:48:51

标签: c# asp.net-mvc data-binding c#-4.0

我有一个用于创建视图的viewmodel类,它包含2个不同类的属性,以及一个选择项列表(用于下拉列表)。下拉列表和其中一个类的字段始终显示在视图中,但仅当选择了列表的特定选项时,才会显示第二个类的字段。 (通过jQuery加载和返回局部视图的控制器,为第二类强类型化)

第二个类视图中的字段是一些正常输入=文本字段和一个下拉列表。

当我提交表单时,除了第二类内的列表值之外,所有数据都将被正确绑定。

问题是,如果存在验证错误,并且我返回带有模型的视图(以显示错误),那么下拉列表(第二类的那个)是空的,因为没有办法选择从中,然后提交将始终具有isValid = false:S

这是我如何设置的一个例子:

我目前的视图模型如下所示:

public class ViewModel
{
   public GenericData genericData{get;set;}
   public SpecializedData specializedData {get;set;}
   public List<SelectListItem> types { get; set; }
}

public class GenericData
{
   public Type type {get;set;}
   public String name {get;set;}
   public String description{get;set;}
}
public class SpecializedData
{
   public String field{get;set;}
   public int foreignKey{get;set;}
   public List<SelectListItem> listOfForeignKeys{ get; set; }
}

视图是ViewModel的强类型,并以这种方式设置:

<p>
   <label for="genericData.type"> Type:  </label>
        <%=Html.DropDownList("genericData.type",Model.types, "Choose a type") %>
</p>
<p>
    <label for="genericData.name"> Name:</label>
    <%: Html.TextBox("genericData.name")%>
    <%= Html.ValidationMessage("genericData.name", "*")%>
</p>
//Same thing for Description as for name

<div id="SpecializedFields">
           //This will display the specialized info it was already captured before.
           <% if (Model.SpecializedData!= null && Model.GenericData.Type == "Specialized")
           {
               Html.RenderPartial("SpecializedInfoView", Model.specializedData);
           } %>
</div>
<p>
     <input type="submit" value="Create" />
</p>

$(document).ready(function () {
        $("#CatalogItem_Type").change(function () {

            var typeVal = $("#GenericData_type").val();
            if (typeVal == "specialized") {
                $("#SpecializedFields").load("/MyController/SpecializedFields");
            }

控制器会做这样的事情

public ActionResult SpecializedFields()
{
     List<SelectListItem> foreignIds = getForeignIdsFromDataBase();
     SpecializedData model = new SpecializedData ();
     model.listOfForeignIds = foreignIds;
     return PartialView("SpecializedInfoView",model);
}

最后,SpecialezedInfoView是SpecializedData的强类型视图,类似于泛型视图,它是这样的:

<p>
   <label for="specializedData.foreignKey"> Key:  </label>    <%=Html.DropDownList("specializedData.foreignKey",Model.listOfForeignKeys, "Choose key") %>
</p>
<p>
    <label for="SpecializedData.field"> Field:</label>
    <%: Html.TextBox("specializedData.field")%>
    <%= Html.ValidationMessage("specializedData.field", "*")%>
</p>

当我点击提交时,如果它不是专门的项目,我将获得specializedData属性的空值,这没关系。如果它是一个专门的项目,那么它不会为空,我将获得genericData的所有属性,我也会获得specializedData.fieldspecializedData.foreignKey值,但是specialized.listOfForeignKeys将是NULL,这意味着如果存在验证错误并且我使用当前模型返回视图,则所有内容都将具有先前输入的值,但 DropDownList与列表外键的内容为空,现在无法选择ID。

我知道我可以在接收帖子的方法中查看expertData是否为null,并重新生成密钥列表并将其分配给当前模型(因为它是唯一缺少的数据) ,但这意味着必须进行额外的数据库调用,而不是模型中存在的信息!

我知道这是一个很长的问题,但我想明确我是如何设置的,有人知道为什么listOfForeignKeys在回发后没有被传回模型!?

谢谢!

1 个答案:

答案 0 :(得分:4)

我想通了......当你绑定时,DropDownLists的值不会被发送回模型...但是,由于绑定会自动调用viewmodel的构造函数{{ 1}}因为绑定而被填充在那里。第二个列表不是在构造函数中构建的,因此它是null。我添加了查询以获取List<SelectItemList> Types构造函数中列表的信息,现在它正在工作..

当用户点击发布时,会有一个额外的数据库调用,而且如果存在验证错误则会更多次调用。也许我会尝试使用缓存来存储查询结果,但就目前而言,这已经足够了。

谢谢!