MVC 4模型返回null

4

我有一个视图需要传入和传出几个不同的对象和对象列表,为此我创建了一个viewmodel。我的viewmodel如下所示:

public class EditUserViewModel
{
    public ManageUsersViewModel ManageUsersViewModel { get; set; }
    public IEnumerable<StateModel> StateModel { get; set; }
}

我遇到的困难在于StateModel,它看起来像这样。
public class StateModel
{
    public bool IsChecked { get; set; }
    public States States { get; set; }
    public UsersInStates UsersInStates { get; set; }
}

并包含此内容

[Table("States")]
public class States
{
    [Key]
    public int StateId { get; set; }
    public string State { get; set; }
}

[Table("UsersInStates")]
public class UsersInStates
{
    [Key, Column(Order = 1)]
    public int UserId { get; set; }
    [Key, Column(Order = 2)]
    public int StateId { get; set; }
    public string LicenseNumber { get; set; }
}

在我看来,我基本上是在尝试循环遍历各种状态并为“UsersInStates”获取用户输入。这就是我试图完成它的方式,但我的整个StateModel返回null。进入视图时,“StateModel.States”具有数据而“UsersInStates”没有。在我的视图中它看起来像这样:

@foreach (var state in Model.StateModel)
{
    @Html.HiddenFor(m => state)
    <tr>
        <td>
            @Html.CheckBoxFor(m => state.IsChecked)
        </td>
        <td>
            @Html.Label(state.States.State)
        </td>
        <td>
            @Html.EditorFor(m => state.UsersInStates.LicenseNumber)
        </td>
    </tr>
}

任何建议都将不胜感激。一切显示正常,ManageUsersViewModel 部分也很好用,只是 StateModel 数据返回到控制器时为 null,而我并不确定如何使其按照我想要的方式工作。
以下是所请求的表格开头和第一行的生成 html:
<table style="margin-left:auto; margin-right:auto; text-align:center">
<input id="state" name="state" type="hidden" value="WebSiteNew.Models.StateModel" />                    <tr>
                <td>
                    <input data-val="true" data-val-required="The IsChecked field is     required." id="state_IsChecked" name="state.IsChecked" type="checkbox" value="true" />    <input name="state.IsChecked" type="hidden" value="false" />
                </td>
                <td>
                    <label for="Alabama">Alabama</label>
                </td>
                <td>
                    <input class="text-box single-line" id="state_UsersInStates_LicenseNumber" name="state.UsersInStates.LicenseNumber" type="text" value="" />
                </td>
            </tr>

回答:

好的,为了解决这个问题,我使用了一个for循环,如下面答案中列出的两个参考文献所解释的那样。

@for (int i = 0; i < Model.StateModel.Count(); i++)
{
    <tr>
        <td>
            @Html.HiddenFor(m => m.StateModel[i].States.StateId)
            @Html.HiddenFor(m => m.StateModel[i].States.State)
            @Html.CheckBoxFor(m => m.StateModel[i].IsChecked)
        </td>
        <td>
            @Html.Label(Model.StateModel[i].States.State)
        </td>
        <td>
            @Html.EditorFor(m => m.StateModel[i].UsersInStates.LicenseNumber)
        </td>
    </tr>
}

提醒任何查看此内容的人,我不得不将我的EditUsersViewModel中的IEnumerable更改为IList以允许索引。


你能展示一下生成的HTML长什么样吗? - CorrugatedAir
为postback添加控制器方法 - Lasse Edsvik
2个回答

6

您的问题在于模型绑定不正确。

假设您有以下两个模型:

public class ParentModel
{
    public string Name {get;set;}
    public ChildModel Child {get;set;}
}

public class ChildModel
{
    public string ChildName {get;set;}
    public int SomeNumber {get;set;}
}

您生成的 HTML(为了使模型绑定正确),需要像这样:

<input name="Name" value="(Not relevant to this example)"/>
<input name="Child.ChildName" value="(Not relevant to this example)" />

请注意名称字段的结构 - 这是MVC确定输入值映射到视图模型中哪些属性的方式。对于嵌套属性,属性名称必须放在其前面。
对于集合,情况会变得更加复杂。模型绑定器需要知道哪些值与属性的哪个实例相对应。
例如,在上一个示例中,如果我们假设ChildModel是IEnumerable类型,则为了正确地进行模型绑定,您的HTML可能如下所示:
<input name="Name" value="(Not relevant to this example)"/>
<input name="Child[0].ChildName" value="(Not relevant to this example)" />
<input name="Child[0].SomeNumber" value="(Not relevant to this example)"/>
<input name="Child[1].ChildName" value="(Not relevant to this example)" />
<input name="Child[1].SomeNumber" value="(Not relevant to this example)"/>

请查看以下内容以了解如何解决它:

http://seesharpdeveloper.blogspot.com/2012/05/mvc-model-binding-to-list-of-complex.html http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

编辑 - 还要注意的是,当Html Helpers生成名称值时,它是基于传递的lambda值。因此,
@Html.CheckBoxFor(m => state.IsChecked)

会生成以下名称
name="state.IsChecked"

由于你在 foreach 循环中,所以得到的名称值是错误的。


1
你尝试使用@Html.HiddenFor(m => state)实现什么目的 - 从渲染的HTML中看,那似乎是你的罪魁祸首。 @Html.HiddenFor(m => state.StateId)是否更合适?此外,由于它是隐藏的并且可以保持HTML有效性,你可以将其放入第一个<td>元素中。

不错的发现,我想我用自己的命名约定把自己搞糊涂了...应该是 @Html.HiddenFor(m => state.States) 或者 @Html.HiddenFor(m => state.States.State) 以及 @Html.HiddenFor(m => state.States.StateId)。然而这并不是问题所在,我仍然得到一个空值。 - aw04

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接