Search code examples
c#asp.net-corerazor-pages

Why does ModelState.IsValid check the model properties without [Required]?


I'm new to ASP.NET. In a ASP.NET Core (6.0) Razor Pages project, I found a problem that ModelState.IsValid would check all the properties of model. For example, I have a model:

public class SimpleModel
    {
        
        public int Id { get; set; }
        [Required]
        public string Name { get; set; }

        public int Age { get; set; }
    }

and a pageExample.cshtml with form:

@page "/example"
@model StudentManagement.Pages.ExampleModel
@{
    ViewData["Title"] = "Example";
}

<form method="post" class="mt-3">
    <input hidden asp-for="simpleModel.Id" />

    <div class="form-group row">
        <label asp-for="simpleModel.Name" class="col-sm-2 col-form-label">
        </label>
        <div class="col-sm-10">
            <input asp-for="simpleModel.Name" class="form-control" placeholder="Name">
            <span asp-validation-for="simpleModel.Name"></span>
        </div>
    </div>
    <div class="form-group row">
        <label asp-for="simpleModel.Age" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input asp-for="simpleModel.Age" class="form-control" placeholder="Age">
        </div>
    </div>

    <div class="form-group row">
        <div class="col-sm-10">
            <button type="submit" class="btn btn-primary">Update</button>
        </div>
    </div>
</form>

Example.cshtml.cs:

public class ExampleModel : PageModel
    {
        public SimpleModel simpleModel { get; set; }
        public ExampleModel()
        {
            simpleModel = new SimpleModel()
            {
                Id = 1,
                Name = "Tom",
                Age = 15
            };
        }
        public void OnGet()
        {
        }

        public IActionResult OnPost(SimpleModel simpleModel)
        {
            if (ModelState.IsValid)
            {
                this.simpleModel.Age = simpleModel.Age;
                this.simpleModel.Name = simpleModel.Name;
            }
            return Page();
        }
    }

The problem is when click Update with a blank Age, ModelState.IsValid is false. Why ModelSate doesn't ignore Age even it's without [Required]?

I tried use int? Age and ModelState.IsValid return true, I still want to know how it works.


Solution

  • ModelState.IsValid indicates if it was possible to bind the incoming values from the request to the model correctly and whether any explicitly specified validation rules were broken during the model binding process.

    The official explanation about non-nullable properties or parameters is as followes

    The validation system treats non-nullable parameters or bound properties as if they had a [Required(AllowEmptyStrings = true)] attribute. By enabling Nullable contexts, MVC implicitly starts validating non-nullable properties or parameters as if they had been attributed with the [Required(AllowEmptyStrings = true)] attribute.

    If the app was built with <Nullable>enable</Nullable>, a missing value for Name in a JSON or form post results in a validation error. Use a nullable reference type to allow null or missing values to be specified for the Name property:

    You can refer to this link to learn more about Model validation