如何将此子模型引用传递给ASP.NET MVC中父域模型中的虚拟ICollection?

时间:2015-10-24 22:52:10

标签: c# asp.net asp.net-mvc-5

我正在使用触发基本控制器操作方法的视图表单为我的ASP.NET MVC博客引擎创建评论系统:

FORM:

 @if (User.Identity.IsAuthenticated)
    {
        //using (Html.BeginForm())
        //  {
        <div class="new_comment">
            <h6 id="shortcodes" class="page-header"><i class="fa fa-file-text-o"></i> Leave a comment</h6>
            <div class="hline"></div>
            <form class="form-horizontal" action="@Url.Action("CreateComment")" method="post" role="form">
                <div class="form-group">
                    <div class="col-sm-4 col-md-4">
                        <textarea rows="7" class="form-control" name="Message" placeholder="Your Comment Here..."></textarea>
                        @Html.AntiForgeryToken()
                        <input type="hidden" name="Slug" value="@Model.Slug"/>
                        <input type="hidden" name="PostId" value="@Model.Id"/>
                        <br/>
                    </div>
                </div>
                <div class="form-group">
                    <input type="submit" value="Post Comment" class="btn btn-primary" style="margin-left: 12px"/>
                </div>
            </form>
        </div>
        //}
    }

控制器:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult CreateComment([Bind(Include = "PostId,Message,Username,DatePosted")]Comment comment)
    {
        var post = db.BlogPosts.Find(comment.PostId);
        if (post == null)
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

        if (ModelState.IsValid)
        {
            comment.Username = User.Identity.GetUserId();
            comment.DatePosted = DateTimeOffset.Now;
            db.Comments.Add(comment);
            db.SaveChanges();
        }

        return RedirectToAction("BlogPostDetails", new { slug = post.Slug});
    }

我在if语句中包含的每个表达式旁边设置了断点,并确认传递的任何数据值("PostId, Message, Username, DatePosted")都不为空,并且db.SaveChances()正在提交更改数据库。接下来,这是Models.BlogPosts ...

模型:

 public class BlogPosts
{
    public BlogPosts()
    {
        this.Comments = new HashSet<Comment>();
    }

    public int Id { get; set; }
    public DateTimeOffset Created { get; set; }
    public DateTimeOffset? Updated { get; set; }
    [AllowHtml]
    [Required]
    public string Title { get; set; }
    public string Slug { get; set; }
    [Required]
    public string Category { get; set; }
    [AllowHtml]
    [Required]
    public string Body { get; set; }
    public string MediaURL { get; set; }
    public bool Published { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }
}

public class Comment
{
    public int Id { get; set; }
    public int PostId { get; set; }
    public string Username { get; set; }

    [Required]
    [DataType(DataType.MultilineText)]
    public string Message { get; set; }
    public DateTimeOffset DatePosted { get; set; }
    public Nullable<System.DateTimeOffset> Edited { get; set; }

    public virtual BlogPosts BlogPost { get; set; }
    public virtual ApplicationUser Author { get; set; }
    //public int? ParentId { get; set; }
    //[ForeignKey("ParentId")]
    //public virtual ICollection<Comment> Children { get; set; }
    //public string ParentComment { get; internal set; }
}

这是无法执行的视图:

查看不执行

 @foreach (var item in Model.Comments.OrderByDescending(c => c.DatePosted))
    {
        <div class="comment">
            <p>
                @if (item.Username == null)
                {
                    <small>By: Anonymous</small><span>|</span>
                }
                else
                {
                    <small>By: @Html.DisplayFor(modelItem => item.Username)</small><span>|</span>
                }
                <small>Date: @Html.DisplayFor(modelItem => item.DatePosted)</small>
                @if (item.Edited != null)
                {
                    <span>|</span><small>Updated: @Html.DisplayFor(modelItem => item.Edited)</small>
                }
            </p>
            <div>
                @Html.DisplayFor(modelItem => item.Message)
            </div>
        </div>
        if (item.Username == User.Identity.GetUserId() || User.IsInRole("Admin") || User.IsInRole("Moderator"))
        {
            <div>
                @Html.ActionLink("Edit", "_EditComment", new { id = item.Id }) <span>|</span>
                @Html.ActionLink("Delete", "_DeleteComment", new { id = item.Id })
            </div>
        }
        <br />
        <!--<div class="hline"></div>-->
    }
    <div>
        <input type="button" class="btn btn-primary" value="Return to Blog Roll" onclick="location.href = '@Url.Action("BlogIndex")'">
    </div>
    <br />
    @if (User.Identity.IsAuthenticated || User.IsInRole("Admin") || User.IsInRole("Moderator"))
    {
        <input type="button" class="btn btn-primary" value="Modify Post" onclick="location.href = '@Url.Action("BlogAdmin")'">
        <br />
        <br />
    }

在上面视图的第一行设置断点时:@foreach (var item in Model.Comments.OrderByDescending(c => c.DatePosted)),引用 public virtual ICollection<Comment> Comments类中的Models.BlogPosts保持为空(这显然意味着我视图中的逻辑无法执行且未发布评论)。

我是ASP.NET MVC,EF Code-First等新手,显然不明白我的控制器如何将子模型中的注释值传递给父模型中的public virtual ICollection<Comment> Comments。 ..我的Models.Comment控制器中引用的CommentCreate如何包含值,而我Models.BlogPosts中的虚拟引用不相同?

编辑:在几位用户对我的代码中的修饰错误和严重错误以及有用的ASP.NET MVC资源指针的反馈非常好后,我确定传递的空引用已经过了在我的域模型中使用不正确的属性命名约定。见下面的答案。

2 个答案:

答案 0 :(得分:1)

您包含PostId,但实际的属性名称是Id。您还需要显示您的视图所接收的模型。如果你对你所曝光的内容感到羞愧(例如Id,为什么不把它标记为隐藏字段?)。

在控制器中只传递您要编辑的模型,例如保留一个控制器仅用于网址路由,仅为您的对象保留您的模型,您的视图应仅适用于您传入的模型。

答案 1 :(得分:0)

最后发现我的BlogPost域模型中public virtual BlogPosts BlogPost中的Models.Comment属性需要重命名,以匹配域模型的外键:public int PostId。解决方案执行如下:

  1. 将属性名称更改为Post
  2. 然后从我的数据库中的PostId表中手动删除空Comment值,
  3. 然后在NuGet中运行update-database -f命令。