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