ASP.NET Core Web API:捕获路由错误

3

我将尝试翻译一下关于ASP.NET Core Web API项目中捕获路由错误的相关内容。

具体来说,所谓路由错误是指例如:

在控制器中只有以下代码:

// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
    return "value";
}

但是一个请求是:

api/values/5/6

自动返回404错误,但我希望能够在代码中处理它(即调用某种异常处理例程)。
我尝试了三种不同的方法,但都没有成功:
在 ConfigureServices(IServiceCollection services)中,我添加了:
services.AddMvc(config =>
{
    config.Filters.Add(typeof(CustomExceptionFilter));
});

这会捕获控制器内发生的错误(例如,如果我在上面的 Get(id) 方法中放置 throw()),但不包括路由错误。我认为这是因为没有找到匹配的控制器方法,所以错误向上传递到中间件管道。为了进一步处理管道上游的错误,我尝试过...
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseExceptionHandler(
        options =>
        {
            options.Run(
            async context =>
            {
                var ex = context.Features.Get<IExceptionHandlerFeature>();
                // handle exception here
            });
        });

    app.UseApplicationInsightsRequestTelemetry();
    app.UseApplicationInsightsExceptionTelemetry();
    app.UseMvc();
}

我也尝试过以下方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.Use(async (ctx, next) =>
        {
            try
            {
                await next();
            }
            catch (Exception ex)
            {
                // handle exception here
            }
        });

    app.UseApplicationInsightsRequestTelemetry();
    app.UseApplicationInsightsExceptionTelemetry();
    app.UseMvc();
}

在路由错误发生时,似乎以上两种方法都没有被调用。我这样做错了吗?还是其中一种方法确实有效?

如果有任何建议,将不胜感激。

谢谢。

克里斯

PS. 我相对于ASP.NET Web API来说比较新,请原谅我可能使用了略微错误的术语。

1个回答

4
您可以使用UseStatusCodePages扩展方法:
 app.UseStatusCodePages(new StatusCodePagesOptions()
 {
     HandleAsync = (ctx) =>
     {
          if (ctx.HttpContext.Response.StatusCode == 404)
          {
               //handle
          }

          return Task.FromResult(0);
     }
 });

编辑

 app.UseExceptionHandler(options =>
 {
       options.Run( async context =>
       {
             var ex = context.Features.Get<IExceptionHandlerFeature>();
             // handle
             await Task.FromResult(0);
       });
 });
 app.UseStatusCodePages(new StatusCodePagesOptions()
 {
     HandleAsync = (ctx) =>
     {
          if (ctx.HttpContext.Response.StatusCode == 404)
          {
               // throw new YourException("<message>");
          }

          return Task.FromResult(0);
     }
 });

谢谢,但如果有可能我更倾向于捕获异常 - 这可行吗?这里的方法似乎更像是在事件发生后捕捉结果,而不是在问题发生时捕捉异常。 - cbailiss
为什么需要针对404结果的异常处理? - adem caglin
谢谢。关于app.UseExceptionHandler()方法,我尝试了这个方法(请参见原始问题),但它似乎没有被调用。路由错误会调用错误处理程序吗?(开始怀疑是否路由错误根本不会引起异常)。 - cbailiss
没有异常就不会被调用,因为404没有异常。要使用它,您应该手动抛出异常。请参见我的更新。 - adem caglin
非常感谢,那就是我一直苦恼的部分。我曾经认为路由错误(导致404)在请求处理过程中会产生异常。所以,基本上我试图捕获一个从未存在的异常。再次感谢。 - cbailiss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接