Search code examples
asp.netasp.net-mvcasp.net-core

ASP.NET Model State validation returning false when everything should be correct


i have a problem when i try and post my form within an asp.net app. I have a blogViewModel like this:

namespace Dev_bloggr.Models.ViewModels
{
    public class CreateBlogViewModel
    {
        public int Id { get; set; }
        [Required]
        [MaxLength(100)]
        public string Title { get; set; }

        [Required]
        [MaxLength(100)]
        public string Header { get; set; }

        [Required]
        [MinLength(200)]
        public string Content { get; set; }

        public DateTime CreatedAt { get; set; }

        // Navigation property for the user
        [ValidateNever]
        public ApplicationUser User { get; set; }
        //Foreign key for the user
        public string UserId { get; set; }

    }
}

The only required fields are title, header and content. Within my controller these are my two methods:

      public IActionResult UpsertBlog(int? id)
        {
            var blogViewModel = new CreateBlogViewModel();
            
            if (id == null || id == 0)
            {
                return View(blogViewModel);
            }
            else
            {
                var blog = _db.Blogs.FirstOrDefault(u => u.Id == id);
                blogViewModel.Id = blog.Id;
                blogViewModel.Title = blog.Title;
                blogViewModel.Header = blog.Header;
                blogViewModel.Content = blog.Content;
                blogViewModel.CreatedAt = blog.CreatedAt;
                blogViewModel.UserId = blog.UserId;
                return View(blogViewModel);
            }
        }
        [Authorize]
        [HttpPost]
        public IActionResult UpsertBlog(CreateBlogViewModel blog)
        {
            if (ModelState.IsValid)
            {
                if (User.Identity.IsAuthenticated)
                {
                    var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
                    var blogInfo = new Blog
                    {
                        Title = blog.Title,
                        Header = blog.Header,
                        Content = blog.Content,
                        CreatedAt = DateTime.Now,
                        UserId = userId // Set the UserId property to associate the Blog with the user.
                    };
                    if (blog.Id == 0 || blog.Id == null)
                    {
                        if (userId != null)
                        {
                            _db.Blogs.Add(blogInfo);
                        }
                    }
                    else
                    {
                        _db.Blogs.Update(blogInfo);

                    }
                    _db.SaveChanges();

                    return RedirectToAction("Index");
                }

            }

            return View();
        }

When i fill in the blog with correct asp-for and try and post the result the model.IsValid always returns false. Does anyone know why?


Solution

  • I test your code with the project version asp.net core 6 in Visual Studio 2022, and I don't meet the error like you. I test with the code:

    UpsertBlog.cshtml:

    @model CreateBlogViewModel
    <div class="row">
        <div class="col-md-4">
            <form asp-action="UpsertBlog">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="Id" class="control-label"></label>
                    <input asp-for="Id" class="form-control" />
                    <span asp-validation-for="Id" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Title" class="control-label"></label>
                    <input asp-for="Title" class="form-control" />
                    <span asp-validation-for="Title" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Header" class="control-label"></label>
                    <input asp-for="Header" class="form-control" />
                    <span asp-validation-for="Header" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Content" class="control-label"></label>
                    <input asp-for="Content" class="form-control" />
                    <span asp-validation-for="Content" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="CreatedAt" class="control-label"></label>
                    <input asp-for="CreatedAt" class="form-control" />
                    <span asp-validation-for="CreatedAt" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="UserId" class="control-label"></label>
                    <input asp-for="UserId" class="form-control" />
                    <span asp-validation-for="UserId" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
    
    
    
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    

    _ValidationScriptsPartial.cshtml :

    <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
    <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
    

    Client-side validation prevents submission until the form is valid. You can read Client-side validation to know more

    I guess your problem may be caused by missing Client-side validation or ApplicationUser User , (you can set breakpoint at ModelState.IsValid to see the result ) like:

    enter image description here

    [ValidateNever]: Indicates that a property or parameter should be excluded from validation.

    From your code ,I see you have added it. ApplicationUser User should be excluded from validation.

    And from ValidateNeverAttribute we know

    Namespace: Microsoft.AspNetCore.Mvc.ModelBinding.Validation

    Assembly: Microsoft.AspNetCore.Mvc.Core.dll

    Package: Microsoft.AspNetCore.App.Ref v6.0.6

    Option 1.Make the [ValidateNever] attribute work

    Make sure your Package: Microsoft.AspNetCore.App.Ref is maintained, you can refer to this. And have Namespace in the CreateBlogViewModel class:

    using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; 
    

    Option 2.If the [ValidateNever] attribute don't work, you can add ? manully to like:

    public ApplicationUser? User { get; set; }
    

    Option 3: you can remove <Nullable>enable</Nullable> from your project file (double-click the project name or right-click the project to choose Edit Project File). You can read this to know more.

    result:

    enter image description here