12

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> }

1 Answer 1

28

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.

Sign up to request clarification or add additional context in comments.

5 Comments

That worked thanks! But why does the name model work for another controller I have that accepts HttpPost data?
Does the model for that action also have a property named Model? The reason it was failing here was because of the name collision.
OH sorry I actually misunderstood what you were saying before but I am clear now. Thanks for you help.
I had the same problem, thanks for answer. It is not obvious, really.
I had a similar problem, but in my case the parameter name was 'response' since I'm collecting R.S.V.P's - response is a sensible name and not a reserved word. It does the concern me the convention over configuration mantra seems to be overreaching in this case

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.