Azure DevOps, Scrum, & .NET Software Leadership and Consulting Services

Introducing Slide Speaker: Videos with Voice-over from your PowerPoint and Google Slides Presentations

Some Model Properties Not Binding in ASP.NET MVC Core


[TL/DR? – skip to the bottom]

I ran into a problem with an ASP.NET MVC Core app today and it took me a while to figure it out. Here’s the problem: on an extremely simple and straightforward form, I couldn’t get a field in my model to POST back to the server. Every time that I’d click the submit button on my form, it would post back to my controller action but that one property would always be null.

I put a breakpoint in the controller action code. The property on my model was null but when I looked at the Request.Form collection, the value from the HTML form was actually getting sent to the server.

SO WHY IS THAT PROPERTY NULL!!!!?!??!??!?!

Here’s the field that’s going missing. It’s nothing special.

A simple HTML form field with a value

Here’s the code in the Index.cshtml file for that Message field:

<div class="form-group">
    @Html.LabelFor(model => model.Message, htmlAttributes: new { @class = "control-label" })
    @Html.EditorFor(model => model.Message, new { htmlAttributes = new { @class = "form-control" } })
</div>

And here’s the the code for the Model:

public class EmailTestViewModel
{
    [Display(Name = "from email")]
    public string FromEmail { get; set; }

    [Display(Name = "from name")]
    public string FromName { get; set; }

    [Display(Name = "recipient email")]
    public string RecipientEmail { get; set; }

    [Display(Name = "recipient name")]
    public string RecipientName { get; set; }

    [Display(Name = "subject")]
    public string Subject { get; set; }

    [Display(Name = "message")]
    public string Message { get; internal set; }
        
    [Display(Name = "result message")]
    public string ResultMessage { get; set; }
}

Here’s the method in the Controller:

[HttpPost]
public async Task<IActionResult> Index(EmailTestViewModel model)
{
    await _EmailService.SendEmail(
        model.RecipientEmail, model.RecipientName,
        model.Subject, model.FromEmail,
        model.FromName, model.Message, 
        $"<p>{model.Message}</p>");

    model.ResultMessage = "sent";

    return View(model);
}

It’s absolutely nothing special. This code couldn’t be any simpler. But when I run the code and hit the breakpoint in the controller, the Message property is null.

The Message property is null in the Controller

But the absolutely bizarre thing is that if I look at the Request.Form dictionary, the value is there and it’s got exactly the value that I’d expect.

…but there’s a value for it in the Form values dictionary?

So what’s going wrong?

The Cause of the Problem and Then The Solution

Well, the cause of the problem turned out to be coder error. (Surprise!)

Once I saw that the value was in the Request.Form dictionary but wasn’t getting populated on the model, I started thinking about how model binding works in ASP.NET MVC Core. It’s going to take the values that have been POSTed from the form and try to match the names up with the public properties on the model.

When I created the code for the Message property, I’d somehow marked the setter to be internal. The internal visibility modifier makes code visible only to other pieces of code inside the same assembly. Since the ASP.NET MVC model binder is in a different assembly, the binder doesn’t see that setter property as being available so it skips setting that value. Therefore, that Message property is always null on postback.

The setter’s visibility is set to ‘internal’

The solution was easy. Remove that extraneous internal modifier and the code worked just fine.

I hope this helps.

-Ben

SUBSCRIBE TO THE BLOG


4 responses to “Some Model Properties Not Binding in ASP.NET MVC Core”

  1. vishavp Avatar

    Hey! Thanks so much for this, it was my problem exactly too, i was missing the get and set on the field declaration inside my viewmodel. Didnt even realize!

    1. jedi8421 Avatar
      jedi8421

      I feel your pain mate, I just lost a coupl ehours tying to figure it out too

  2. John Avatar
    John

    Perfect! I was using a { protected set;} on one of my properties. Hours of debugging pain trying to figure out why my model wasn’t binding to the controller. This is true for .NET MVC as well.

  3. Dave Wysocki Avatar
    Dave Wysocki

    I am still having the problem and I am not missing the get, set and I don’t have the set marked as internal.

    My view model has 3 tables in it. One occurrence of each table. I can pass data to the view when using a plain text box. I manually set a value of 1 in a numeric control but it still shows as zero.

    When the view posts the view model received by the controller is completely null. All 3 tables show as null.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.