mirror of https://github.com/abpframework/abp.git
12 changed files with 207 additions and 39 deletions
@ -0,0 +1,7 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc |
|||
{ |
|||
public class AbpActionInfoInHttpContext |
|||
{ |
|||
public bool IsObjectResult { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,92 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Primitives; |
|||
using Microsoft.Net.Http.Headers; |
|||
using Volo.Abp.AspNetCore.Mvc.Uow; |
|||
using Volo.Abp.Http; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling |
|||
{ |
|||
public class AbpExceptionHandlingMiddleware |
|||
{ |
|||
private readonly RequestDelegate _next; |
|||
private readonly ILogger<AbpUnitOfWorkMiddleware> _logger; |
|||
|
|||
private readonly Func<object, Task> _clearCacheHeadersDelegate; |
|||
|
|||
public AbpExceptionHandlingMiddleware(RequestDelegate next, ILogger<AbpUnitOfWorkMiddleware> logger) |
|||
{ |
|||
_next = next; |
|||
_logger = logger; |
|||
|
|||
_clearCacheHeadersDelegate = ClearCacheHeaders; |
|||
} |
|||
|
|||
public async Task Invoke(HttpContext httpContext) |
|||
{ |
|||
try |
|||
{ |
|||
await _next(httpContext); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
// We can't do anything if the response has already started, just abort.
|
|||
if (httpContext.Response.HasStarted) |
|||
{ |
|||
_logger.LogWarning("An exception occured, but response has already started!"); |
|||
throw; |
|||
} |
|||
|
|||
if (httpContext.Items["_AbpActionInfo"] is AbpActionInfoInHttpContext actionInfo) |
|||
{ |
|||
if (actionInfo.IsObjectResult) |
|||
{ |
|||
await HandleAndWrapException(httpContext, ex); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
throw; |
|||
} |
|||
} |
|||
|
|||
private async Task HandleAndWrapException(HttpContext httpContext, Exception exception) |
|||
{ |
|||
_logger.LogException(exception); |
|||
|
|||
var errorInfoConverter = httpContext.RequestServices.GetRequiredService<IExceptionToErrorInfoConverter>(); |
|||
var statusCodeFinder = httpContext.RequestServices.GetRequiredService<HttpExceptionStatusCodeFinder>(); |
|||
var jsonSerializer = httpContext.RequestServices.GetRequiredService<IJsonSerializer>(); |
|||
|
|||
httpContext.Response.Clear(); |
|||
httpContext.Response.StatusCode = statusCodeFinder.GetStatusCode(httpContext, exception); |
|||
httpContext.Response.OnStarting(_clearCacheHeadersDelegate, httpContext.Response); |
|||
httpContext.Response.Headers.Add(new KeyValuePair<string, StringValues>("_AbpErrorFormat", "true")); //TODO: Constant
|
|||
|
|||
await httpContext.Response.WriteAsync( |
|||
jsonSerializer.Serialize( |
|||
new RemoteServiceErrorResponse( |
|||
errorInfoConverter.Convert(exception) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
private Task ClearCacheHeaders(object state) |
|||
{ |
|||
var response = (HttpResponse)state; |
|||
|
|||
response.Headers[HeaderNames.CacheControl] = "no-cache"; |
|||
response.Headers[HeaderNames.Pragma] = "no-cache"; |
|||
response.Headers[HeaderNames.Expires] = "-1"; |
|||
response.Headers.Remove(HeaderNames.ETag); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using System; |
|||
using System.Net; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Volo.Abp.Authorization; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Domain.Entities; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling |
|||
{ |
|||
public class HttpExceptionStatusCodeFinder : ITransientDependency |
|||
{ |
|||
public virtual int GetStatusCode(HttpContext httpContext, Exception exception) |
|||
{ |
|||
if (exception is AbpAuthorizationException) |
|||
{ |
|||
return httpContext.User.Identity.IsAuthenticated |
|||
? (int)HttpStatusCode.Forbidden |
|||
: (int)HttpStatusCode.Unauthorized; |
|||
} |
|||
|
|||
if (exception is AbpValidationException) |
|||
{ |
|||
return (int)HttpStatusCode.BadRequest; |
|||
} |
|||
|
|||
if (exception is EntityNotFoundException) |
|||
{ |
|||
return (int)HttpStatusCode.NotFound; |
|||
} |
|||
|
|||
return (int)HttpStatusCode.InternalServerError; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
@using Volo.Abp.Ui |
|||
<h2>Exception test</h2> |
|||
@{ |
|||
throw new UserFriendlyException("test exception!"); |
|||
} |
|||
Loading…
Reference in new issue