gpt4 book ai didi

c# - 如何处理 .net MVC Core 中的动态错误页面?

转载 作者:行者123 更新时间:2023-12-03 17:20:14 25 4
gpt4 key购买 nike

目前我有

app.UseExceptionHandler("/Home/Error");

我想让路径相对于原始路径。

例如如果

Tenant1/PageThatThrowsError then app.UseExceptionHandler("Tenant1/Home/Error");



但如果

Tenant2/PageThatThrowsError then app.UseExceptionHandler("Tenant2/Home/Error");



我以为我能做到
app.UseExceptionHandler(
new ExceptionHandlerOptions
{
ExceptionHandler = async (ctx) =>
{
//logic that extracts tenant
ctx.Request.Path = new PathString(Invariant($"{tenant}/Home/Error"));
}
}
);

但这会抛出 500

编辑:例如使用重定向的所有当前解决方案都会丢失当前的错误上下文,并且不允许 Controller 例如调用 HttpContext.Features.Get()。

最佳答案

我们假设应用程序需要 /Tenant1/Home/Error 的路由和端点。和 /Tenant2/Home/Error .您可以使用以下代码解决问题:

app.UseExceptionHandler(
new ExceptionHandlerOptions
{
ExceptionHandler = async (ctx) =>
{
string tenant = ctx.Request.Host.Value.Split('/')[0];
ctx.Response.Redirect($"/{tenant}/Home/Error");
},
}
);

另一个等效的解决方案是将以下代码放在 startup.cs 上:
app.UseExceptionHandler("$/{tenant}/Home/Error");

我们假设 tenant来自诸如 appsettings 之类的地方。然后,您可以通过在您的操作上编写一个简单的路由,轻松地在您想要的端点上获得异常:
[Route("/{TenantId}/Home/Error")]
public IActionResult Error(string TenantId)
{
string Id = TenantId;
// Here you can write your logic and decide what to do based on TenantId
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}

或者您可以创建两个不同的操作:
[Route("/Tenant1/Home/Error")]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[Route("/Tenant2/Home/Error")]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}

更新:

如果你的租户是动态添加的,无法放入你的 appsettings.json (我们在上述解决方案中假设的)您可以编写一个中间件来处理异常,方法如下:

在您的 Startup.cs 中添加中间件在 Configure方法:
app.UseMiddleware(typeof(ErrorHandlingMiddleware));

在下一行添加错误路由(正好在中间件之后):
app.UseMvc(routes =>
{
routes.MapRoute(
name: "errors",
template: "{tenant}/{controller=Home}/{action=Index}/");
});

为您的中间件创建一个类,并将这些代码放在:
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
this.next = next;
}

public async Task Invoke(HttpContext context /* other dependencies */)
{
try
{
await next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex,this.next);
}
}

private static Task HandleExceptionAsync(HttpContext context, Exception ex, RequestDelegate next)
{
string tenant = "tenant1";//write your logic something like this: context.Request.Path.Value.Split('/')[0];
context.Request.Path = new PathString($"/{tenant}/Home/Error");
context.Request.HttpContext.Features.Set<Exception>(ex);// add any object you want to the context
return next.Invoke(context);
}
}

请注意,您可以像这样在上下文中添加任何您想要的内容: context.Request.HttpContext.Features.Set<Exception>(ex); .

最后,您应该创建一个具有适当路由的操作来在那里编写您的逻辑:
[Route("/{TenantId}/Home/Error")]
public IActionResult Error(string TenantId)
{
string Id = TenantId;
var exception= HttpContext.Features.Get<Exception>();// you can get the object which was set on the middle-ware
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}

请注意,现在可以检索在中间件上设置的对象。

关于c# - 如何处理 .net MVC Core 中的动态错误页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60814674/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com