ExceptionHandling:如果控制器方法返回json,则返回json,如果View,则返回Redirect

时间:2019-04-30 07:43:54

标签: c# asp.net-core .net-core

我想要实现以下目标:

如果在返回Json的方法中引发了异常,则返回new Json(new { success = false, error = "unknown" });

但是如果方法返回View,则返回Redirect

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

2 个答案:

答案 0 :(得分:3)

听起来像您正在尝试处理Action方法引发的异常。在这种情况下,ASP.NET Core具有内置的IExceptionFilter,适用于此:

  

在动作引发异常之后运行的过滤器。

要实现您的目标,请创建一个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");
        }
    }
}

并按如下所示注册此过滤器:

services.AddMvc(opts => {
    opts.Filters.Add(typeof(CustomExceptionFilter));
});

对我来说很好。

答案 1 :(得分:1)

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

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
}