Modelstate bị invalid làm cho không thể thực hiện thêm vào database

Chào các bác, hiện tại em có 1 table novel có 2 khóa ngoại như hình:

image

Đây là NovelModel được Entity framework scaffold/generate từ database:

public partial class Novel
{
    [Key]
    public int NovelId { get; set; } // Tự động tăng

    public string NovelTitle { get; set; } = null!;

    public string NovelDescription { get; set; } = null!;

    public string NovelCover { get; set; } = null!;

    public DateTime NovelDatePost { get; set; } = DateTime.Now;

    public int NovelView { get; set; } = 1; 

    public int AuthorId { get; set; }

    public string UserId { get; set; } = null!;

    public virtual Author Author { get; set; } = null!;

    public virtual ICollection<Chapter> Chapters { get; } = new List<Chapter>();

    public virtual User User { get; set; } = null!;

    public virtual ICollection<UserComment> UserComments { get; } = new List<UserComment>();

    public virtual ICollection<UserRating> UserRatings { get; } = new List<UserRating>();

    public virtual ICollection<Genre> Genres { get; } = new List<Genre>();
}

AuthorModel:

public partial class Author
{
    public int AuthorId { get; set; }

    public string AuthorName { get; set; } = null!;

    public virtual ICollection<Novel> Novels { get; } = new List<Novel>();
}

UserModel:

public partial class User
{
    [DisplayName("Tên đăng nhập")]
    public string UserId { get; set; } = null!;

    [DisplayName("Họ và tên")]
    public string UserName { get; set; } = null!;

    [DisplayName("Mật khẩu")]
    public string UserPassword { get; set; } = null!;

    [DisplayName("Email")]
    public string UserEmail { get; set; } = null!;

    public int RoleId { get; set; }

    public virtual ICollection<Novel> Novels { get; } = new List<Novel>();

    public virtual Role Role { get; set; } = null!;

    public virtual ICollection<UserComment> UserComments { get; } = new List<UserComment>();

    public virtual ICollection<UserRating> UserRatings { get; } = new List<UserRating>();
}

Theo em được biết thì ngoài các models thể hiện entities ra thì cần phải có View model để truyền data ra Views và ngược lại. Nên em tạo 1 class là NovelViewModel:

namespace WebNovel.Models.ViewModels
{
    public class NovelViewModel
    {
        [Required]
        public String NovelTitle { get; set; }
        [Required]
        public String NovelDescription { get; set; }
        [Required]
        public String NovelCover { get; set; }

        [Required]
        public string UserID { get; set; }
        public virtual User User { get; set; }

        [Required]
        public int AuthorID { get; set; }
        public virtual Author Author { get; set; }
    }
}

Đây là action trong Controller:

    // GET: Novels/Create
        public IActionResult Create()
        {
            NovelViewModel novel = new NovelViewModel();
            ViewData["AuthorId"] = new SelectList(_context.Authors, "AuthorId", "AuthorId");
            ViewData["UserId"] = new SelectList(_context.Users, "UserId", "UserId");
            return View(novel);
        }

    // POST: Novels/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(NovelViewModel novel)
    {
        try
        { 
            if (ModelState.IsValid)
            {
                _context.Add(novel);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            else
            {
                ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
            }
        }
        catch (RetryLimitExceededException ex)
        {
            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
        }
        ViewData["AuthorId"] = new SelectList(_context.Authors, "AuthorId", "AuthorName", novel.AuthorID);
        ViewData["UserId"] = new SelectList(_context.Users, "UserId", "UserId", novel.UserID);
        return View(novel);
    }

Đây là View Create.cshtml

@model WebNovel.Models.ViewModels.NovelViewModel

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

<h1>Create</h1>

<h4>Novel</h4>
<hr />
<div class="row">
    <div class="col-md-4 p-3">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="NovelTitle" class="control-label"></label>
                <input asp-for="NovelTitle" class="form-control" />
                <span asp-validation-for="NovelTitle" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="NovelDescription" class="control-label"></label>
                <input asp-for="NovelDescription" class="form-control" />
                <span asp-validation-for="NovelDescription" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="NovelCover" class="control-label"></label>
                <input asp-for="NovelCover" class="form-control" />
                <span asp-validation-for="NovelCover" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="AuthorID" class="control-label"></label>
                <select asp-for="AuthorID" class ="form-control" asp-items="ViewBag.AuthorId"></select>
            </div>
            <div class="form-group">
                <label asp-for="UserID" class="control-label"></label>
                <select asp-for="UserID" class ="form-control" asp-items="ViewBag.UserId"></select>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

Em đặt breakpoint ở dòng if (ModelState.IsValid) và trong debugger hiện là 2 phần tử AuthorIDUserID bị invalid:

Em thực sự không biết mình bị sai ở chỗ nào nên rất mong nhận được sự giúp đỡ.

Đã có giải đáp: Trong View Model do 2 có 2 object Author và User nên khi thực hiện POST, ModelState sẽ kiểm tra luôn 2 thuộc tính này. Nhưng khi POST không có truyền về 2 object này nên ModelState bị invalid.

File NovelViewModel.cs sau khi sửa:

public class NovelViewModel
    {
        [Required]
        public String NovelTitle { get; set; }
        [Required]
        public String NovelDescription { get; set; }
        [Required]
        public String NovelCover { get; set; }

        [Required]
        public string UserID { get; set; }

        [Required]
        public int AuthorID { get; set; }
    }

File NovelController.cs sau khi sửa nên truyền lại View Model vào Model(Entity) để lưu được vào database.

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?