如何使用MVC3创建包含内联评论发布的新闻页面?

时间:2012-10-02 16:55:40

标签: c# asp.net-mvc-3 entity-framework

我在过去几周一直在学习MVC3,我正在尝试编写我认为应该是一个足够简单的功能,但我遇到了让它正常工作的真正问题。

方案

我的网站将包含在主页上汇总的新闻帖子,其中包含用于查看每个文章在其页面中的完整详细信息的链接。

可以对每篇文章进行评论,这些评论显示在每篇文章的详细信息页面的末尾。经过身份验证的用户应该能够从显示文章本身的页面中将自己的评论发布到文章中。我想避免将用户带到一个单独的页面(虽然我从代码的角度理解这更容易,但我不同意这是一个很好的用户体验!)。

有关我希望如何看待的一个例子,Scott Hanselman的博客(http://www.hanselman.com)就是一个完美的例子(尽管他的主页显示的是整篇文章,而不仅仅是摘要!) - 它链接到评论页面和“添加评论”表格整齐地位于底部,与文章一致。

我到目前为止

我已经设法为我的新闻部分编写了Controller,使用了Index方法(检索X个最近的帖子)和一个“Comments”方法来显示完整的文章和评论。我还用它自己的Controller方法创建了一个名为“CommentForm”的部分视图。来自以下控制器的代码片段:

//
// GET: /News/ 
public ActionResult Index()
{
    using (var nm = new NewsManager())
    {
        var news = nm.GetLatestActiveNewsArticles(50, "System");
        return View(news);
    }
}
//
// GET: /News/Comments/20
public ActionResult Comments(int id)
{
    using (var nm = new Rapallo.Core.Managers.NewsManager())
    {
        var article = nm.GetArticle(id);
        return View(article);
    }
}
// GET: /News/CommentForm/20
[HttpGet()]
public ActionResult CommentForm(int newsId)
{
    return View(new Rapallo.DataAccess.Comment() { NewsId = newsId });
}
// 
// POST: /News/Comments/20
[Authorize()]
[HttpPost()]
public ActionResult Comments(Comment comment)
{
    using (var nm = new NewsManager())
    {
        var article = nm.GetArticle(comment.NewsId.Value);
        if (null == article) HttpNotFound();
    }
    using (var cm = new CommentManager())
    {
        if (cm.AddCommentToNews(comment.NewsId.Value, CurrentUser.RapalloUser.Id, comment.Body))
        return RedirectToAction("Comments", "News", new { id = comment.NewsId.Value });
    }
    return HttpNotFound();
}

从评论视图中,代码片段显示我想要添加评论表单的位置:

@if (User.Identity.IsAuthenticated)
{
    @Html.Partial("Comment", new Rapallo.DataAccess.Comment() { NewsId = Model.Id });
}

此视图指定:

@model Rapallo.DataAccess.News

最后,评论形成了自己:

@model Rapallo.DataAccess.Comment
@using (Html.BeginForm())
{ 
    @Html.TextAreaFor(m => m.Body);
    <input type="submit" value="Send Comment" />
}

问题

简而言之,当我提交评论表单(正确呈现)时,评论模型上的NewsId不会被填充,因此控制器无法将新评论与正确的新闻帖子相关联。

如果有人能指出我哪里出错了,我会很感激!我试图调整NerdDinner的一些代码来完成这项工作,以及在火车上花费无数个小时尝试各种部分视图组合,不同模型,甚至在我的控制器中重命名方法以试图让它工作。

我非常热衷于将“添加评论”功能封装到它自己的单独表单中,并且能够使用它来添加评论而不仅仅是新闻文章。数据库模式和域模型已经支持这一点,我无法让UI工作。

非常欢迎任何帮助,并感激不尽。

2 个答案:

答案 0 :(得分:1)

我们必须解决类似的问题,但我们选择了基于JavaScript的解决方案,而不是使用HTML表单,而是将消息发布到API控制器。

Detail.aspx

<!-- Display the Content (i.e. News Story, Product, etc -->
<%= Html.DisplayFor(n => Model.Content[Model.Content.PageIndex], "ReleaseFull")%>
<!-- Display the comments and form.  Pass in the type of content and the Id -->
<% Html.RenderAction("Commenting", "Home", new { area = "Reviews",
    contentTypeName = "product",
    contentTypeId = ContentType.Product,
    contentId = Model.Content[Model.Content.PageIndex].Id }); %>

评论控制器

[ChildActionOnly]
public ActionResult Commenting(string contentTypeName, int contentTypeId, int contentId)
{
    //psuedo-code to get comments
    var comments = CommentingAPI.GetCommentsForContentType(contentTypeId, contentId);

    var viewModel = new CommentsListing
    {
        Comments = comments,
        ContentId = contentId,
        ContentTypeId = contentTypeId,
        ContentTypeName = contentTypeName
    };
    return View(viewModel);
}

Commenting.aspx

<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<Website.ViewModels.CommentsListing>" %>

<div id="commenting" class="commenting">
        <h3 class="h2">Comment and then share on Facebook &amp; Twitter</h3>
        <div class="arrow"></div>
        <textarea placeholder="Type your comment here..." class="w100 p10 tMrg10" cols="40" rows="4" id="commentText></textarea>
        <div class="textarea-support">
            <span class="post-action">
                <span id="commentButton"><a class="btn l-btn-lg">Post Comment</a></span>
            </span>
        </div>

    <!-- Insert new comments here so they show up at the top of the listing --> 
    <div id="newComments"></div>

    <% foreach (var comment in Model.Comments) { %>
        <!-- Display the comments here -->
        <% var memberComment = comment; %><%= Html.DisplayFor(c => memberComment)%>
    <% } %>
</div>

<script type="text/javascript">
    //using a custom jQuery plugin we hook up the commenting section
    //when the user clicks "Post Comment" the message is posted to
    //another Controller using $.ajax({ type:POST }); 
    //The controller stores the comment in the database and returns an instance of the comment
    $(function () {
        $('#commenting').commenting( {
            contentTypeTypeId: <%: Model.ContentTypeId %>,
            contentId: <%: Model.ContentId %>,
            isAuthenticated: <%= Html.IsMember() %>
    });
</script>

答案 1 :(得分:1)

简单的答案是,您需要在表单上使用NewsId表示模型绑定器才能找到它。因此,请将评论表单更改为:

@model Rapallo.DataAccess.Comment
@using (Html.BeginForm())
{ 
    @Html.HiddenForm(m => m.NewsId);
    @Html.TextAreaFor(m => m.Body);
    <input type="submit" value="Send Comment" />
}