如何处理.net MVC Core中的动态错误页面? [英] How to handle dynamic error pages in .net MVC Core?

查看:99
本文介绍了如何处理.net MVC Core中的动态错误页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前我有

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

我要使路径相对于原始路径.

I want to make the path relative to the original path.

例如,如果

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

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

但如果

Tenant2/PageThatThrowsError然后app.UseExceptionHandler("Tenant2/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

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

推荐答案

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

We suppose that the application has required routes and endpoints of /Tenant1/Home/Error and /Tenant2/Home/Error. You can solve the issue using this code:

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

另一种等效的解决方案是将以下代码放在 startup.cs 上:

Another equivalent solution is putting the following code on the startup.cs:

app.UseExceptionHandler("$/{tenant}/Home/Error");

我们假设 tenant 来自诸如appsettings之类的地方.然后,您可以通过在操作上编写一条简单的路线来轻松地在所需的端点上获取异常:

We suppose that tenant comes from somewhere like appsettings. Then you can easily get exceptions on your desired endpoint by writing a simple route on your action:

[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 });
}

或者您可以创建两个不同的操作:

or you can create two different actions:

[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 中(在上述解决方案中我们已经假设过),则可以编写一个中间件来处理Exceptions,方法如下:

If your tenants are dynamically added and can't be put in your appsettings.json (what we've supposed in the above solutions) you can write a middle-ware to handle the Exceptions, here is how:

Startup.cs 中的 Configure 方法中添加中间件:

Add the middle-ware in your Startup.cs in Configure method:

app.UseMiddleware(typeof(ErrorHandlingMiddleware));

在下一行添加错误的路由(恰好在中间件之后):

At the next line add a route for errors (exactly after the middle-ware):

app.UseMvc(routes =>
    {
       routes.MapRoute(
            name: "errors",
            template: "{tenant}/{controller=Home}/{action=Index}/");
    });

为您的中间件创建一个类,并将这些代码放在:

Create a class for your middle-ware, and put these code on:

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); .

Note that you can add anything you want to the context like this: context.Request.HttpContext.Features.Set<Exception>(ex);.

最后,您应该创建一个具有适当路由的操作,以在其中编写逻辑:

And finally you should create an action with an appropriate routing to write your logic there:

[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 });
}

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

Note that the object which was set on the middle-ware, now can be retrieved.

这篇关于如何处理.net MVC Core中的动态错误页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