如何在ASP.NET Core中针对API调用和MVC(视图)调用以不同方式处理错误(或区分) [英] How to handle errors differently for (or distinguish between) API calls and MVC (views) calls in ASP.NET Core

查看:482
本文介绍了如何在ASP.NET Core中针对API调用和MVC(视图)调用以不同方式处理错误(或区分)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在基于普通MVC和WebApi的应用程序中,我有两种不同的错误处理途径.

如果在WebApi调用期间发生错误,我将拦截它(使用标准的Web api选项),并返回带有相应HTTP状态代码的json消息,以便客户端应用程序可以处理它.

如果错误发生在MVC中,那么我将使用一些标准处理程序,这些处理程序可能会根据状态代码将用户重定向到某些默认错误屏幕.

现在,ASP.NET Core中的两个都加入了相同的框架,因此,如果我只是截取并返回JSON,则冒着向用户显示JSON的风险,因为它可以是返回视图的操作.另一方面,如果我使用app.UseExceptionHandler,那么我的API调用将从错误页面中获取HTML,而该错误页面在js中无法使用.

为这两种情况提供单独的错误处理的好方法是什么?还是有一种更好的方法来处理它?<​​/p>

P.S.我宁愿重用开箱即用的MVC异常处理程序,而仅添加Web api部分.

解决方案

有很多方法可以实现目标:

1-使用两个不同的异常过滤器(我会采用这种方法,因为您的问题与mvc pipline有关)

实施:

// For api
public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        // send error as json
    }
}


[ApiExceptionFilter]
public class ApiController : Controller{...}

// For mvc
public class MvcExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        // send view result
    }
}


[MvcExceptionFilter]
public class HomeController : Controller{...}

如果要全局添加过滤器,请参见为某个区域注册过滤器

2-使用UseWhenUseExceptionHandler

         app.UseWhen(x => x.Request.Path.Value.StartsWith("/api"), builder =>
         {
             builder.UseExceptionHandler(new ExceptionHandlerOptions()
             {
                 ExceptionHandler = async (ctx) =>
                 {
                     var feature = ctx.Features.Get<IExceptionHandlerFeature>();
                     var error = feature?.Error;
                     // send json
                 }
             });
         });
        app.UseWhen(x => !x.Request.Path.Value.StartsWith("/api"), builder =>
        {
            builder.UseExceptionHandler("/Error");
        });`

3-有条件地使用UseExceptionHandler:

        app.UseExceptionHandler(new ExceptionHandlerOptions()
        {
            ExceptionHandler = async (ctx) =>
            {
                if (ctx.Request.Path.Value.StartsWith("/api"))
                {
                    var feature = ctx.Features.Get<IExceptionHandlerFeature>();
                    var error = feature?.Error;
                    // send json
                }
                else
                {
                    // redirect error page
                }
            }
        });

In my applications based on ordinary MVC and WebApi I had two different error handling routes.

If an error occurred during WebApi call, I would intercept it (using standard web api options) and return json message with corresponding HTTP Status Code so that client app can handle it.

If the error happened in MVC, then I would use some standard handlers that would redirect user to some default error screen possibly based on status code.

Now in ASP.NET Core both are joined in the same framework, so if I just intercept and return JSON, then I risk showing json to a user, since it can be an action that returns a view. On the other hand if I use app.UseExceptionHandler then my API calls would get HTML from the error page that is unusable inside js.

What is the good way to provide separate error handling for this two cases? Or perhaps there is a better way to handle it altogether?

P.S. I would rather reuse the MVC exception handler that comes out of the box and only add the web api part.

解决方案

There are many ways to achive your goal:

1- Using two different exception filter(i would go with this approach because your question is about mvc pipline)

Implementation:

// For api
public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        // send error as json
    }
}


[ApiExceptionFilter]
public class ApiController : Controller{...}

// For mvc
public class MvcExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        // send view result
    }
}


[MvcExceptionFilter]
public class HomeController : Controller{...}

If you want to add filter globally, see Register filter for an area

2- Using UseWhen and UseExceptionHandler

         app.UseWhen(x => x.Request.Path.Value.StartsWith("/api"), builder =>
         {
             builder.UseExceptionHandler(new ExceptionHandlerOptions()
             {
                 ExceptionHandler = async (ctx) =>
                 {
                     var feature = ctx.Features.Get<IExceptionHandlerFeature>();
                     var error = feature?.Error;
                     // send json
                 }
             });
         });
        app.UseWhen(x => !x.Request.Path.Value.StartsWith("/api"), builder =>
        {
            builder.UseExceptionHandler("/Error");
        });`

3- Using UseExceptionHandler conditionally:

        app.UseExceptionHandler(new ExceptionHandlerOptions()
        {
            ExceptionHandler = async (ctx) =>
            {
                if (ctx.Request.Path.Value.StartsWith("/api"))
                {
                    var feature = ctx.Features.Get<IExceptionHandlerFeature>();
                    var error = feature?.Error;
                    // send json
                }
                else
                {
                    // redirect error page
                }
            }
        });

这篇关于如何在ASP.NET Core中针对API调用和MVC(视图)调用以不同方式处理错误(或区分)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