我们假设应用程序具有所需的路由和端点/Tenant1/Home/Error
and /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
来自应用程序设置之类的地方。然后,您可以通过在操作上编写简单的路由来轻松获得所需端点上的异常:
[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 });
}
Update:
如果您的租户是动态添加的并且无法放入您的appsettings.json
(我们在上面的解决方案中假设的)您可以编写一个中间件来处理异常,方法如下:
将中间件添加到您的Startup.cs
in Configure
method:
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 });
}
请注意,现在可以检索在中间件上设置的对象。