Conformément à la documentation ServiceStack , nous disposons d’un gestionnaire d’exception de service global. Les docs disent que ce gestionnaire devrait enregistrer l’exception puis appeler DtoUtils.HandleException
, comme ceci:
private object LogServiceException(object request, Exception exception) { var message = ssortingng.Format("Here we make a custom message..."); _logger.Error(message, exception); return DtoUtils.HandleException(this, request, exception); }
Il en résulte que l’erreur est consignée deux fois, puisque DTOUtils.HandleException
enregistre également , dans un format moins personnalisé. Oui, je préfère de loin ceci à la journalisation de DTOUtils et je ne veux pas simplement l’utiliser.
Comment désactiver l’enregistrement DTOUtils
tout en conservant le rest des fonctionnalités? Personne n’aime recevoir deux fois plus de courriels d’erreur qu’ils le devraient.
J’espère que le code suivant résout votre problème.
basé sur la documentation New API, Custom Hooks, ServiceRunner
et gestion fine des erreurs à l’aide de ServiceRunner de la nouvelle API
dans AppHost.Configure
LogManager.LogFactory = new ServiceStack.Logging.Support.Logging.ConsoleLogFactory();
puis en classe AppHost
public override IServiceRunner CreateServiceRunner (ActionContext actionContext) { return new MyServiceRunner (this, actionContext); }
dans la classe ServiceRunner
public class MyServiceRunner : ServiceRunner { public override object HandleException(IRequestContext requestContext, T request, Exception ex) { if ( isYourCondition ) { ResponseStatus rs = new ResponseStatus("error1", "your_message"); // optionally you can add custom response errors rs.Errors = new List(); rs.Errors.Add(new ResponseError()); rs.Errors[0].ErrorCode = "more details 2"; // create an ErrorResponse with the ResponseStatus as parameter var errorResponse = DtoUtils.CreateErrorResponse(request, ex, rs); // log the error Log.Error("your_message", ex); return errorResponse; } else return base.HandleException(requestContext, request, ex); } }
si vous renvoyez la base.HandleException, il appelle en interne la DtoUtils.HandleException. Vous verrez dans la console une seule erreur de journal.
Dans le client, si vous gérez l’exception WebServiceException pour les erreurs personnalisées.
catch (WebServiceException err) { if ( err.ResponseStatus.Errors != null) { // do something with err.ResponseStatus.Errors[0].ErrorCode; } }
DtoUtils.HandleException
pas DtoUtils.HandleException
car il enregistre l’erreur. DtoUtils.HandleException
pas ServiceRunner.HandleException
non plus, il appelle DtoUtils.HandleException
.
Appelez DtoUtils.CreateErrorResponse
pour DtoUtils.CreateErrorResponse
la réponse (elle est utilisée par DtoUtils.HandleException
). L’assistant ToResponseStatus
est également dans DtoUtils
Mon AppServiceRunner est maintenant comme ceci:
public class AppServiceRunner : ServiceRunner { public AppServiceRunner(AppHost appHost, ActionContext actionContext) : base(appHost, actionContext) { } public override object HandleException(IRequestContext requestContext, T request, Exception ex) { LogException(requestContext, request, ex); var responseStatus = ex.ToResponseStatus(); return DtoUtils.CreateErrorResponse(request, ex, responseStatus); } private void LogException(IRequestContext requestContext, T request, Exception ex) { // since AppHost.CreateServiceRunner can be called before AppHost.Configure // don't get the logger in the constructor, only make it when it is needed var logger = MakeLogger(); var requestType = typeof(T); var message = ssortingng.Format("Exception at URI:'{0}' on service {1} : {2}", requestContext.AbsoluteUri, requestType.Name, request.ToJson()); logger.Error(message, ex); } private static ILog MakeLogger() { return LogManager.GetLogger(typeof(AppServiceRunner )); } }
Maintenant, les seules erreurs de service que je reçois sont celles générées par ce code.