Ejemplo n.º 1
0
        public static void UseErikTheCoderExceptionHandling(this IApplicationBuilder ApplicationBuilder, Action <ExceptionHandlingOptions> ConfigureOptions = null)
        {
            var options = new ExceptionHandlingOptions();

            ConfigureOptions?.Invoke(options);
            ExceptionHandlingMiddleware.Enable(ApplicationBuilder, options);
        }
        /// <summary>
        /// Handles exceptions based upon the indicated behavior and rethrows the Exception
        /// </summary>
        /// <param name="exception"></param>
        /// <param name="exceptionBehavior"></param>
        /// <param name="log"></param>
        /// <param name="msg"></param>
        /// <param name="parameters"></param>
        public static void Handle(this Exception exception, ExceptionHandlingOptions exceptionBehavior, ILogWrapper log = null,
                                  string msg = "", params object[] parameters)
        {
            var caller = GetCaller();

            if (exceptionBehavior == ExceptionHandlingOptions.RecordOnly || exceptionBehavior == ExceptionHandlingOptions.RecordAndThrow)
            {
                ILogWrapper logger = log ?? new LogWrapper(LogManager.GetLogger(caller), LogLevel.Error);

                if (string.IsNullOrEmpty(msg))
                {
                    logger.Error(exception);
                }
                else
                {
                    logger.Error(String.Format(msg, parameters), exception);
                }
            }

            if (exceptionBehavior == ExceptionHandlingOptions.RecordAndThrow ||
                exceptionBehavior == ExceptionHandlingOptions.ThrowOnly)
            {
                throw exception;
            }
        }
Ejemplo n.º 3
0
 public static void Enable(IApplicationBuilder ApplicationBuilder, ExceptionHandlingOptions Options)
 {
     ApplicationBuilder.UseExceptionHandler(AlternatePipeline =>
     {
         // Run terminates the middleware pipeline.
         AlternatePipeline.Run(async Context =>
         {
             var logger = ApplicationBuilder.ApplicationServices.GetRequiredService <ILogger>();
             try
             {
                 await HandleException(Context, Options, logger);
             }
             catch (Exception exception)
             {
                 logger?.Log(Context.GetCorrelationId(), $"Exception occurred in {nameof(ExceptionHandlingMiddleware)}.  {exception.GetSummary(true, true)}");
                 throw;
             }
         });
     });
 }
Ejemplo n.º 4
0
        public void HandleTest(ExceptionHandlingOptions options, string msg, bool throwLoggingException)
        {
            var logger = A.Fake <ILogWrapper>();

            if (throwLoggingException)
            {
                A.CallTo(() => logger.Error(A <object> .Ignored, A <Exception> .Ignored))
                .Throws(new InvalidOperationException("Unit test should not get an exception of this type"));
            }
            else
            {
                A.CallTo(() => logger.Error(A <object> .Ignored, A <Exception> .Ignored));
            }

            try
            {
                throw new Exception(msg);
            }
            catch (Exception ex)
            {
                ex.Handle(options, logger, msg);
            }
        }
        /// <summary>
        /// Handles exceptions based upon the indicated behavior and throws a new exception of the given
        /// type, assigning the original exception as the InnerException
        /// </summary>
        public static void Handle <T>(this Exception exception, ExceptionHandlingOptions exceptionBehavior, ILogWrapper log = null,
                                      string msg = "", params object[] parameters) where T : Exception
        {
            var caller = GetCaller();

            if (exceptionBehavior == ExceptionHandlingOptions.RecordOnly || exceptionBehavior == ExceptionHandlingOptions.RecordAndThrow)
            {
                ILogWrapper logger = log ?? new LogWrapper(LogManager.GetLogger(caller), LogLevel.Error);

                if (string.IsNullOrEmpty(msg))
                {
                    logger.Error(exception);
                }
                else
                {
                    logger.Error(String.Format(msg, parameters), exception);
                }
            }

            if (exceptionBehavior == ExceptionHandlingOptions.RecordAndThrow || exceptionBehavior == ExceptionHandlingOptions.ThrowOnly)
            {
                throw (T)Activator.CreateInstance(typeof(T), string.Format("Exception occurred in {0}", caller), exception);
            }
        }
    protected virtual RemoteServiceErrorInfo CreateErrorInfoWithoutCode(Exception exception, ExceptionHandlingOptions options)
    {
        if (options.SendExceptionsDetailsToClients)
        {
            return(CreateDetailedErrorInfoFromException(exception, options.SendStackTraceToClients));
        }

        exception = TryToGetActualException(exception);

        if (exception is RemoteCallException remoteCallException && remoteCallException.Error != null)
        {
            return(remoteCallException.Error);
        }

        if (exception is DbConcurrencyException)
        {
            return(new RemoteServiceErrorInfo(L["DbConcurrencyErrorMessage"]));
        }

        if (exception is EntityNotFoundException)
        {
            return(CreateEntityNotFoundError(exception as EntityNotFoundException));
        }

        var errorInfo = new RemoteServiceErrorInfo();

        if (exception is UserFriendlyException || exception is RemoteCallException)
        {
            errorInfo.Message = exception.Message;
            errorInfo.Details = (exception as IHasErrorDetails)?.Details;
        }

        if (exception is IHasValidationErrors)
        {
            if (errorInfo.Message.IsNullOrEmpty())
            {
                errorInfo.Message = L["ValidationErrorMessage"];
            }

            if (errorInfo.Details.IsNullOrEmpty())
            {
                errorInfo.Details = GetValidationErrorNarrative(exception as IHasValidationErrors);
            }

            errorInfo.ValidationErrors = GetValidationErrorInfos(exception as IHasValidationErrors);
        }

        TryToLocalizeExceptionMessage(exception, errorInfo);

        if (errorInfo.Message.IsNullOrEmpty())
        {
            errorInfo.Message = L["InternalServerErrorMessage"];
        }

        errorInfo.Data = exception.Data;

        return(errorInfo);
    }
