I have an Aspect class that uses the MethodInterception class. When I create a throw like below in this class, ExceptionMiddleware does not handle, why?
I am using Castle.DynamicProxy for MethodInterception. Since Castle.DynamicProxy has a working problem in async methods, I solved my problem by using the extension 'Castle.Core.AsyncInterceptor'. But now the problem is that the throw exception from an async interceptor is not handled by the exception middleware. If I don't define the onBefore method as async, the exception middleware works, but I run await method in onbefore, so it's necessary.
public class ExceptionMiddleware
{
private RequestDelegate _next;
public ExceptionMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext)
{
try
{
await _next(httpContext);
}
catch (Exception e)
{
await HandleExceptionAsync(httpContext, e);
}
}
private Task HandleExceptionAsync(HttpContext httpContext, Exception e)
{
httpContext.Response.ContentType = "application/json";
httpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
string message = "Internal Server Error";
if (e.GetType() == typeof(UnauthorizedAccessException))
{
message = e.Message;
httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
return httpContext.Response.WriteAsync(new ErrorDetails
{
StatusCode = httpContext.Response.StatusCode,
Message = message
}.ToString());
}
}
SecuredScopeAspect
public class SecuredOperation : MethodInterception
{
private string[] _roles;
private IHttpContextAccessor _httpcontextAccessor;
public SecuredOperation()
{
_httpcontextAccessor = ServiceTool.ServiceProvider.GetService<IHttpContextAccessor>();
}
public SecuredOperation(string roles)
{
_roles = roles.Split(',');
_httpcontextAccessor = ServiceTool.ServiceProvider.GetService<IHttpContextAccessor>();
}
protected override async void OnBefore(IInvocation invocation)
{
if (_httpcontextAccessor.HttpContext.User.Identity.IsAuthenticated)
{
if (_roles != null)
{
//some await proccess
const result = await _fga.check();
if(result != null) return;
throw new MemberAccessException(AuthMessages.AuthorizationForbidden);
}
return;
}
throw new UnauthorizedAccessException(AuthMessages.AuthorizationDenied);
}
}
MethodInterception.cs
public abstract class MethodInterception : MethodInterceptionBaseAttribute
{
protected virtual void OnBefore(IInvocation invocation)
{
}
protected virtual void OnAfter(IInvocation invocation)
{
}
protected virtual void OnException(IInvocation invocation, System.Exception e)
{
}
protected virtual void OnSuccess(IInvocation invocation)
{
}
public override void InterceptSynchronous(IInvocation invocation)
{
var isSuccess = true;
OnBefore(invocation);
try
{
invocation.Proceed();
}
catch (Exception e)
{
isSuccess = false;
OnException(invocation, e);
throw;
}
finally
{
if (isSuccess)
{
OnSuccess(invocation);
}
}
OnAfter(invocation);
}
public override void InterceptAsynchronous(IInvocation invocation)
{
invocation.ReturnValue = InternalInterceptAsynchronous(invocation);
}
protected async Task InternalInterceptAsynchronous(IInvocation invocation)
{
var isSuccess = true;
OnBefore(invocation);
try
{
invocation.Proceed();
var task = (Task)invocation.ReturnValue;
await task;
}
catch (Exception e)
{
isSuccess = false;
OnException(invocation, e);
throw;
}
finally
{
if (isSuccess)
{
OnSuccess(invocation);
}
}
OnAfter(invocation);
}
public override void InterceptAsynchronous<TResult>(IInvocation invocation)
{
invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation);
}
protected async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation)
{
TResult result;
var isSuccess = true;
OnBefore(invocation);
try
{
invocation.Proceed();
var task = (Task<TResult>)invocation.ReturnValue;
result = await task;
}
catch (Exception e)
{
isSuccess = false;
OnException(invocation, e);
throw;
}
finally
{
if (isSuccess)
{
OnSuccess(invocation);
}
}
OnAfter(invocation);
return result;
}
}
}