Làm cách nào để xử lý các trang lỗi động trong .net MVC Core?


8

Hiện tại tôi có

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

Tôi muốn làm cho đường dẫn liên quan đến đường dẫn ban đầu.

Ví dụ nếu

Tenant1 / PageThatThrowsError sau đó app.UseExceptionHandler ("Tenant1 / Home / Error");

nhưng nếu

Tenant2 / PageThatThrowsError sau đó app.UseExceptionHandler ("Tenant2 / Home / Error");

Tôi nghĩ rằng tôi sẽ có thể làm

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

nhưng điều này ném 500

EDIT: Tất cả các giải pháp hiện tại, ví dụ sử dụng chuyển hướng đều làm mất bối cảnh lỗi hiện tại và không cho phép bộ điều khiển ví dụ gọi HTTPContext.Features.Get ().


Tôi không chắc chắn nếu điều này sẽ giúp docs.microsoft.com/en-us/aspnet/core/fundamentals/ Khăn
Patrick Mcvay

Tôi có thể chỉ xử lý việc chuyển hướng (giả sử rằng bạn có một trang lỗi cho mọi người thuê) trong phương thức lỗi được gọi bởi trình xử lý ngoại lệ mặc định hoặc bạn có thể thực hiện như liên kết trên hiển thị và tạo phản hồi động.
Patrick Mcvay

Trình xử lý lỗi thực hiện một loạt các công cụ ra khỏi hộp như chuyển mã lỗi và cứ thế. CNTT sẽ rất tuyệt nếu vẫn có điều đó và chỉ cần có thể thiết lập url động.
Murdock

ứng dụng của bạn có nghe Tenant1 / Home / Error và Tenant2 / Home / Error không?
Alireza Mahmoudi

Đúng. Nhưng vấn đề là định tuyến nó
Murdock

Câu trả lời:


2

Chúng tôi cho rằng ứng dụng có các tuyến và điểm cuối yêu cầu /Tenant1/Home/Error/Tenant2/Home/Error. Bạn có thể giải quyết vấn đề bằng mã này:

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

Một giải pháp tương đương khác là đặt đoạn mã sau vào startup.cs:

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

Chúng tôi cho rằng điều đó tenantđến từ một nơi nào đó như cài đặt ứng dụng. Sau đó, bạn có thể dễ dàng nhận được các ngoại lệ trên điểm cuối mong muốn của mình bằng cách viết một lộ trình đơn giản cho hành động của bạn:

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

hoặc bạn có thể tạo hai hành động khác nhau:

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

Cập nhật:

Nếu người thuê nhà của bạn được thêm động và không thể đưa vào appsettings.json(những gì chúng tôi đã giả định trong các giải pháp trên), bạn có thể viết một kho trung gian để xử lý các Ngoại lệ, đây là cách:

Thêm kho trung gian Startup.cstrong Configurephương thức của bạn :

app.UseMiddleware(typeof(ErrorHandlingMiddleware));

Ở dòng tiếp theo, thêm một tuyến cho các lỗi (chính xác là sau kho trung gian):

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

Tạo một lớp cho kho trung gian của bạn và đặt các mã này vào:

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

Lưu ý rằng bạn có thể thêm bất cứ điều gì bạn muốn vào bối cảnh như thế này : context.Request.HttpContext.Features.Set<Exception>(ex);.

Và cuối cùng bạn nên tạo một hành động với một định tuyến thích hợp để viết logic của bạn ở đó:

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

Lưu ý rằng đối tượng đã được đặt trên kho trung gian, bây giờ có thể được truy xuất.


HttpContext.Features.Get <IExceptionHandlerPathFeature> () sử dụng để có sẵn trong bộ điều khiển Lỗi. Sử dụng chuyển hướng làm mất bối cảnh đó và bạn không thể truy xuất nó nữa.
Murdock

@Murdock Còn giải pháp thứ hai thì sao? giải pháp thứ hai có vẻ hiệu quả.
Alireza Mahmoudi

Người thuê nhà của tôi rất năng động do đó tôi không thể thêm tuyến đường.
Murdock

Tuyến đường app.UseExceptionHandler($"/{tenant}/Home/Error");không tĩnh! Bạn có thể đặt những gì bạn muốn thay vì {tenant}, và với lộ trình Route("/{TenantId}/Home/Error")]bạn có thể lắng nghe tất cả chúng.
Alireza Mahmoudi

Ok nhưng làm thế nào .net biết người thuê nào sẽ định tuyến đến với app.UseExceptionHandler ($ "/ {tenant} / Home / Error"). Câu hỏi hỏi làm thế nào để suy ra nó từ url đến gây ra lỗi.?
Murdock
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.