【问题标题】:using UseExceptionHandler() with API handling and 404 handling in ASP.NET Core 2在 ASP.NET Core 2 中使用带有 API 处理和 404 处理的 UseExceptionHandler()
【发布时间】:2020-07-10 13:27:12
【问题描述】:

我有以下情况:

  • ASP.NET Core 2 在/api/* 上提供 api 请求
  • ASP.NET Core 2 在/health 上服务健康请求
  • /svc/* 上的 ASP.NET Core 2 服务器代理请求
  • ASP.NET Core 2 在 /app/ 上提供 SPA(如果您转到 example.com,它将提供来自 /app/ 文件夹的文件。

现在,如果有人请求一个不存在的实体,则会引发异常。这是通过在 Startup.cs 中使用以下内容处理的

app.UseExceptionHandler("/error");

ErrorController 处理这些异常并返回 NotFound()BadRequest() 等内容。最终,它们都是 JSON 响应。

现在,如果您要转到 /hshfdhfgh 网址,现在会产生一个空的 404 页面,因为没有任何匹配项。但我想做的是能够为错误页面添加一些自定义 HTML 视图。也许使用 Razor Pages 或其他东西。

我已经查过了,建议您使用UseExceptionHandler("/error") 方法,这样您就可以返回一些视图。但这会与我的 JSON 响应冲突!

我唯一能想到的就是:

if request does not start with /health, /svc/, /, /app or /api/
    app.UseExceptionHandler("/error/404");
else
    app.UseExceptionHandler("/error");

但这感觉很hacky。有没有其他办法?

而且,为我的项目添加剃须刀支持的最佳/最简单的方法是什么?目前没有。

【问题讨论】:

  • 你有两个选择:一个是使用异常处理程序和一个处理错误的自定义控制器。二是将任何你想要的东西直接写到响应中
  • 如果是这样,我当然更喜欢选项 1。但是返回 404 JSON 和 404 HTML 有什么不同呢?

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


【解决方案1】:

您可以以此为起点(它是 netcore 3.1,但我认为从 2 迁移时我们不必进行重大更改)。让处理程序本身正确,并将其放置在 Startup 中的正确位置,这感觉很糟糕,而且很痛苦(特别是如果您将它与正确处理未经授权的响应、剃刀视图和这些剃刀视图的静态文件等事情结合起来)。但我没有找到更好的方法。

public static readonly PathString ApiPath = new PathString("/api");
public static readonly PathString StaticFilePath = new PathString("/site");
static bool IsApiRequestPredicate(HttpContext context) => context.Request.Path.StartsWithSegments(ApiPath, StringComparison.InvariantCulture);
static bool IsStaticFilePredicate(HttpContext context) => context.Request.Path.StartsWithSegments(StaticFilePath, StringComparison.InvariantCulture);

...

app.UseWhen(x => !IsApiRequestPredicate(x) && !IsStaticFilePredicate(x), builder =>
{
    builder.UseStatusCodePagesWithReExecute("/Error/StatusCodeViewReexecuteHandler/{0}");
    app.UseDeveloperExceptionPage();
});
app.UseWhen(x => IsApiRequestPredicate(x), builder =>
{
    builder.UseExceptionHandler("/Error/ExceptionApiReexecuteHandler");
    builder.UseStatusCodePagesWithReExecute("/Error/StatusCodeApiReexecuteHandler/{0}");
});

您也可以仅使用一个处理程序并根据 ErrorController 操作中的 OriginalPath 进行决定:

var errorFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerFeature>();
if (errorFeature.OriginalPath.StartsWith("/api", StringComparison.InvariantCulture))
{
    return BadRequest(new { error = "entity not found" });
} else {
    return View("NotFound");
}
// exceptionFeature gives you access to the exception thrown

【讨论】:

    猜你喜欢
    • 2021-11-28
    • 2016-07-29
    • 2019-02-11
    • 2019-08-07
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 2011-04-03
    相关资源
    最近更新 更多