1

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

场景

我的网站将包含新闻帖子,在主页上进行了总结,并带有链接以在其自己的页面中查看每篇文章的完整详细信息。

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

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

到目前为止我在哪里

我已经成功地为我的新闻部分编写了控制器,使用 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 工作。

任何帮助都将受到欢迎并感激不尽。

4

2 回答 2

1

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

详细信息.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);
}

评论.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>
于 2012-10-02T17:31:07.037 回答
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" />
}
于 2012-10-02T19:12:29.313 回答