2017-08-31 4 views
1

Pour l'un de mes projets, j'utilise l'API Web avec une sorte d'architecture SOA. Dans le contrôleur, je veux attraper l'exception (renvoyé par Repository) et retourner HttpResposeMessage.

Ce que je veux, c'est qu'il devrait y avoir un BaseController qui hérite de ApiController (class BaseController : ApiController) et chacun de mon contrôleur devrait être hérité par baseController
par exemple. class TaskController : BaseController et si une exception se produit dans mon contrôleur, il doit être géré par BaseController. Démo:
Gestion des exceptions dans Web API Controller et lancement du message d'erreur personnalisé

Voici les nouveaux projets dans notre VS Solution: (structure de projet)

XYZ.Model 
XYZ.Repository 
XYZ.WebServices 
XYZ.Exception 
XYZ.UI 

code: XYZ.Model

public class Error 
{ 
    public string Code { get; set; } 
    public string Message { get; set; } 

} 

XYZ.Exception

// To create the custom exception as per our need 
public class BaseException : Exception 
{ 
    private Error _error; 
    public Error Error 
    { 
     get { return _error; } 
    } 

    public BaseException() 
    { 
     _error = new Error(); 
    } 

    public void SetErrorCode(string code) 
    { 
     _error.Code = code; 
    } 

    public void SetErrorMessage(string message) 
    { 
     _error.Message = message; 
    } 
} 


public class TaskNotFoundException : BaseException 
{ 
    public TaskNotFoundException() 
    { 
     string errorCode = "T0001"; 
     base.SetErrorCode(errorCode); 
     base.SetErrorMessage((new ExceptionMessage()).GetExceptionMessage(errorCode)); 
    } 
} 

XYZ.Repository

public Task UpdateTaskDetails(Task task) 
{ 
    try 
    { 
     //--Task updating logic--// 
    } 
    catch (Exception ex) 
    { 
     throw new TaskUpdateFailedException(); 
    } 
    return task; 
} 

XYZ.WebServices

public class BaseController : ApiController 
{ 
    public HttpResponseMessage CreateResponseMessage() 
    { 
     try 
     { 
      GetTasksByUserIdAndProjectId(new TaskQuery()); 
     } 
     catch(BaseException exception) 
     { 
      return Request.CreateResponse(HttpStatusCode.InternalServerError, exception.Error); 
     } 
    } 

    public virtual List<Task> GetTasksByUserIdAndProjectId(TaskQuery query) 
    { 
     Console.WriteLine("I can be overridden"); 
    } 
} 


public class TaskController : BaseController 
{ 
    [HttpPost] 
    public override List<Task> GetTasksByUserIdAndProjectId(TaskQuery query) 
    { 
     return _taskRepo.GetTasksByUserIdAndProjectId(query.UserId, query.ProjectId); 
    } 

} 

En TaskController si une exception se produit dans GetTasksByUserIdAndProjectId méthode, il doit jeter l'exception à la BaseController CreateReponseMessage() et là, il retournera le HttpResponseMessage au client.

Remarque: Dans chaque contrôleur il existe plusieurs méthodes Get/Put/Post, il n'est donc pas possible de déclarer toutes les méthodes (méthodes de service Web) dans BaseController pour intercepter l'exception de classe enfant dans la structure actuelle de mon projet.

Existe-t-il une meilleure façon de gérer Exception dans l'API Web qui s'intègre facilement dans mon projet?

+0

Cela peut être mieux fait en utilisant un filtre d'exception. – Nkosi

+0

@Nkosi, Merci pour votre suggestion, j'ai mis en place un filtre d'exception et ça fonctionne très bien. Mais j'ai une autre question "Pouvons-nous gérer une erreur de validation de type erreur dans le filtre d'exception? AS échec de validation n'est pas une exception, mais je veux qu'il soit géré dans une classe commune." – BhushanK

Répondre

3

Nous utilisons un filtre d'exception comme celui-ci:

D'abord, nous créons notre propre exception:

public class UserFriendlyException: Exception 
    { 
     public UserFriendlyException(string message) : base(message) { } 
     public UserFriendlyException(string message, Exception innerException) : base(message, innerException) { } 
    } 

Ensuite, nous créons un filtre:

public class UserFriendlyExceptionFilterAttribute: ExceptionFilterAttribute 
    { 
     public override void OnException(HttpActionExecutedContext context) 
     { 
      var friendlyException = context.Exception as UserFriendlyException; 
      if (friendlyException != null) 
      { 
       context.Response = context.Request.CreateResponse(HttpStatusCode.BadRequest, new {Message = friendlyException.Message}); 
      } 
     } 
    } 

Et enfin dans la configuration pour WebAPI nous ajoutons ce filtre. Avec cette solution, vous pouvez lancer UserFriendlyException n'importe où dans le code et la réponse sera en fonction du filtre.

+0

Merci pour votre réponse, j'ai mis en place un filtre d'exception et ça fonctionne très bien. Mais j'ai une autre question "Pouvons-nous gérer une erreur de validation de type erreur dans le filtre d'exception? AS L'échec de validation n'est pas une exception mais je veux qu'il soit traité dans une classe commune.". – BhushanK