|
|
|
@ -0,0 +1,112 @@
|
|
|
|
|
using System;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc.Abstractions;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc.Filters;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
|
|
|
using Volo.Abp.AspNetCore.ExceptionHandling;
|
|
|
|
|
using Volo.Abp.DependencyInjection;
|
|
|
|
|
using Volo.Abp.ExceptionHandling;
|
|
|
|
|
using Volo.Abp.Http;
|
|
|
|
|
using Volo.Abp.Json;
|
|
|
|
|
|
|
|
|
|
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
|
|
|
|
|
{
|
|
|
|
|
public class AbpExceptionPageFilter : IAsyncPageFilter, ITransientDependency
|
|
|
|
|
{
|
|
|
|
|
public ILogger<AbpExceptionPageFilter> Logger { get; set; }
|
|
|
|
|
|
|
|
|
|
private readonly IExceptionToErrorInfoConverter _errorInfoConverter;
|
|
|
|
|
private readonly IHttpExceptionStatusCodeFinder _statusCodeFinder;
|
|
|
|
|
private readonly IJsonSerializer _jsonSerializer;
|
|
|
|
|
|
|
|
|
|
public AbpExceptionPageFilter(
|
|
|
|
|
IExceptionToErrorInfoConverter errorInfoConverter,
|
|
|
|
|
IHttpExceptionStatusCodeFinder statusCodeFinder,
|
|
|
|
|
IJsonSerializer jsonSerializer)
|
|
|
|
|
{
|
|
|
|
|
_errorInfoConverter = errorInfoConverter;
|
|
|
|
|
_statusCodeFinder = statusCodeFinder;
|
|
|
|
|
_jsonSerializer = jsonSerializer;
|
|
|
|
|
|
|
|
|
|
Logger = NullLogger<AbpExceptionPageFilter>.Instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
|
|
|
|
|
{
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
|
|
|
|
|
{
|
|
|
|
|
if (context.HandlerMethod == null || !ShouldHandleException(context))
|
|
|
|
|
{
|
|
|
|
|
await next();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var pageHandlerExecutedContext = await next();
|
|
|
|
|
if (pageHandlerExecutedContext.Exception == null)
|
|
|
|
|
{
|
|
|
|
|
return;;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await HandleAndWrapException(pageHandlerExecutedContext);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual bool ShouldHandleException(PageHandlerExecutingContext context)
|
|
|
|
|
{
|
|
|
|
|
//TODO: Create DontWrap attribute to control wrapping..?
|
|
|
|
|
|
|
|
|
|
if (context.ActionDescriptor.IsPageAction() &&
|
|
|
|
|
context.ActionDescriptor.HasObjectResult())
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context.HttpContext.Request.CanAccept(MimeTypes.Application.Json))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context.HttpContext.Request.IsAjax())
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual async Task HandleAndWrapException(PageHandlerExecutedContext context)
|
|
|
|
|
{
|
|
|
|
|
//TODO: Trigger an AbpExceptionHandled event or something like that.
|
|
|
|
|
|
|
|
|
|
context.HttpContext.Response.Headers.Add(AbpHttpConsts.AbpErrorFormat, "true");
|
|
|
|
|
context.HttpContext.Response.StatusCode = (int)_statusCodeFinder.GetStatusCode(context.HttpContext, context.Exception);
|
|
|
|
|
|
|
|
|
|
var remoteServiceErrorInfo = _errorInfoConverter.Convert(context.Exception);
|
|
|
|
|
|
|
|
|
|
context.Result = new ObjectResult(new RemoteServiceErrorResponse(remoteServiceErrorInfo));
|
|
|
|
|
|
|
|
|
|
var logLevel = context.Exception.GetLogLevel();
|
|
|
|
|
|
|
|
|
|
Logger.LogWithLevel(logLevel, $"---------- {nameof(RemoteServiceErrorInfo)} ----------");
|
|
|
|
|
Logger.LogWithLevel(logLevel, _jsonSerializer.Serialize(remoteServiceErrorInfo, indented: true));
|
|
|
|
|
Logger.LogException(context.Exception, logLevel);
|
|
|
|
|
|
|
|
|
|
await context.HttpContext
|
|
|
|
|
.RequestServices
|
|
|
|
|
.GetRequiredService<IExceptionNotifier>()
|
|
|
|
|
.NotifyAsync(
|
|
|
|
|
new ExceptionNotificationContext(context.Exception)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
context.Exception = null; //Handled!
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|