【问题标题】:Why is ModelState.IsValid returning true but then saving changes throws a DbEntityValidationError?为什么 ModelState.IsValid 返回 true 但保存更改会引发 DbEntityValidationError?
【发布时间】:2015-12-17 15:30:07
【问题描述】:

如果我有两个模型(Post 和 Comment,其中一个 Post 可以有许多 cmets)并且在我的 Post 控制器中我有一个“LeaveComment”方法......为什么 ModelState.IsValid 在这个方法中返回 true,但是然后 db. SaveChanges() 抛出 DbEntityValidationException?

ModelState.IsValid 是否只检查 Post 的有效性,而不检查正在创建的 Comment 的有效性?

下面是我的部分代码。

编辑:我也很可能完全采取了错误的方法

控制器:

public class PostsController : Controller
{
    private MyEntityModelContainer db = new MyEntityModelContainer();

    [HttpPost, ActionName("LeaveComment")]
    [ValidateAntiForgeryToken]
    public ActionResult LeavePostComment(int? id, string CommentText)
    {
        Post post = db.Posts.Find(id);
        post.LeaveComment(db, CommentText);

        if (ModelState.IsValid)
        {
           //Evaluates to true!

            db.Entry(post).State = System.Data.Entity.EntityState.Modified;
            db.SaveChanges();  //throws DbEntityValidationException
        }
    }
}

评论模型:

public partial class Comment
{
    public Comment () {}

    public Comment(string comment)
    {
        this.CommentText = comment;
    }

    [Required(ErrorMessage="You must enter a comment")]
    public string CommentText { get; set; }

    public virtual Post Post { get; set; }
}

后模型:

public partial class Post
{        
    public virtual ICollection<Comment> Comments { get; set; }

    public void LeaveComment(MyEntityModelContainer db, string comment_text)
    {
        Comment comment = new Comment(comment_text);
        this.Comments.Add(comment);
    }
}

【问题讨论】:

  • 查看 DbContext 的 ChangeSet 谁和什么未能通过验证。
  • 与问题无关,为什么将 db 传递给 LeaveComment?为什么不在获取 Post 和调用 LeaveComment 之前检查有效性?
  • LeaveComment 中,您没有将评论分配给帖子。我敢打赌你的数据库有一个外键约束(当然应该有。)
  • Jack Hughes -- this.Comments.Add(comment) 应该将评论添加到帖子中,不是吗?
  • Andy Wiesendanger - 抱歉,在这种情况下传递 db 是不必要的,但在其他一些方法中使用了这些方法,而这些方法在试图解决这个问题时被忽略了。

标签: asp.net-mvc entity-framework asp.net-mvc-5 entity-framework-6


【解决方案1】:

ModelState 作用于给定动作的模型。在您的情况下,您没有模型。您只需传入一个字符串并使用它来创建模型。你可以检查string.isnullorempty(commenttext)。或者,改用模型。

【讨论】:

    【解决方案2】:

    ModelState 是 POST 数据/ViewModel 的状态,而不是实体模型的状态。 (见http://www.exceptionnotfound.net/asp-net-mvc-demystified-modelstate/)。

    要使 MVC 验证正常工作,请使用 ViewModel 作为评论:

    public class CommentViewModel : /* optional: */ IValidatableObject {
    
        [Required(ErrorMessage="You must enter a comment")]
        public string CommentText { get; set; }
    
        // example how to check for valid ID range
        // this should probably not be nullable if the Id is required by your code
        [Range(1, int.MaxValue)]
        public int PostId { get; set; }
    
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
           // optional: you can put any complex validation logic here ...
         }
    }
    

    将您的操作签名更改为

    public ActionResult LeavePostComment(CommentViewModel viewModel)
    

    然后ModelState.IsValid 将检查 ViewModel 中的所有验证属性并调用 Validate() 方法(如果已定义)。

    【讨论】:

    • CommentText 为空,是的。试图让 ModelState.IsValid 因此返回 false ......但我想我知道我做错了什么
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 2017-07-25
    • 2019-06-16
    • 1970-01-01
    • 2015-02-08
    相关资源
    最近更新 更多