5

作成中のブログへのコメントをモデレートする簡単な(そしておそらく大雑把な)方法があります。これは学習/楽しいプロジェクトなので、私は自分でできることをすべて実行して、いくつかの異なるテクノロジーに慣れるようにしています。私のロジックに穴があるのか​​、それとも私がやっていることのより良い実装があるのだろうかと思っています。このサイトで匿名のコメントを許可するつもりですが、不適切だと思うものについてはそれらをモデレートしたいと思います。これが私がそれをした方法です:

私のモデルはEFコードの最初のアプローチを使用しています:

public class Comment
{
    public int Id { get; set; }
    public bool Moderated { get; set; }
    public string DisplayName { get; set; }
    public string Email { get; set; }
    public DateTime DateCreated { get; set; }
    public string Content { get; set; }
    public int PostId { get; set; }
    public Post Post { get; set; }
}

ここに標準的なもの。次に、ViewModelを作成して、ブログ投稿の詳細とそれに関連するすべてのコメントを次のようなページに表示します。

public class PostCommentViewModel
{
    public Post Post { get; set; }
    public List<Comment> Comment { get; set; }

    public PostCommentViewModel(int postId)
    {
        var db = new BlogContext();

        Post = db.Posts.First(x => x.Id == postId);
        var query = from x in db.Comments where x.PostId == postId && x.Moderated == true select x;

        Comment = query.ToList();
    }
}

コメントの場合、これはPostIdに関連し、モデレートされている(つまり、レビューできた)ものを取得するだけです。

これを表示するビューの場合、基本のスキャフォールディングテンプレートを使用します。

public ActionResult Details(int id = 0)
    {
        var viewModel = new PostCommentViewModel(id);
        return View(viewModel);
    }

cshtml:

@model CodeFirstBlog.ViewModels.PostCommentViewModel


<fieldset>
<legend>PostCommentViewModel</legend>
@Html.DisplayFor(x => x.Post.Title)
<br />
@Html.DisplayFor(x => x.Post.Content)
<br />
@Html.DisplayFor(x => x.Post.CreatedDate)
<hr />    
@foreach(var comment in Model.Comment)
{
    @Html.DisplayFor(x => comment.Content)
    <br />
    @Html.DisplayFor(x => comment.DateCreated)
    <br />
    @Html.DisplayFor(x => comment.DisplayName)
    <br />
    @Html.DisplayFor(x => comment.Email)
    <br />
    <hr />
}

</fieldset>
@Html.ActionLink("Add Comment", "AddComment", new { id = Model.Post.Id} )

これがコントローラーのAddCommentです

public ActionResult AddComment(int id = 0)
    {
        return View();
    }

    [HttpPost]
    public ActionResult AddComment(Comment comment, int id)
    {
        if (ModelState.IsValid)
        {
            comment.PostId = id;
            db.Comments.Add(comment);
            db.SaveChanges();
            return RedirectToAction("Details", "Blog", new { id = id });
        }
        return RedirectToAction("Details", "Blog", new { id = id });
    }

したがって、コメントが追加されると、モデレートはデフォルトでfalseに設定されるため、コメントはすぐには表示されません。これで、管理者がログインすると、ViewModerationビューに移動して、承認待ちのすべてのコメントのリストを返すことができます。

public ActionResult ViewModeration()
    {
        var comments = from x in db.Comments where x.Moderated == false select x;
        return View(comments);
    }

彼が承認ボタンをクリックすると、コントローラーでこれが実行されます。

 public ActionResult ApproveComment(int id)
    {
        Comment c = (from x in db.Comments
                     where x.Id == id
                     select x).First();
        c.Moderated = true;
        db.SaveChanges();
        return RedirectToAction("ViewModeration");
    }

私が本当に知りたいのはこれです:

  1. 知っているユーザーがポストバックのモデレート値をオーバーライドできるなど、この実装に穴はありますか?
  2. 従うべきより単純な、またはおそらくよりエレガントな解決策はありますか?繰り返しますが、事前に作成されたものは使用したくありません。このプロジェクトのポイントは、物事を学ぶことです。
4

2 に答える 2

4

モデルはこれまでのところ持ちこたえているように見えるので、次のように質問に答えます。

知っているユーザーがポストバックのモデレート値をオーバーライドできるなど、この実装に穴はありますか?

はい。送信した内容に基づいたFORMコードは作成していませんが、投稿値を介してコメントを作成し、データベースに直接保存していると想定します。これは悪いことかもしれません。ユーザーから必要な値のみを取得し、残りをコントローラーに入力することをお勧めします。

public ActionResult AddComment(Comment comment, int id)
{
    if (ModelState.IsValid)
    {
        // NEW
        comment.Moderated = false;

        comment.PostId = id;
        db.Comments.Add(comment);
        db.SaveChanges();
        return RedirectToAction("Details", "Blog", new { id = id });
    }
    return RedirectToAction("Details", "Blog", new { id = id });
}

従うべきより単純な、またはおそらくよりエレガントな解決策はありますか?繰り返しますが、事前に作成されたものは使用したくありません。このプロジェクトのポイントは、物事を学ぶことです。

先に述べたように、これは今のところ良さそうです。ただし、再利用性とテストの目的で、サービスやリポジトリなどの別のクラスでデータベース操作を取得する可能性があります。

したがって、コードは次のようになります。

public ActionResult AddComment(Comment comment, int id)
{
    if (ModelState.IsValid)
    {
        CommentService.Save(comment);
        return RedirectToAction("Details", "Blog", new { id = id });
    }
    return RedirectToAction("Details", "Blog", new { id = id });
}

これは大きな変更ではありませんが、このコードを再利用したい場合は、後で柔軟性を高めることができるという意味で大きな変化です。

PostCommentViewModelクラスに関しては、特にコンストラクターではなく、ViewModelsで操作を実行しませんでした。ViewModelを使用する方法は、ViewModelにジョブを実行させるのではなく、データをそれにバインドすることです。とにかくデータを取得している可能性があります。ViewModelsは、表示する必要があるものの構造のみを表します。したがって、そこからコードを取得し、それをサービス(つまり、CommentService)に配置します。

于 2012-06-29T17:17:50.433 に答える
2

最初の質問に対する答えは「はい」です。知識のあるユーザーがModeratedを設定できます。同様のことがGitHubにも少し前に起こりました。完全な説明については、この投稿を参照してください。簡単に説明すると、ユーザーはChromeデベロッパーツールなどでフォームデータを変更Moderatedし、投稿する前にモデルにプロパティを設定できます。

あなたの2番目の質問に答えるために、私は2つのオプションを見ることができます(他の人はあなたがもっと知っているならコメントしてください)

1)値をモデルにDefaultModelBinderバインドさせる代わりに、更新する必要のあるプロパティのみを呼び出して指定することができます。例えばCommentTryUpdateModel

public ActionResult AddComment(int id)
{
    if (ModelState.IsValid)
    {
        Comment comment = new Comment();
        TryUpdateModel(comment, new[] { "Email ", "DateCreated", "Content", "etc" });
        comment.PostId = id;
        db.Comments.Add(comment);
        ...
    }
    ...
}

2)より良いオプションであるimhoは、プロパティを含まない別のモデルクラスを作成し、Moderatedこのモデルをユーザーのコメントに使用することです。Comment管理者のみがアクセスできるアクションの管理目的で既存のモデルを使用できます。

于 2012-06-29T17:15:42.463 に答える