Мы предполагаем, что приложению требуются маршруты и конечные точки /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
in 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);
}
}
Обратите внимание, что вы можете добавить в контекст все, что захотите, например this: context.Request.HttpContext.Features.Set<Exception>(ex);
.
И, наконец, вы должны создать действие с соответствующей маршрутизацией, чтобы записать туда свои логи c:
[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 });
}
Обратите внимание, что объект, который был установлен на промежуточное ПО, теперь можно получить.