代码之家  ›  专栏  ›  技术社区  ›  Francisco Noriega

ASP.Net MVC视图dropdownlist在提交(post)后未绑定到模型

  •  4
  • Francisco Noriega  · 技术社区  · 15 年前

    我有一个用于创建视图的viewmodel类,该视图由两个不同的属性类和一个selectitems列表(用于dropdownlist)组成。下拉列表和其中一个类的字段始终显示在视图中,但仅当选择了列表的特定选项时,才会显示第二个类的字段(通过jQuery加载和返回部分视图的控制器(第二类为强类型)

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

    问题是,如果存在验证错误,并且我返回带有模型的视图(以显示错误),那么dropdownlist(第二个类的一个)为空,并且由于无法从中进行选择,那么submit将始终具有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);
    }
    

    最后,SpecializedInfo视图是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>
    

    当我单击submit时,如果它不是一个专门的项目,我将为 specializedData 属性,这是可以的。如果它是一个专用项,那么它将不会为null,我将从 genericData 我去拿 specializedData.field specializedData.foreignKey 也很有价值,但是 specialized.listOfForeignKeys 将是一个 NULL 这意味着,如果存在验证错误,并且我返回带有当前模型的视图,那么所有内容都将具有以前输入的值,但是 包含外键列表的下拉列表将为空 ,现在无法选择id。

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

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

    谢谢

    1 回复  |  直到 15 年前
        1
  •  4
  •   Francisco Noriega    15 年前

    DropDownLists 没有发送回模型时,你做我绑定。。。但是,由于绑定会自动调用viewmodel的构造函数 List<SelectItemList> Types 不是真的因为装订的关系才被填满的。第二个列表不是在构造函数中构建的,因此它是空的。我添加了查询以获取列表中的信息 SpecializedData

    不过,当用户点击post时,会有一个额外的DB调用,如果出现验证错误,调用次数会更多,这有点糟糕。也许我会尝试使用缓存来存储查询结果,但就目前而言,这已经足够了。

    谢谢