Ejemplo n.º 7
0
        public async Task Index_Test()
        {
            using (var loggerFactory = new NullLoggerFactory())
            {
                var exceptionHandlingOptions = new ExceptionHandlingOptions();
                var errorController          = await this.CreateErrorControllerAsync(exceptionHandlingOptions, loggerFactory);

                var actionResult = await errorController.Index();

                var objectResult   = (ObjectResult)actionResult;
                var problemDetails = (ProblemDetails)objectResult.Value;
                Assert.IsNotNull(problemDetails);
                Assert.IsNull(problemDetails.Detail);
                Assert.AreEqual("Error", problemDetails.Title);

                exceptionHandlingOptions = new ExceptionHandlingOptions {
                    Detailed = true
                };
                errorController = await this.CreateErrorControllerAsync(exceptionHandlingOptions, loggerFactory);

                actionResult = await errorController.Index();

                objectResult   = (ObjectResult)actionResult;
                problemDetails = (ProblemDetails)objectResult.Value;
                Assert.IsNotNull(problemDetails);
                Assert.IsNull(problemDetails.Detail);
                Assert.AreEqual("Error", problemDetails.Title);

                exceptionHandlingOptions = new ExceptionHandlingOptions();
                errorController          = await this.CreateErrorControllerAsync(exceptionHandlingOptions, loggerFactory, new InvalidOperationException("Test-exception"));

                actionResult = await errorController.Index();

                objectResult   = (ObjectResult)actionResult;
                problemDetails = (ProblemDetails)objectResult.Value;
                Assert.IsNotNull(problemDetails);
                Assert.IsNull(problemDetails.Detail);
                Assert.AreEqual("Error", problemDetails.Title);

                exceptionHandlingOptions = new ExceptionHandlingOptions {
                    Detailed = true
                };
                errorController = await this.CreateErrorControllerAsync(exceptionHandlingOptions, loggerFactory, new InvalidOperationException("Test-exception"));

                actionResult = await errorController.Index();

                objectResult   = (ObjectResult)actionResult;
                problemDetails = (ProblemDetails)objectResult.Value;
                Assert.IsNotNull(problemDetails);
                Assert.AreEqual("System.InvalidOperationException: Test-exception", problemDetails.Detail);
                Assert.AreEqual("Error", problemDetails.Title);

                exceptionHandlingOptions = new ExceptionHandlingOptions();
                errorController          = await this.CreateErrorControllerAsync(exceptionHandlingOptions, loggerFactory, new ServiceException("Test-exception"));

                actionResult = await errorController.Index();

                objectResult   = (ObjectResult)actionResult;
                problemDetails = (ProblemDetails)objectResult.Value;
                Assert.IsNotNull(problemDetails);
                Assert.IsNull(problemDetails.Detail);
                Assert.AreEqual("Test-exception", problemDetails.Title);

                exceptionHandlingOptions = new ExceptionHandlingOptions {
                    Detailed = true
                };
                errorController = await this.CreateErrorControllerAsync(exceptionHandlingOptions, loggerFactory, new ServiceException("Test-exception"));

                actionResult = await errorController.Index();

                objectResult   = (ObjectResult)actionResult;
                problemDetails = (ProblemDetails)objectResult.Value;
                Assert.IsNotNull(problemDetails);
                Assert.AreEqual("HansKindberg.RoleService.Models.ServiceException: Test-exception", problemDetails.Detail);
                Assert.AreEqual("Test-exception", problemDetails.Title);
            }
        }
