带有外键的 ViewModel 和创建操作

ViewModel with foreign key and Create action

我有一个页面显示 post 的详细信息,并且已识别的用户可以在 post 上添加评论。

我的问题:

  1. PostID 和 UserID 在 Comment 模型中是 FK,不会从视图传递到控制器

  2. CommnetMessage 为空!!

怎么了?

评论模型:

public class Comment : System.Object
{
    public Comment()
    {
        this.CommnetDate = General.tzIran();
    }

    [Key]
    public int CommentID { get; set; }

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

    [Required]
    public DateTime CommnetDate { get; set; }
    public string UserId { get; set; }
    [Key, ForeignKey("UserId")]
    public virtual ApplicationUser ApplicationUser { get; set; }

    public int PostID { get; set; }
    [Key, ForeignKey("PostID")]
    public virtual Post posts { get; set; }
}

Post 型号:

public class Post : System.Object
    {
        public Post()
        {
            this.PostDate = General.tzIran();
            this.PostViews = 0;
        }

        [Key]
        public int PostID { get; set; }
        public string PostName { get; set; }
        public string PostSummery { get; set; }
        public string PostDesc { get; set; }
        public string PostPic { get; set; }
        public DateTime PostDate { get; set; }
        public int PostViews { get; set; }
        public string postMetaKeys { get; set; }
        public string PostMetaDesc { get; set; }

        public string UserId { get; set; }
        [ForeignKey("UserId")]
        public virtual ApplicationUser ApplicationUser { get; set; }

        public int CategoryID { get; set; }
        [ForeignKey("CategoryID")]
        public virtual Category Category { get; set; }

        public virtual ICollection<Comment> commnets {get; set;}
    }


public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    /*Realations*/

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

查看模型:

public class PostViewModel
{
    public ApplicationUser Users { get; set; }
    public Post posts { get; set; }
    public Category Categories { get; set; }
    public IEnumerable<Comment> ListCommnets { get; set; }
    public Comment Commnets { get; set; }
}

控制器:

public ActionResult Details(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    var post = db.Posts.Find(id);

    post.PostViews += 1;
    db.SaveChanges();

    if (post == null)
    {
        return HttpNotFound();
    }
    return View(new PostViewModel() { posts = post });
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details([Bind(Include = "CommentID,CommnetMessage,CommnetDate,UserId,PostID")] Comment comment , int? id)
{
    int pid = comment.PostID;
    if (ModelState.IsValid)
    {
        db.CommentS.Add(comment);
        db.SaveChanges();
        TempData["notice"] = "پیغام شما با موفقیت ثبت شد.";
        return RedirectToAction("success");
    }

    ViewBag.UserId = new SelectList(db.Users, "Id", "FirstName", comment.UserId);
    ViewBag.PostID = id;
    return View( new PostViewModel() { posts = db.Posts.Find(id)});
}

public ActionResult success()
{

    ViewBag.Message = "از طریق فرم زیر می توانید برایمان پیغام بگذارید.";

    return View("Details", new PostViewModel() { ListCommnets = db.CommentS });
}

评论部分视图:

@using Microsoft.AspNet.Identity
@using FinalKaminet.Models
@using Microsoft.AspNet.Identity.EntityFramework

@model FinalKaminet.ViewModel.PostViewModel

@if (TempData["notice"] != null)
{
    <p>@TempData["notice"]</p>
}


@if (Request.IsAuthenticated)
{
    var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
    var user = manager.FindById(User.Identity.GetUserId());

    using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
            <div class="form-horizontal">
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                @Html.HiddenFor(model => model.posts.PostID)
                @Html.HiddenFor(model => model.Users.Id)
                <div class="form-group">
                        @Html.LabelFor(model => model.Users.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
                        <div class="col-md-10">
                            @{
                                var name = user.FirstName + " " + user.LastName;
                            }
                            <input type="text" id="Id" value="@name" disabled="disabled" class="form-control" />
                        </div>
                    </div>

                <div class="form-group">
                    @Html.LabelFor(model => model.Commnets.CommnetMessage, htmlAttributes: new { @class = "control-label col-md-2" })
                    <div class="col-md-10">
                        @Html.EditorFor(model => model.Commnets.CommnetMessage, new { htmlAttributes = new { @class = "form-control" } })
                        @Html.ValidationMessageFor(model => model.Commnets.CommnetMessage, "", new { @class = "text-danger" })
                    </div>
                </div>

                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" value="Send" class="btn btn-default" />
                    </div>
                </div>
            </div>
    }
}
else
{
    <p>@Html.ActionLink("Log in", "Login", "Account", new { returnUrl = Request.Url }, null)</p>
}

如@StephenMuecke 所述,您的视图模型是 PostViewModel,并且所有 编辑器、隐藏字段 都是基于您的视图模型创建的。例如,当您使用 @Html.HiddenFor(model => model.posts.PostID) 生成隐藏字段并尝试 post 您的数据 MVC 模型绑定器尝试将此字段的值绑定到您的 Action 方法[=中指定的模型26=]。在你的情况下它是 Comment 所以,MVC 模型绑定器将尝试将生成的隐藏字段的值绑定到 Comment.posts.PostID 不存在。为了使一切完美运行,您必须使用相同的视图模型作为操作方法的参数:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details(PostViewModel viewModel)
{
......
}

另外,正如@StephenMuecke 所说,您的视图模型应该只包含您需要的那些属性。例如,您的 PostViewModel 应该如下所示:

public class PostViewModel
{
    // Actually, you do not need UserId property
    // as it should be retrieved inside controller
    // from current user data
    public string UserId { get; set; }
    public string UserName { get; set; }
    public int PostID { get; set; }
    public string CommentMessage { get; set; }
}

回到您的操作方法,您必须将视图模型映射到您的模型:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Details(PostViewModel viewModel)
{
    Comment comment = new Comment
    {
        CommnetMessage = viewModel.CommentMessage,
        // and other properties
    }

    // Save your model and etc.
}