1

私はここ数週間で MVC3 を学んでおり、十分に単純な機能であると思われるものを書き込もうとしていますが、正しく動作させるのに実際の問題があります。

シナリオ

私のウェブサイトには、ホームページに要約されたニュース投稿が含まれ、各記事の詳細を個別のページに表示するためのリンクが含まれます。

各記事にはコメントを付けることができ、これらのコメントは各記事の詳細ページの最後に表示されます。認証されたユーザーは、記事自体を表示するページから記事に自分のコメントを投稿できる必要があります。ユーザーが別のページに移動するのを避けたいです (コードの観点からは、この方が簡単であることは理解していますが、それが優れた UX であることに同意しません!)。

私がこれをどのように見せたいかの例として、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" />
}

問題

簡単に言うと、コメント フォームを送信すると (正しく表示されます)、Comment モデルの NewsId が入力されないため、コントローラーは新しいコメントを正しいニュース投稿に関連付けることができません。

誰かが私が間違っているところを指摘していただければ幸いです!これを機能させるために NerdDinner のコードをいくつか適応させようとしましたが、電車の中で数え切れないほどの時間を費やして、部分ビューのさまざまな組み合わせ、さまざまなモデル、さらにはコントローラーのメソッドの名前を変更して、これを機能させようとしました。

「コメントの追加」機能を独自の別のフォームにカプセル化し、これを使用して単なるニュース記事以外にもコメントを追加できるようにすることに非常に熱心です。データベース スキーマとドメイン モデルは既にこれをサポートしていますが、UI を動作させることができません。

どんな助けでも大歓迎です。

4

2 に答える 2

1

同様の問題を解決する必要がありましたが、HTMLフォームを使用する代わりに、APIコントローラーにメッセージを投稿するJavaScriptベースのソリューションを選択しました。

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>
于 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 に答える