首页 > 解决方案 > HttpContext GetEndpoint 修改请求路径.net 5

问题描述

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

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

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

当 countryCode 在 url (mysite.com/us/home/Index )中时, GetEndpoint返回 null。

但是,如果我在 url (mysite.com/home/Index) 中输入没有 countryCode 的站点,那么就GetEndpoint可以了。

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

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

标签: c#asp.net-coremodel-view-controllermiddleware.net-5

解决方案


我找到了解决方案,

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

我不知道它的扩展性如何,但它现在可以工作。我在这里找到了代码的主要部分:Changing Request Path in .Net Core 3.1


推荐阅读