模型正确显示但回发null

时间:2013-01-23 21:01:27

标签: c# asp.net-mvc-3 forms razor

我使用强类型模型填充了局部视图。在这个局部视图中是一个表格。当我提交表单时,它告诉我模型中的对象为null,即使它们不是因为局部视图基于同一模型呈现所有元素。

更具体地说,我无法将所有复选框都传回去。如果你查看我的控制器,你可以看到我检查CompanyOptions是否为空,每次运行程序时它都会打印STUFF IS NULL,这意味着它是空的。

型号:

public class Company
{
    public string Name { get; set; }
    public string DatabaseName { get; set; }
    public CompanyOptions CompanyOptions;
}

 public class CompanyOptions
    {

        public CompanyLicenseOptions CompanyLicenseOptions { get; set; }
    }

 public class CompanyLicenseOptions
    {
        public List<CompanyLicenseOption> CompanyLicenseOptionsList;
}

查看:

@using (Html.BeginForm("Action", FormMethod.Post))
{
    for (int i = 0; i < Model.CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList.Count; i++)
    {
        @Html.CheckBoxFor(model => model.CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[i].IsLicensed, checkboxHtmlAttributes);
        <label for="@Model.CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[i].LicenseName">@Model.CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[i].LicenseName</label>                                                                                       
        <br/>
    } 
    @Html.HiddenFor(model => model.DatabaseName)
    <input id="submit_licenses" type="submit" style="display:none;" />
}

控制器:

       [HttpPost]
        public void Action(Company model)
        {
            System.Diagnostics.Debug.WriteLine("STUFF:" + model.DatabaseName);
            if(model.CompanyOptions!=null)foreach (var item in model.CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList) System.Diagnostics.Debug.WriteLine("STUFF:" + item);
            else System.Diagnostics.Debug.WriteLine("STUFF IS NULL");
        }

生成的HTML:

<input class="licenses" data-val="true" disabled="" id="CompanyOptions_CompanyLicenseOptions_CompanyLicenseOptionsList_0__IsLicensed" name="CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[0].IsLicensed" type="checkbox" value="true" /><input name="CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[0].IsLicensed" type="hidden" value="false" />

不相关的JS

$('#save_licenses').click(function () {
        swap_licenses(true);
        $('#submit_licenses').click();
    });

POST:

Request URL:http://localhost:3080/Controller/Action
Request Method:POST
Status Code:200 OK

CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[0].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[1].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[2].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[3].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[4].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[5].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[6].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[7].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[8].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[9].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[10].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[11].IsLicensed:false
    CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[12].IsLicensed:false
    DatabaseName:myDb

3 个答案:

答案 0 :(得分:2)

<input class="licenses" data-val="true" disabled="" id="CompanyOptions_CompanyLicenseOptions_CompanyLicenseOptionsList_0__IsLicensed" name="CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[0].IsLicensed" type="checkbox" value="true" /><input name="CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList[0].IsLicensed" type="hidden" value="false" />

这是你的问题:

disabled=""

您的复选框为disabled,因此不会向服务器发送任何内容。这就是HTML的工作原理。永远不会发送禁用的元素。所以摆脱这个属性。

如果您想阻止用户修改该值,但初始值已发送到服务器,请使用readonly属性,而不是disabled

我在代码中看到的另一个问题是CompanyLicenseOptionsList集合字段。它应该是具有公共getter和setter的属性:

public class CompanyLicenseOptions
{
    public List<CompanyLicenseOption> CompanyLicenseOptionsList { get; set; }
}

同样适用于您的CompanyOptions字段(您已将其定义为字段,而它应该是属性):

public class Company
{
    public string Name { get; set; }
    public string DatabaseName { get; set; }
    public CompanyOptions CompanyOptions { get; set; }
}

更新:

现在您已经修复了缺少的getter和setter的问题,剩下的就是确保干预此对象图的所有模型都具有默认(无参数)构造函数。如果您希望它们显示为动作参数,那么这是一个要求,否则默认模型绑定器将不知道如何实例化它们。如果由于某种原因您无法为所有对象添加默认构造函数,我强烈建议您修改对象层次结构并立即开始使用视图模型。

答案 1 :(得分:0)

你应该使用foreach循环而不是简单的for,这样:

@using (Html.BeginForm("Action", FormMethod.Post))
{
    foreach (var option in Model.CompanyOptions.CompanyLicenseOptions.CompanyLicenseOptionsList)
    {
        @Html.CheckBoxFor(o => o.IsLicensed, checkboxHtmlAttributes);
        <label for="@option.LicenseName">@option.LicenseName</label>                                                                                       
        <br/>
    } 
    @Html.HiddenFor(model => model.DatabaseName)
    <input id="submit_licenses" type="submit" style="display:none;" />
}

答案 2 :(得分:-1)

由于所有这些复选框的端点都是List<T>,因此您需要确保在使用前将其实例化:

public class CompanyOptions
{
    public CompanyLicenseOptions CompanyLicenseOptions { get; set; }
}
public class CompanyLicenseOptions
{
    public List<CompanyLicenseOption> CompanyLicenseOptionsList;
    public CompanyLicenseOptions() 
    {
         CompanyLicenseOptionsList = new List<CompanyLicenseOption>();
    }
}

编辑:为了确保读者获得适当的上下文并避免混淆,我已经复制了上面的OP代码。