C# 异常处理:如果控制器方法返回json,则返回json;如果视图,则返回重定向

C# 异常处理:如果控制器方法返回json,则返回json;如果视图,则返回重定向,c#,asp.net-core,.net-core,C#,Asp.net Core,.net Core,我想实现这样的目标: 若在返回Json的方法中抛出异常,则返回newJSON(new{success=false,error=“unknown”}) 但如果方法返回视图,则返回重定向 public async Task Invoke(HttpContext ctx) { try { await next(ctx); } catch (Exception ex) { HandleException(ctx, ex);

我想实现这样的目标:

若在返回Json的方法中抛出异常,则返回
newJSON(new{success=false,error=“unknown”})

但如果方法返回
视图
,则返回
重定向

public async Task Invoke(HttpContext ctx)
{
    try
    {
        await next(ctx);
    }
    catch (Exception ex)
    {
        HandleException(ctx, ex);
    }
}

private static void HandleException(HttpContext context, Exception ex)
{
    // some logger
    LoggerService.Log(ex);

    context.Response.Redirect("/Error/ErrorPage");
}
如何确定发送请求的位置?我的意思是如何获取请求发送到的方法类型


因为我想做一些类似于
typeof(targetMethod)
的事情来确定它是否是,例如
JsonResult

您需要在这里进行一些思考:

string methodName = ControllerContext.RouteData.Values["action"].ToString();
Assembly asm = Assembly.GetExecutingAssembly();

var methodInfo = asm.GetTypes()
    .Where(type => typeof(Controller).IsAssignableFrom(type)) //filter controllers
    .SelectMany(type => type.GetMethods())
    .Where(method => method.IsPublic)
    .Where(x => x.DeclaringType != null)
    .Where(x => x.Name == methodName)
    .SingleOrDefault();

if (methodInfo == null)
{
    return null; // Method wasn't found
}

if (typeof(JsonResult) == methodInfo.ReturnType)
{
    // Return JSON
}
else if (typeof(JsonResult) == methodInfo.ReturnType)
{
    // Redirect
}
else
{
    // Exception handling
}

听起来您正试图处理Action方法引发的异常。如果是这种情况,ASP.NET Core有一个内置的,适用于:

在操作引发异常后运行的筛选器

要实现您的目标,请创建一个
CustomExceptionFilter

public class CustomExceptionFilter : IExceptionFilter
{
    private ILogger<CustomExceptionFilter> _logger;

    public CustomExceptionFilter(ILogger<CustomExceptionFilter> logger)
    {
        this._logger = logger;
    }

    public void OnException(ExceptionContext context)
    {
        var ex = context.Exception;
        var c = (ControllerActionDescriptor) context.ActionDescriptor;

        if(c == null){
            context.Result = new StatusCodeResult(500);
        } else if (typeof(JsonResult) == c.MethodInfo.ReturnType) {
            context.Result = new JsonResult(new { success = false, error = "unknown" });
        } else {
            // Redirect
            this._logger.LogCritical(ex,ex.Message);
            context.Result = new RedirectResult("/Error/ErrorPage");
        }
    }
}

这对我来说很好。

你不能抛出例如JsonException或ViewException,然后执行正确的操作吗?@PatiK我想全局执行:P@Joelty我猜;)我的意思是,您可以将其添加到基本代码中(例如,类似于日志记录)。如何在中间件中访问
ControllerContext
?我注射了,但几乎所有的东西都是空的我很糟糕,你不能。尝试,您需要将
HttpContext.Current
替换为
context
services.AddMvc(opts => {
    opts.Filters.Add(typeof(CustomExceptionFilter));
});