MarredCheese
MarredCheese

Reputation: 20831

Why is this view-model string field treated as required?

I have a simple login page with the view model below. It used to work just fine, but seemingly suddenly, ModelState will contain an error for the ReturnUrl field if it wasn't supplied to the action. It states, "The ReturnUrl field is required."

public class LoginViewModel
{
    [Required(ErrorMessage = TextValidation.RequiredErrorMessage)]
    [Display(Name = "User")]
    public string Username { get; set; }

    [Required(ErrorMessage = TextValidation.RequiredErrorMessage)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    public string ReturnUrl { get; set; }
}

Why would it do that for a string field (i.e. nullable) that does not have a [Required] annotation?

Here's the beginning of the controller action that makes use of that model.

[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View();  // <-- It returns here.
    }
    ...
}

If I debug, I see the following:

ModelState.Results[2].Key = "ReturnUrl"
ModelState.Results[2].Value.AttemptedValue = null
ModelState.Results[2].Value.Errors[0].ErrorMessage = "The ReturnUrl field is required."

One more detail I can add is that I have the same model and action in another project, and in that project, it works fine. If I debug the Login action in that project, I see that ModelState.Results only contains 2 elements: "Username" and "Password". The third element ("ReturnUrl") is not there, which is what I would expect since it shouldn't be getting validated.

Upvotes: 2

Views: 1145

Answers (2)

Edu_LG
Edu_LG

Reputation: 1730

In latest versions of .NET, you have to declare string as nullable (string?) or change project build properties to accept strings as nullable.

Upvotes: 1

MarredCheese
MarredCheese

Reputation: 20831

Apparently, reference types had been set to non-nullable for the project. I don't know how it happened, but in <Project>.csproj, there was this entry:

<Nullable>annotations</Nullable>

Here's more info on the 4 options for that field:
https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references

If you delete the entry, you get the default: disable. And note that these nullability contexts can also be controlled at the file or line level via #nullable <context>. The above link covers that as well.

If I had to guess, I'd say I must have misclicked while viewing Visual Studio's graphical interface for the project's properties:

properties

Upvotes: 3

Related Questions