コード例 #1
0
 public static ApiBehaviorOptions UseFailureProblemDetailResponseFactory(this ApiBehaviorOptions options)
 {
     options.InvalidModelStateResponseFactory = context =>
     {
         var detail = FailureProblemDetail.FromHttpContext(context.HttpContext)
                      .WithFailures(context.ModelState.ToSerializable());
         return(new BadRequestObjectResult(detail));
     };
     return(options);
 }
コード例 #2
0
        public static IApplicationBuilder UseExceptionHandling(this IApplicationBuilder app,
                                                               Action <Exception, ExceptionHandlingContext> handle = null)
        {
            return(app.UseExceptionHandler(appException => appException.Run(async context =>
            {
                var feature = context.Features[typeof(IExceptionHandlerFeature)] as IExceptionHandlerFeature;
                var logger = app.ApplicationServices.GetRequiredService <ILoggerFactory>()
                             .CreateLogger("ExceptionHandling");
                var env = app.ApplicationServices.GetRequiredService <IHostEnvironment>();
                var options = app.ApplicationServices.GetRequiredService <IOptions <ExceptionOptions> >();

                // Should always exist, but best to be safe!
                if (feature?.Error == null)
                {
                    return;
                }

                var exception = feature.Error;
                var detail = FailureProblemDetail.FromHttpContext(context);

                context.Response.StatusCode = StatusCodes.Status500InternalServerError;
                context.Response.ContentType = "application/json";

                var handlingContext = new ExceptionHandlingContext();
                handle?.Invoke(exception, handlingContext);
                if (handlingContext.ExceptionHandled)
                {
                    detail.Message = handlingContext.FriendlyMessage;
                    context.Response.StatusCode = handlingContext.StatusCode;
                }
                else
                {
                    switch (exception)
                    {
                    case OperationCanceledException:
                        logger.LogInformation($"OperationCanceledException: {exception}");

                        detail.Message = "Request was cancelled";
                        context.Response.StatusCode = StatusCodes.Status400BadRequest;
                        break;

                    case ValidationException validationException:
                        logger.LogInformation($"ValidationException: {exception}");

                        detail.Message = validationException.Message;
                        if (validationException.Failures != null)
                        {
                            detail.WithFailures(validationException.Failures);
                        }
                        context.Response.StatusCode = StatusCodes.Status400BadRequest;
                        break;

                    case DbConcurrencyException:
                        logger.LogInformation($"DbConcurrencyException: {exception}");

                        detail.Message = options.Value.DbConcurrencyException;
                        context.Response.StatusCode = StatusCodes.Status400BadRequest;
                        break;

                    case DbException dbException
                        when options.Value.TryFindMapping(dbException, out var mapping):
                        {
                            logger.LogInformation($"DbException: {mapping.Message}");

                            if (string.IsNullOrEmpty(mapping.MemberName))
                            {
                                detail.Message = mapping.Message;
                            }
                            else
                            {
                                detail.WithFailures(new[]
                                                    { new ValidationFailure(mapping.MemberName, mapping.Message) });
                            }

                            context.Response.StatusCode = StatusCodes.Status400BadRequest;
                            break;
                        }

                    default:
                        {
                            logger.LogError(new EventId(exception.HResult), exception,
                                            $"InternalServerIssue: {exception.Message}");

                            detail.Message = exception is DbException
                                ? options.Value.DbException
                                : options.Value.InternalServerIssue;

                            if (env.IsDevelopment())
                            {
                                detail.DevelopmentMessage = exception.ToString();
                            }

                            context.Response.StatusCode = StatusCodes.Status500InternalServerError;
                            break;
                        }
                    }
                }

                var stream = context.Response.Body;
                await JsonSerializer.SerializeAsync(stream, detail);
            })));
        }