3

たとえば、「ユーザーは、ユーザーが作成したコメントのみを編集または削除できる」というロジックを考えてみてください。

My Controller Actionsは、現在ログインしているユーザーがコメントに影響を与える可能性があるかどうかを確認するロジックを繰り返します。例

[Authorize]
public ActionResult DeleteComment(int comment_id)
{
    var comment = CommentsRepository.getCommentById(comment_id);
    if(comment == null) 
        // Cannot find comment, return bad input
        return new HttpStatusCodeResult(400); 
    if(comment.author != User.Identity.Name)
        // User not allowed to delete this comment, return Forbidden
        return new HttpStatusCodeResult(403);
    // Error checking passed, continue with delete action
    return new HttpStatusCodeResult(200);
}

もちろん、そのスニペットをコピー/貼り付けしないように、そのロジックをメソッドにバンドルすることもできます。ただし、そのコードをコントローラーから取り出してValidationAttributeに入れると、アクションが小さくなり、テストを記述しやすくなります。例

public class MustBeCommentAuthorAttribute : ValidationAttribute
{
    // Import attribute for Dependency Injection
    [Import]
    ICommentRepository CommentRepository { get; set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        int comment_id = (int)value;
        var comment = CommentsRepository.getCommentById(comment_id);
        if(comment == null) 
            return new ValidationResult("No comment with that ID"); 
        if(comment.author != HttpContext.Current.User.Identity.Name)
            return new ValidationResult("Cannot edit this comment");
        // No errors
        return ValidationResult.Success;
     }
}

public class DeleteCommentModel
{
    [MustBeCommentAuthor]
    public int comment_id { get; set; }
}

モデル検証はこの仕事に適したツールですか?私はその懸念をコントローラーのアクションから取り除くのが好きです。しかし、この場合、事態はさらに複雑になる可能性があります。これは、このアクションがRESTful APIの一部であり、ModelStateの検証エラーに応じて異なるHTTPステータスコードを返す必要があると考える場合に特に当てはまります。

この場合の「ベストプラクティス」はありますか?

4

1 に答える 1

0

個人的には見た目はいいと思いますが、アノテーションに夢中になっています。これはプレゼンテーション層に属していないので、サービス層で処理する必要があると思います。

私は次の行に何かを持っているでしょう:

[Authorize] 
public ActionResult DeleteComment(int comment_id) 
{ 
    try
    {
       var result = CommentsService.GetComment(comment_id, Auth.Username);

       // Show success to the user
    }
    catch(Exception e)
    {
       // Handle by displaying relevant message to the user
    }
} 
于 2012-02-17T23:50:09.567 に答える