【问题标题】:asp.net core app.UseExceptionHandler() to handle exceptions for certain endpoints?asp.net core app.UseExceptionHandler() 来处理某些端点的异常?
【发布时间】:2021-09-16 05:48:28
【问题描述】:

我正在向现有的 ASP.NET Core Web 应用程序添加一些 Web API 方法。这意味着我的新 Web API 控制器将具有属性 [ApiController] 并且调用客户端将期望返回输出为 JSON 而不是常规 HTML。

在另一个项目中,我使用app.UseExceptionHandler(...) 实现了一个自定义异常处理程序,它将响应编码为 JSON,提供有关异常的信息。在这个中,我想这样做,但只有当异常来自[ApiController] 控制器内的操作方法时;否则我仍然想使用app.UseExceptionHandler("/Home/Error");,因为异常来自常规页面并且响应应该是 HTML。

有没有一种方法可以设置异常处理程序,以便它知道异常来自哪里,并相应地呈现响应?

【问题讨论】:

    标签: c# json asp.net-core exception asp.net-core-webapi


    【解决方案1】:

    在 ASP.Net Core 6 中,您可以从 IExceptionHandlerFeature 获取 Endpoint,在此之前,您可以在路由中间件之后自己捕获 Endpoint 并将其存储在一个特性中并在异常处理程序代码中使用它。

    app.UseExceptionHandler("/Error");
    app.UseRouting();
    app.Use(async (context, next) =>
    {
        var feature = new EndpointFeature
        {
            Endpoint = context.GetEndpoint()
        };
        context.Features.Set(feature);
        await next();
    });
    app.UseEndpoints(endpoints =>
    {
        endpoints.Map("/Error", context =>
        {
            var feature = context.Features.Get<EndpointFeature>();
            var endpointMetadata = feature.Endpoint.Metadata;
        });
    });
    

    【讨论】:

    【解决方案2】:

    请问您使用的是哪个版本的 ASP.Net Core? link 可能对您有所帮助。 ASP.Net Core Web Api 的异常处理中间件

    var exceptionHandlerPathFeature =
            HttpContext.Features.Get<IExceptionHandlerPathFeature>();
         var context = HttpContext.Features.Get<IExceptionHandlerFeature>();
         var detail = context.Error.StackTrace;
         var message = context.Error.Message;
            if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
            {
                ExceptionMessage = "File error thrown";
                _logger.LogError(ExceptionMessage);
            }
            if (exceptionHandlerPathFeature?.Path == "/index")
            {
                ExceptionMessage += " from home page";
            }
    

    【讨论】:

    • 该代码如何让我确定异常来自的控制器是否具有ApiController 属性?我正在使用 ASP.NET Core 3.1。
    • 虽然这段代码 sn-p 可以解决问题,including an explanation 确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
    • @Jez 您可以尝试使用 ExceptionHandlerFeature 吗,它会为您提供发生异常的控制器名称。我已经更新了代码。
    • @Priyanka 那应该如何给控制器名称?它只有Path 和Error。路径和控制器名称不是一回事,当路由改变时,控制器的路径可以改变。
    • @Jezz 你好,你能不能尝试使用 throw new ArgumentException( $"Exception throw from {variablename}.", nameof(variable));这是Link
    【解决方案3】:

    在这个,我想这样做,但只有当异常来自 [ApiController] 控制器内的操作方法;否则我 仍然想使用 app.UseExceptionHandler("/Home/Error");,作为 异常来自常规页面,响应应该是 HTML。

    根据您的描述,您似乎想检测异常来自哪里,如果异常来自 API 方法,您将使用自定义异常处理程序和自定义响应,否则将通过Home/Error 页面。

    在这种情况下,自定义异常处理程序页面的替代方法是向 UseExceptionHandler 提供 lambda。使用 lambda 允许在返回响应之前访问出错的请求的路径。

    例如:

    //app.UseExceptionHandler("/Home/Error");
    app.UseExceptionHandler(errorApp =>
    {
        errorApp.Run(async context =>
        { 
            var exceptionHandlerPathFeature =
                context.Features.Get<IExceptionHandlerPathFeature>();
            //check if the handler path contains api or not.
            if (exceptionHandlerPathFeature.Path.Contains("api"))
            { 
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; ;
                context.Response.ContentType = "text/html";
    
                await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
                await context.Response.WriteAsync("ERROR From API!<br><br>\r\n");
    
                await context.Response.WriteAsync(
                                                "<a href=\"/\">Home</a><br>\r\n");
                await context.Response.WriteAsync("</body></html>\r\n"); 
            }
            else
            {
                context.Response.Redirect("/Home/Error");
            }
        });
    });
    

    结果如下:

    更多详细信息,请参阅Exception handler lambda 和Asp .Net Core How to handle error pages in area。

    【讨论】:

    • 我已经考虑过了,如果可能的话我宁愿不依赖路径,因为路由很容易改变。我宁愿参考导致异常的实际类/方法。
    • “我宁愿参考导致异常的实际类/方法”,您可以尝试创建两个自定义异常类来抛出应用程序特定的异常,一个用于 API,一个用于MVC,然后,在 action 方法中使用 try-catch 语句并抛出自定义异常,然后在 Exception handler 方法中检查异常类型,然后根据结果更改响应。
    猜你喜欢
    • 1970-01-01
    • 2011-12-10
    • 2016-12-02
    • 2020-12-16
    • 1970-01-01
    • 2011-07-02
    • 2021-05-28
    • 2021-08-06
    • 1970-01-01
    相关资源
    最近更新 更多