ASP.NET MVC View Model not binding on HTTP Post with DropDownList

34,855

Solution 1

Looks like it might be because of a difference between properties and variables as noted in this question. Add { get; set; } to all variables that you want to bind. As noted in that question I think this is because of the way the default model binder uses reflection.

I have found it useful in the past to actually grab the ASP.NET MVC source code so that I can debug it and see what is going on.

Solution 2

There is another reason for view model is NULL :

  • The name of model in action parameter be the same as one of view model's properties


Example:

Model:

public class NewBookPageView{
  int blabla {get;set;}
  Book NewBook {get;set;} //NewBook is the same as newBook in action parameter
}

controller:

[HttpPost]
public ActionResult AddNewBook(NewBookPageView newBook)//newBook is the same as NewBook in view
{
   int temp = newBook.blabla;
   temp++;
   //...
}


Tip: Here same name means case insensitive (newBook is same as NewBook)

Tip: Faced in MVC3 and MVC4.

Solution 3

To model binding in View you should use strongly-typed-html-helpers

replace

@Html.DropDownList("CategoryParentId", new SelectList(@Model.CategoryParents, "Value", "Text"), new { @class = "input-xlarge-fluid" })

to:

@Html.DropDownListFor(model => model.CategoryParentId, new SelectList(@Model.CategoryParents, "Value", "Text"), new { @class = "input-xlarge-fluid" })
Share:
34,855

Related videos on Youtube

Danny Brady
Author by

Danny Brady

Full Stack .NET Developer specialiasing in Umbraco CMS.

Updated on July 09, 2022

Comments

  • Danny Brady
    Danny Brady almost 2 years

    I am having an issue that when I post to a controller I lose binding and everything in my view model is NULL. Here is the code I am using:

    View:

    @model ArticleCategoryVm
    
    @using (@Html.BeginForm())
    {
        @Html.HiddenFor(model => model.LanguageIdDisplayed)
    
        <label>Name: <span class="label label-important">Required</span></label>
        @Html.HmlValidationFor(model => model.CategoryName)
        @Html.TextBoxFor(model => model.CategoryName, new { maxlength = "255", placeholder = "Category Name", @class = "input-xlarge-fluid" })                  
        <span class="help-block">The is the name of the category and how it appears on the site.</span>
    
        <label>Language: <span class="label label-important">Required</span></label>
        @Html.HmlValidationFor(model => model.LanguageId)
        @Html.DropDownList("LanguageId", new SelectList(@Model.Languages, "Value", "Text"), "Select language", new { @class="input-xlarge-fluid" })
        <span class="help-block">This will be the language that the category is set too.</span>
    
        <label>Parent:</label>
        @Html.HmlValidationFor(model => model.CategoryParentId)
        @Html.DropDownList("CategoryParentId", new SelectList(@Model.CategoryParents, "Value", "Text"), new { @class = "input-xlarge-fluid" })
        <span class="help-block">Allows you to group the category under another existing category.</span>
    
        <label>Moderator Email: <span class="label label-important">Required</span></label>
        @Html.HmlValidationFor(model => model.ModeratorEmail)
        @Html.TextBoxFor(model => model.ModeratorEmail, new { maxlength = "255", placeholder = "Email Address", @class = "input-xlarge-fluid" })
        <span class="help-block">This is the moderator email for articles in this category.</span>
    
        <button type="submit" class="btn btn-duadua btn-small"><i class="icon-ok-3"></i> Add New Category</button>                      
    }
    

    ViewModel:

    public class ArticleCategoryVm : BaseLayoutVm
    {
        public int LanguageIdDisplayed;
        public List<ArticleCategoryItemVm> ArticleCategoryItemVms { get; set; }
    
        // Add Category Fields
        [Required]
        public string CategoryName;
    
        [EmailAttribute]
        [Required]
        public string ModeratorEmail;
    
        [Required]
        public int LanguageId;
    
        public int CategoryParentId;
    
        public List<SelectListItem> Languages { get; set; }
        public List<SelectListItem> CategoryParents { get; set; }
    }
    

    Controller:

    [HttpPost]
    public ActionResult Categories(ArticleCategoryVm vm)
    {
       // Code here
       if (ModelState.IsValid)
       {
       }
    
       ReDrawDropDowns(vm);
       return View(vm)
    }
    

    Why is everything in my viewmodel NULL? I can see in using Chromes tools that in the post the values are being posted for the strings and ints... As a work around I have just done the following to get the code working:

    Workaround Controller:

    [HttpPost]
    public ActionResult Categories(int LanguageIdDisplayed, string CategoryName, string ModeratorEmail, int LanguageId, int CategoryParentId)
    {
        var vm = new ArticleCategoryVm()
        {
            CategoryName = CategoryName,
            LanguageIdDisplayed = LanguageIdDisplayed,
            ModeratorEmail = ModeratorEmail,
            LanguageId = LanguageId,
            CategoryParentId = CategoryParentId
        };
    
        if (ModelState.IsValid)
        {
        }
    
        ReDrawDropDowns(vm);
        return View(vm)
    }
    

    Thanks

  • Ste W
    Ste W almost 10 years
    I just got caught out by this one... seems to be a lot of hidden reserved words / rules with action parameter names... a few days ago I wanted to have a parameter called 'action' which broke my routing! Somewhere under the hood I assume it’s making an anonymous object like the route values anonymous object that turns these parameters into properties on that object so if you use a name like ‘controller’, ‘action’ etc. it screws things up.
  • Samurai Ken
    Samurai Ken almost 9 years
    This was driving me NUTS. Sometimes you don't see what's right in front of your eyes.
  • Jeremy Ray Brown
    Jeremy Ray Brown over 7 years
    This fix worked perfectly. It was driving me nuts too, since I clearly saw the data posted while monitoring the request.
  • Clark Kent
    Clark Kent over 2 years
    Thank you very much. That worked... I've been struggling for 3 hours. :-(