Ejemplo n.º 8
0
        protected internal virtual async Task <IOptionsMonitor <ExceptionHandlingOptions> > CreateExceptionHandlingOptionsMonitorAsync(ExceptionHandlingOptions exceptionHandlingOptions)
        {
            var exceptionHandlingOptionsMonitorMock = new Mock <IOptionsMonitor <ExceptionHandlingOptions> >();

            exceptionHandlingOptionsMonitorMock.Setup(exceptionHandlingOptionsMonitor => exceptionHandlingOptionsMonitor.CurrentValue).Returns(exceptionHandlingOptions);

            return(await Task.FromResult(exceptionHandlingOptionsMonitorMock.Object));
        }
Ejemplo n.º 9
0
 protected internal virtual async Task <ErrorController> CreateErrorControllerAsync(ExceptionHandlingOptions exceptionHandlingOptions, ILoggerFactory loggerFactory, Exception exception = null)
 {
     return(await this.CreateErrorControllerAsync(exceptionHandlingOptions, await this.CreateExceptionHandlerFeatureAsync(exception), loggerFactory));
 }
Ejemplo n.º 10
0
        protected internal virtual async Task <ErrorController> CreateErrorControllerAsync(ExceptionHandlingOptions exceptionHandlingOptions, IExceptionHandlerFeature exceptionHandlerFeature, ILoggerFactory loggerFactory)
        {
            var features = new FeatureCollection();

            features.Set(exceptionHandlerFeature);

            return(await this.CreateErrorControllerAsync(exceptionHandlingOptions, new DefaultHttpContext(features), loggerFactory));
        }
Ejemplo n.º 11
0
        protected internal virtual async Task <ErrorController> CreateErrorControllerAsync(ExceptionHandlingOptions exceptionHandlingOptions, HttpContext httpContext, ILoggerFactory loggerFactory)
        {
            var exceptionHandlingOptionsMonitorMock = new Mock <IOptionsMonitor <ExceptionHandlingOptions> >();

            exceptionHandlingOptionsMonitorMock.Setup(exceptionHandlingOptionsMonitor => exceptionHandlingOptionsMonitor.CurrentValue).Returns(exceptionHandlingOptions);

            var errorController = new ErrorController(loggerFactory, await this.CreateExceptionHandlingOptionsMonitorAsync(exceptionHandlingOptions))
            {
                ControllerContext = new ControllerContext()
                {
                    HttpContext = httpContext
                }
            };

            return(await Task.FromResult(errorController));
        }
Ejemplo n.º 12
0
        private static async Task HandleException(HttpContext Context, ExceptionHandlingOptions Options, ILogger Logger)
        {
            if (Options.ResponseHandler != null)
            {
                if (Options.ExceptionResponseFormat.HasValue || Options.IncludeDetails)
                {
                    throw new ArgumentException($"If setting an {nameof(Options.ResponseHandler)}, do not set an {nameof(Options.ExceptionResponseFormat)} or set {nameof(Options.IncludeDetails)} to true.");
                }
            }
            // Get correlation ID.
            var correlationId = Context.GetCorrelationId();
            // Get exception.
            var             exceptionHandlerFeature = Context.Features.Get <IExceptionHandlerFeature>();
            SimpleException innerException;

            if (exceptionHandlerFeature.Error is ApiException apiException)
            {
                // Exception occurred when a Refit proxy called a service method.
                // Deserialize exception from JSON response.
                try
                {
                    var refitException = await apiException.GetContentAsAsync <SimpleException>() ?? new SimpleException(apiException, correlationId, Options.AppName, Options.ProcessName);

                    innerException = new SimpleException(refitException, correlationId, Options.AppName, Options.ProcessName,
                                                         "An exception occurred when a Refit proxy called a service method.");
                }
                catch
                {
                    // Ignore exception when deserializing JSON response.
                    innerException = new SimpleException(apiException, correlationId, Options.AppName, Options.ProcessName);
                    innerException = new SimpleException(innerException, correlationId, Options.AppName, Options.ProcessName,
                                                         $"Failed to deserialize exception from service method response.  Ensure the service's {nameof(ExceptionHandlingMiddleware)} is configured to use {nameof(ExceptionResponseFormat)}.{nameof(ExceptionResponseFormat.Json)}.");
                }
            }
            else
            {
                innerException = new SimpleException(exceptionHandlerFeature.Error, correlationId, Options.AppName, Options.ProcessName);
            }
            // Log exception.
            var exception = new SimpleException(innerException, correlationId, Options.AppName, Options.ProcessName,
                                                $"{Context.Request.Method} with {Context.Request.ContentType ?? "unknown"} content type to {Context.Request.Path} resulted in HTTP status code {Context.Response.StatusCode}.");

            Logger.Log(correlationId, exception);
            Logger.LogMetric(correlationId, Context.Request.Path, "Critical Error", 1);
            // Respond to caller.
            if (Options.ResponseHandler != null)
            {
                // Respond with customer handler.
                Options.ResponseHandler(Context, exception);
                return;
            }
            // Respond with HTML or JSON.
            // ReSharper disable once SwitchStatementMissingSomeCases
            switch (Options.ExceptionResponseFormat)
            {
            case ExceptionResponseFormat.Html:
                await RespondWithHtml(Context, exception, Options.IncludeDetails);

                break;

            case ExceptionResponseFormat.Json:
                await RespondWithJson(Context, exception, Options.IncludeDetails);

                break;

            default:
                throw new Exception($"{nameof(ExceptionResponseFormat)} {Options.ExceptionResponseFormat} not supported.");
            }
        }
