且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

ASP.NET MVC模型绑定返回null对象

更新时间:2023-02-25 18:48:57

的问题是,有一个在类命名的属性模式之间的名称冲突 DeviceModel 并命名为模式创建操作变量。该名冲突导致 DefaultModelBinder 失败,因为它试图将Model属性绑定到DeviceModel类。

更改创建行动变量的名称 deviceModel 键,它将正确绑定。

I am having a problem where everytime I post a form back to the [HttpPost] version of my controller action, the ModelBinder returns a null object. I can't work out why. If I change the signature to use a FormCollection instead I can see that all the correct keys have been set. Can someone help me pin point what's wrong here, because I can't spot it.

Here are the models for working with my views

public class DeviceModel
{
    public int Id { get; set; }

    [Required]
    [Display(Name = "Manufacturer")]
    public int ManufacturerId { get; set; }

    [Required]
    [Display(Name = "Model")]
    [StringLength(20)]
    public string Model { get; set; }

    [StringLength(50)]
    [Display(Name = "Name")]
    public string Name { get; set; }

    [StringLength(50)]
    [Display(Name = "CodeName")]
    public string CodeName { get; set; }

    public int? ImageId { get; set; }
}

public class DeviceCreateViewModel : DeviceModel
{
    public IEnumerable<SelectListItem> Manufacturers { get; set; } 
}

Which I use in my controller like so:

public ActionResult Create()
{
    DeviceCreateViewModel viewModel = new DeviceCreateViewModel()
                                            {
                                                Manufacturers = ManufacturerHelper.GetSortedManufacturersDropDownList()
                                            };

    return View(viewModel);
}

[HttpPost]
public ActionResult Create(DeviceModel model)
{
    // if I check model here it is NULL
    return View();
}

And the view looks like this:

@model TMDM.Models.DeviceCreateViewModel

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>

        <div class="editor-label">
            @Html.LabelFor(model => model.ManufacturerId)
        </div>
        <div class="editor-field">
            @Html.DropDownList("ManufacturerId", Model.Manufacturers)
            @Html.ValidationMessageFor(model => model.ManufacturerId)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Model)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Model)
            @Html.ValidationMessageFor(model => model.Model)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.CodeName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.CodeName)
            @Html.ValidationMessageFor(model => model.CodeName)
        </div>

        <p>
            <input type="submit" value="Save" class="medium green awesome" />
            @Html.ActionLink("Cancel", "Index", "Device", null, new { @class="medium black awesome" })
        </p>
    </fieldset> }

The problem is that there is a name collision between the property named Model in the class DeviceModel and the variable named model in the Create action. The name collision causes the DefaultModelBinder to fail, since it tries to bind the Model property to the DeviceModel class.

Change the name of the variable in the Create action to deviceModel and it will bind correctly.