Joel Rodrigues
Joel Rodrigues

Reputation: 163

ASP.NET MVC model binding vs nullable reference types

I just created a new ASP.NET MVC application using .NET 6.0 and C# 10, and in this project template the Nullable Reference Types feature is enabled by default. But OK, I'm learning how to deal with this feature.

I had the following ViewModel class:

public class CustomerViewModel
{
    public string Name { get; set; }
}

To avoid the Nullable Reference Type warning for the Name field, I created a constructor to initialize this field:

public class CustomerViewModel
{
    public CustomerViewModel(string name) => Name = name;

    public string Name { get; set; }
}

But now, when I try to receive this ViewModel in my controller action, the binding mechanism asks for a parameterless constructor:

public IActionResult CreateCustomer(CustomerViewModel customer)
{
}

If I add a parameterless constructor to my ViewModel, I get the Nullable Reference Type warnings again, because the Name field will not have a initial value outside the constructor.

This field is non-nullable, so I can't make it nullable by adding a question mark operator. And for me it doesn't make sense to initialize this field with a "random" value, like String.Empty.

How are you dealing with this feature? Have you ever faced a scenario like this? And how did you solve it?

Thank you.

Upvotes: 6

Views: 2390

Answers (1)

Bruno V
Bruno V

Reputation: 1731

Due to the nature of model binding (first instantiate an object, then fill its properties), there is a conflict with the Nullable Reference Types feature. However, there is a good blog post which offers 3 ways of dealing with this:

  1. Declare all fields as nullable and add a [Required] attribute

    [Required]
    public string? Name { get; set; }
    
  2. Add the Null-forgiving operator to all non-nullable properties

    public string Name { get; set; } = null!;
    
  3. Disable nullability warnings for the ViewModel

    #nullable disable warnings
    public class CustomerViewModel
    {
        public string Name { get; set; }
    }
    

Just like the author of the blog, I prefer the third approach. Since the issue only occurs on classes that require a parameterless constructor, the nullable check can be disabled for these classes only. All properties remain uncluttered.

Upvotes: 8

Related Questions