Ejemplo n.º 13
0
        public static void Enable(IApplicationBuilder ApplicationBuilder, ExceptionHandlingOptions Options)
        {
            if (Options.ResponseHandler != null)
            {
                if (Options.ExceptionResponseFormat.HasValue || Options.IncludeDetails)
                {
                    throw new ArgumentException($"If setting an {nameof(Options.ResponseHandler)}, do not set an {nameof(Options.ExceptionResponseFormat)} or set {nameof(Options.IncludeDetails)} to true.");
                }
            }
            ApplicationBuilder.UseExceptionHandler(AlternatePipeline =>
            {
                // Run terminates the middleware pipeline.
                AlternatePipeline.Run(async HttpContext =>
                {
                    // Get correlation ID.
                    Guid correlationId = HttpContext.GetCorrelationId();
                    // Get exception.
                    IExceptionHandlerFeature exceptionHandlerFeature = HttpContext.Features.Get <IExceptionHandlerFeature>();
                    SimpleException innerException;
                    if (exceptionHandlerFeature.Error is ApiException apiException)
                    {
                        // Exception occurred when a Refit proxy called a service method.
                        // Deserialize exception from JSON response.
                        try
                        {
                            SimpleException refitException = apiException.GetContentAs <SimpleException>() ?? new SimpleException(apiException, correlationId, Options.AppName, Options.ProcessName);
                            innerException = new SimpleException(refitException, correlationId, Options.AppName, Options.ProcessName,
                                                                 "An exception occurred when a Refit proxy called a service method.");
                        }
                        catch
                        {
                            // Ignore exception when deserializing JSON response.
                            innerException = new SimpleException(apiException, correlationId, Options.AppName, Options.ProcessName);
                            innerException = new SimpleException(innerException, correlationId, Options.AppName, Options.ProcessName,
                                                                 $"Failed to deserialize exception from service method response.  Ensure the service's {nameof(ExceptionHandlingMiddleware)} is configured to use {nameof(ExceptionResponseFormat)}.{nameof(ExceptionResponseFormat.Json)}.");
                        }
                    }
                    else
                    {
                        innerException = new SimpleException(exceptionHandlerFeature.Error, correlationId, Options.AppName, Options.ProcessName);
                    }
                    // Log exception.
                    SimpleException exception = new SimpleException(innerException, correlationId, Options.AppName, Options.ProcessName,
                                                                    $"{HttpContext.Request.Method} with {HttpContext.Request.ContentType ?? "unknown"} content type to {HttpContext.Request.Path} resulted in HTTP status code {HttpContext.Response.StatusCode}.");
                    ILogger logger = ApplicationBuilder.ApplicationServices.GetRequiredService <ILogger>();
                    logger.Log(correlationId, exception);
                    logger.LogMetric(correlationId, HttpContext.Request.Path, "Critical Error", 1);
                    // Respond to caller.
                    if (Options.ResponseHandler != null)
                    {
                        // Respond with customer handler.
                        Options.ResponseHandler(HttpContext, exception);
                        return;
                    }
                    // Respond with HTML or JSON.
                    // ReSharper disable once SwitchStatementMissingSomeCases
                    switch (Options.ExceptionResponseFormat)
                    {
                    case ExceptionResponseFormat.Html:
                        await RespondWithHtml(HttpContext, exception, Options.IncludeDetails);
                        break;

                    case ExceptionResponseFormat.Json:
                        await RespondWithJson(HttpContext, exception, Options.IncludeDetails);
                        break;

                    default:
                        throw new Exception($"{nameof(ExceptionResponseFormat)} {Options.ExceptionResponseFormat} not supported.");
                    }
                });
            });
        }