Home > Enterprise >  ASP.NET MVC - ModelState is invalid but form content is acessible
ASP.NET MVC - ModelState is invalid but form content is acessible

Time:06-23

I am trying to pass some input from the "Create" view to my controller but the ModelState is returning error:

The Controller:

[Route("Create")]
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create([Bind("Name, Location, MaxCapacity")] Warehouse warehouse)
{

    if (ModelState.IsValid)
    {
        _Db.Add(warehouse);
        _Db.SaveChanges();
        return RedirectToAction("Index");
    }

    return BadRequest();
}

The view:

@model InventoryManSys.Models.Warehouse

@{
    ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>Warehouse</h4>
<hr />
<div >
    <div >
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" ></div>
            <div >
                <label asp-for="Name" ></label>
                <input asp-for="Name"  />
                <span asp-validation-for="Name" ></span>
            </div>
            <div >
                <label asp-for="Location" ></label>
                <input asp-for="Location"  />
                <span asp-validation-for="Location" ></span>
            </div>
            <div >
                <label asp-for="MaxCapacity" ></label>
                <input asp-for="MaxCapacity"  />
                <span asp-validation-for="MaxCapacity" ></span>
            </div>
            <div >
                <input type="submit" value="Create"  />
            </div>
        </form>
    </div>
</div>

The model:

public class Warehouse
{
    [Key]
    public int Id { get; set; }
    [Required]
    [StringLength(30, ErrorMessage = "Name should have less than 30 characters")]
    [DisplayName("Warehouse Name")]
    public string Name { get; set; }
    [Required]
    public string Location { get; set; }
    [Required]
    public int MaxCapacity { get; set; }

    //Navigation Property
    public ICollection<Category> Categories { get; set; }

}

But when I do a "Console.WriteLine(warehouse.Name)" the input is being passed correctly. How to solve that? is the "bind[]"attribute a problem?

CodePudding user response:

Your form is missing the anti forgery token that your [ValidateAntiForgeryToken] attribute in the controller is attempting to check against.

You can try adding the anti forgery token line within your form:

@Html.AntiForgeryToken()

CodePudding user response:

ModelState is invalid but form content is acessible

You may add the client validation js library jquery.validate.js and jquery.validate.unobtrusive.js.

Check this document:

https://docs.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-6.0#client-side-validation

If Name/Location/MaxCapacity are received value, it should work fine, suggest you can check the ModelState or just return BadRequest(ModelState); to see what's the detailed error.

But if you use .NET 6, as this document said:

Beginning with .NET 6, new projects include the <Nullable>enable</Nullable> element in the project file. Once the feature is turned on, existing reference variable declarations become non-nullable reference types.

So that the non-nullable property must be required in ASP.NET 6, otherwise the ModelState will be invalid.

One way is to remove <Nullable>enable</Nullable> from your project file.

Another way is to add ? like below:

public class Warehouse
{
    [Key]
    public int? Id { get; set; }
    [Required]
    [StringLength(30, ErrorMessage = "Name should have less than 30 characters")]
    [DisplayName("Warehouse Name")]
    public string Name { get; set; }
    [Required]
    public string Location { get; set; }
    [Required]
    public int MaxCapacity { get; set; }

    //Navigation Property
    public ICollection<Category>? Categories { get; set; }

}
  • Related