Entity framework EF代码第一个MVC4-ArgumentNullException on edit-我在这里做错了什么?

Entity framework EF代码第一个MVC4-ArgumentNullException on edit-我在这里做错了什么?,entity-framework,asp.net-mvc-4,ef-code-first,Entity Framework,Asp.net Mvc 4,Ef Code First,假设我有3个模型: [Table("UserProfile")] public class UserProfile //this is a standard class from MVC4 Internet template { [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public int UserId { get; set; } public string User

假设我有3个模型:

[Table("UserProfile")]
public class UserProfile //this is a standard class from MVC4 Internet template
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
}

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int CategoryId { get; set; }
    public virtual Category Category { get; set; }

    public int UserProfileId { get; set; }
    [ForeignKey("UserProfileId")]
    public virtual UserProfile UserProfile { get; set; }
}
我得到了一个例外。 快速查看调试,我可以知道我的Category为null,尽管CategoryId设置为正确的值

这句话的意思是,“难看的把戏”解决了这个问题,但我想它根本不应该存在。所以问题是如何正确地解决它

我会说这是EF延迟加载的原因,因为我有非常相似的代码用于添加Post,在调试中有相同的场景:正确的CategoryId,Category为null,尽管EF自动解决了Post类别依赖性,我不必使用任何额外的技巧。
在编辑方法上,EF有一些问题,但我无法找出我做错了什么。

这是按预期工作的。您的
Post
对象未附加到上下文,因此它没有理由执行任何延迟加载。这是完整的密码吗?我不明白为什么您需要将Category设置为
Modified
,因为您实际上并没有对其进行任何更改

无论如何,我建议您从数据库中查询现有帖子,并指定要让用户修改的相关字段,如:

[HttpPost]
public ActionResult Edit(Post post)
{
    var existingPost = context.Posts
        .Where(p => p.Id == post.Id)
        .SingleOrDetault();

    if (existingPost == null)
        throw new HttpException(); // Or whatever you wanna do, since the user send you a bad post ID

    if (ModelState.IsValid)
    {
        // Now assign the values the user is allowed to change
        existingPost.SomeProperty = post.SomeProperty;
        context.SaveChanges();

        return RedirectToAction("Index");
    }

    return View(post);
}
通过这种方式,您还可以确保用户试图编辑的帖子确实存在。仅仅因为您收到了一些操作参数,并不意味着它们是有效的,或者帖子的Id是真实的。例如,一些恶意用户可能会决定编辑他不允许编辑的帖子。你需要检查一下这类事情

更新

另一方面,您还可以避免手动查询当前用户的Id。如果您使用的是
简单成员身份
,则可以通过
WebSecurity.CurrentUserId

如果您使用的是
表单身份验证
,则可以执行
Membership.GetUser().ProviderUserKey

是的!:)从DB获取post成功了,lazy正在按预期工作。不,这不是完整的代码,我尽量保持简单。看起来根本不需要“修改”。这个答案正是我所期望的——如何正确处理这个问题的总体思路。谢谢:)
[HttpPost]
public ActionResult Edit(Post post)
{
    var existingPost = context.Posts
        .Where(p => p.Id == post.Id)
        .SingleOrDetault();

    if (existingPost == null)
        throw new HttpException(); // Or whatever you wanna do, since the user send you a bad post ID

    if (ModelState.IsValid)
    {
        // Now assign the values the user is allowed to change
        existingPost.SomeProperty = post.SomeProperty;
        context.SaveChanges();

        return RedirectToAction("Index");
    }

    return View(post);
}