« L'utilisateur peut faire X est l'utilisateur possède l'objet Y »: Mettre en œuvre la logique dans le modèle de validation ou de la logique du contrôleur?

StackOverflow https://stackoverflow.com/questions/9333916

  •  27-10-2019
  •  | 
  •  

Question

Considérons, par exemple à cause de la logique « Un utilisateur ne peut modifier ou supprimer un commentaire que l'utilisateur est l'auteur ».

Actions Mon contrôleur répétera la logique de vérifier si l'utilisateur actuellement connecté peut affecter le commentaire. Exemple

[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);
}

Bien sûr, je peux regrouper cette logique dans une méthode pour que je ne suis pas copier / coller cet extrait; Toutefois, en ce code sur le contrôleur et le mettre dans un ValidationAttribute garde mon action plus petit et plus facile à des tests d'écriture pour. Exemple

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; }
}

est un modèle de validation de l'outil pour ce travail? Je aime prendre cette préoccupation sur le contrôleur d'action; mais dans ce cas, il peut compliquer encore les choses. Cela est particulièrement vrai si l'on considère que cette action fait partie d'une API RESTful et doit retourner un autre code d'état HTTP en fonction des erreurs de validation dans le ModelState.

Y at-il "les meilleures pratiques" dans ce cas?

Était-ce utile?

La solution

Personnellement, je pense qu'il a l'air bien, mais vous se laisser emporter avec annotations. Je pense que cela ne appartiennent dans votre couche de présentation et il doit être manipulé par votre couche de service.

j'aurais quelque chose sur les lignes suivantes:

[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
    }
} 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top