修改后的请求路径上的 HttpContext GetEndpoint .net 5

HttpContext GetEndpoint on modified request path .net 5

我正在尝试创建一个中间件来处理 url 中的国家/地区代码。 我的代码非常适合删除国家代码,因此它被路由到 mvc 管道中的正确端点。

我遇到的问题是我需要根据端点是否具有特定属性来执行一些操作。

我看到 HttpContext 有一个方法 GetEndpoint,这正是我需要的。

当国家代码在url(mysite.com/us/home/Index)时, GetEndpoint returns 空。

但是如果我在 url (mysite.com/home/Index) 中输入没有国家代码的站点,那么 GetEndpoint 有效。

如何在修改后的请求 url 上使用 GetEndpoint() 方法?

我需要更改 HttpContext 上的另一个 属性 吗?

public async Task InvokeAsync(HttpContext httpContext)
{
    // mysite.com/us/home/Index
    var currentAddress = httpContext.Request.Path; 
    
    // mysite.com/home/Index
    httpContext.Request.Path = ExtractCountryCodeFromUrl(currentAddress); 

    var endpoint = httpContext.GetEndpoint(); // null

    var hasMyAttribute = endPoint.Metadata.GetMetadata<MyAttribute>();
    // Do something...

    await next(httpContext);
}

我找到了解决方法,

private static ControllerActionDescriptor GetControllerByUrl(HttpContext httpContext)
{
    var pathElements = httpContext.Request.Path.ToString().Split("/").Where(m => m != "");
    string controllerName = (pathElements.ElementAtOrDefault(0) == "" ? null : pathElements.ElementAtOrDefault(0)) ?? "w";
    string actionName = (pathElements.ElementAtOrDefault(1) == "" ? null : pathElements.ElementAtOrDefault(1)) ?? "Index";

    var actionDescriptorsProvider = httpContext.RequestServices.GetRequiredService<IActionDescriptorCollectionProvider>();
    ControllerActionDescriptor controller = actionDescriptorsProvider.ActionDescriptors.Items
    .Where(s => s is ControllerActionDescriptor bb
                && bb.ActionName == actionName
                && bb.ControllerName == controllerName
                && (bb.ActionConstraints == null
                    || (bb.ActionConstraints != null
                        && bb.ActionConstraints.Any(x => x is HttpMethodActionConstraint cc
                        && cc.HttpMethods.Any(m => m.ToLower() == httpContext.Request.Method.ToLower())))))
    .Select(s => s as ControllerActionDescriptor)
    .FirstOrDefault();
    return controller;
}

那我就可以了

ControllerActionDescriptor controller = GetControllerByUrl(httpContext);
var countryCodeAttribute = controller.MethodInfo.GetCustomAttribute<MyAttribute>();

我不知道它的扩展性如何,但它现在可以使用。 我在这里找到了代码的主要部分:

我遇到了同样的问题,问题的解决方案(至少是我的)是 Startup 中中间件的顺序:您的自定义中间件必须在 UseRouting()

之后
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseMiddleware<MyCustomMiddleware>();

    app.UseAuthorization();

    app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}