结合 Razor Pages 和 ApiControllers 的应用程序中的 Asp.net 核心异常处理

Posted

技术标签:

【中文标题】结合 Razor Pages 和 ApiControllers 的应用程序中的 Asp.net 核心异常处理【英文标题】:Asp.net core exception handling in applications that combines Razor Pages and ApiControllers 【发布时间】:2021-11-01 00:36:15 【问题描述】:

使用结合了 Razor 页面和 Api 控制器的 asp.net 应用程序时。 如何全局检查 Api Controller 是否抛出异常?

这个想法是使用UseExceptionHandler midlleware,但如果从 Razor 页面抛出未经处理的异常,则有条件地返回 html 响应;如果从 ApiController 抛出异常,则有条件地返回 json ProblemDetails 响应

【问题讨论】:

“检查是否抛出异常”是什么意思?您是否正在为所有 API 控制器寻找全局异常处理程序? 你用的是哪个版本? 我的目标是 netcoreapp3.1 【参考方案1】:

对于web Api,使用Api添加属性路由,然后在中间件或异常处理程序中检查请求路径,如下所示:

app.UseExceptionHandler("/Error"); //handle the exception from the razor page

//handle the exception from the API.
app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), subApp =>

    subApp.UseExceptionHandler(builder =>
    
        builder.Run(async context =>
        
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; 
            context.Response.ContentType = "application/json"; 
            await context.Response.WriteAsync("\"error\":\"Exception from API!\"");
            //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");
        );
    );
);

结果如下:

此外,您还可以使用自定义异常处理程序页面为 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");
        
    );
);

更多详情见asp.net core app.UseExceptionHandler() to handle exceptions for certain endpoints?

【讨论】:

以上是关于结合 Razor Pages 和 ApiControllers 的应用程序中的 Asp.net 核心异常处理的主要内容,如果未能解决你的问题,请参考以下文章

关于 razor,.NET MVC 对 razor 的支持与 .NET razor pages 有啥区别,有啥叫做 .NET MVC razor pages 的东西吗?

Razor-Pages - HTML 标记

Razor Pages 在页面加载时设置当前日期

当其他输入验证验证失败时,Razor Pages textarea 输入只会增长和增长

如何从 Razor Pages 应用程序中的插件动态加载页面?

单击 Razor Pages Asp 发送电子邮件和重定向