在ASP.NET Core 2.2上运行的中间件中,是否有任何方式检测请求是否适用于apicontroller



i具有MVC和'new''ApicOntroller端点的应用程序中的ASP.NET Core 2.2共存。

在添加API端点之前,我一直使用使用app.UseExceptionHandler((x) => { ... }注册为中间件的全局异常处理程序,该处理程序将重定向到错误页面。

当然,这对API响应不起作用,我想以ProblemDetails格式的结果返回ObjectResult(协商)500结果。

问题是,如果我正在处理MVC或API请求,我不确定如何在" UseExceptionHandler" Lambda中可靠地确定。我可以使用某种请求URL匹配(例如/api/...前缀),但是我想要一个更强大的解决方案,将来不会再咬我。

我要实现的内容是:

app.UseExceptionHandler(x =>
{
    x.Run(async context =>
    {
        // extract the exception that was thrown
        var ex = context.Features.Get<IExceptionHandlerFeature>()?.Error;
        try
        {
            // generically handle the exception regardless of what our response needs to look like by logging it
            // NOTE: ExceptionHandlerMiddleware itself will log the exception
            // TODO: need to find a way to see if we have run with negotiation turned on (in which case we are API not MVC!! see below extensions for clues?)
            // TODO: ... could just use "/api/" prefix but that seems rubbish
            if (true)
            {
                // return a 500 with object (in RFC 7807 form) negotiated to the right content type (eg. json)
            }
            else
            {
                // otherwise, we handle the response as a 500 error page redirect
            }
        }
        catch (Exception exofex)
        {
            // NOTE: absolutely terrible if we get into here
            log.Fatal($"Unhandled exception in global error handler!", exofex);
            log.Fatal($"Handling exception: ", ex);
        }
    });
});
}

有什么想法?

欢呼!

这可能与您的期望有所不同,但是您可以检查请求是否是AJAX请求。

您可以使用此扩展名:

public static class HttpRequestExtensions
{
    public static bool IsAjaxRequest(this HttpRequest request)
    {
        if (request == null)
            throw new ArgumentNullException(nameof(request));
        if (request.Headers == null)
            return false;
        return request.Headers["X-Requested-With"] == "XMLHttpRequest";
    }
}

,然后使用看起来像:

的调用方法
public async Task Invoke(HttpContext context)
{
    if (context.Request.IsAjaxRequest())
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
             //Handle the exception
             await HandleExceptionAsync(context, ex);
        }
    }
    else
    {
        await _next(context);
    }
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
    //you can do more complex logic here, but a basic example would be:
    var result = JsonConvert.SerializeObject(new { error = "An unexpected error occurred." });
    context.Response.ContentType = "application/json";
    context.Response.StatusCode = 500;
    return context.Response.WriteAsync(result);
}

有关更详细的版本,请参阅此答案。

如果要检查是否将请求路由到ApiController,则可以尝试使用IExceptionFilter来hande hande hande异常。

public class CustomExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        if (IsApi(context))
        {
            HttpStatusCode status = HttpStatusCode.InternalServerError;
            var message = context.Result;
            //You can enable logging error
            context.ExceptionHandled = true;
            HttpResponse response = context.HttpContext.Response;
            response.StatusCode = (int)status;
            response.ContentType = "application/json";
            context.Result = new ObjectResult(new { ErrorMsg = message });
        }
        else
        {
        }
    }
    private bool IsApi(ExceptionContext context)
    {
        var controllerActionDesc = context.ActionDescriptor as ControllerActionDescriptor;
        var attribute = controllerActionDesc
                        .ControllerTypeInfo
                        .CustomAttributes
                        .FirstOrDefault(c => c.AttributeType == typeof(ApiControllerAttribute));
        return attribute == null ? false : true;
    }
}

感谢他人的所有建议,但是我已经意识到了更多的思想和想法,我的方法首先不正确 - 而且我应该处理大多数例外情况在控制器中并从那里做出响应。

我基本上保留了错误处理中间件的错误,就像它正在处理MVC未手动异常一样。客户将获得带有HTML响应的500,但到那时,客户都无法做到这一点,因此不会造成伤害。

感谢您的帮助!

最新更新