如何使用DefaultHttpContext从Uri获取RouteData

问题描述 投票:0回答:1

我正在将代码从 .net4.8 框架迁移到 .net 8 MVC 项目

之前我们使用此代码从 Uri 中获取控制器名称

public class GetRouteDataContext : HttpContextBase
{
    public override HttpRequestBase Request { get; }

    private RouteDataContext(Uri uri)
    {
        var url = uri.GetLeftPart(UriPartial.Path);
        var qs = uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped);
        Request = new HttpRequestWrapper(new HttpRequest(null, url, qs));
    }

    public static RouteValueDictionary RouteValuesFromUri(Uri uri)
    {
        return RouteTable.Routes.GetRouteData(new RouteDataContext(uri)).Values;
    }
}

现在我们不能使用这个 HttpContextBase、HttpRequestBase、HttpRequestWrapper 和 RouteTable.Routes.GetRouteData(new RouteDataContext(uri)) 来获取 RouteData

需要帮助以替代方法获取 RouteData。我对我写的代码没有信心。

我尝试在 HttpContext 中的 EndpointDataSource 的帮助下从 Uri 获取routeValues

public class GetRouteDataContext 
{
    private static HttpContext _httpContext => new HttpContextAccessor().HttpContext;
    public HttpContext HttpContext { get; }

    // Constructor to initialize HttpContext from the given Uri
    public GetRouteDataContext(Uri uri)
    {
        var qs = uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped);
        qs = !string.IsNullOrEmpty(qs) ? (qs.Contains('?') ? qs : "?" + qs) : qs;
        HttpContext = new DefaultHttpContext
        {
            Request = {
                Scheme = uri.Scheme,
                Host = new HostString(uri.Host),
                Path = new PathString(uri.AbsolutePath),
                QueryString = new QueryString(qs)
            },
        };
    }

    public RouteValueDictionary RouteValuesFromUri(Uri uri)
    {
        var routeContext = new GetRouteDataContext(uri);
        // Use HttpContext to get route data
        var routeData = GetRouteData(routeContext.HttpContext);

        return routeData?.Values ?? new RouteValueDictionary();
    }

    // Manually resolve route data using EndpointDataSource
    private RouteData GetRouteData(HttpContext httpContext)
    {
        var endpointDataSource = _httpContext.RequestServices.GetRequiredService<EndpointDataSource>();

        var routeContext = new RouteContext(httpContext);

        foreach (var endpoint in endpointDataSource.Endpoints)
        {
            if (endpoint is RouteEndpoint routeEndpoint && routeEndpoint.RoutePattern != null)
            {
                var routeValues = routeEndpoint.RoutePattern.RequiredValues;
                var meta = routeEndpoint.Metadata.GetMetadata<ControllerActionDescriptor>();
                string endpointUrl = string.Format("/{0}/{1}", meta.ControllerName, meta.ActionName);
                if (httpContext.Request.Path.ToString().Contains(endpointUrl))
                {
                    routeContext.RouteData.Values.Add("controller", routeValues["controller"]);
                    routeContext.RouteData.Values.Add("action", routeValues["action"]);

                    return routeContext.RouteData;
                }
            }
        }

        return null; // No matching route found
    }

}

请建议获取路线值的替代方法/有效方法。

注意:我是 .net core 和迁移代码的新手

asp.net-core-mvc .net-8.0
1个回答
0
投票

您可以尝试使用下面的优化方法。

public class RouteDataExtractor
{
    public static RouteData GetRouteData(Uri uri, IRouteCollection routes)
    {
        var services = new ServiceCollection();
        services.AddRouting();

        var serviceProvider = services.BuildServiceProvider();

        var httpContext = new DefaultHttpContext
        {
            RequestServices = serviceProvider
        };

        httpContext.Request.Path = uri.LocalPath;
        httpContext.Request.Host = new HostString(uri.Host);

        var routeContext = new RouteContext(httpContext);
        var route = routes.GetRouteData(httpContext);

        return route;
    }
}

然后用这个方法获取Uri。

var routeData = RouteDataExtractor.GetRouteData(new Uri("https://localhost/home/index"), routeBuilder);
© www.soinside.com 2019 - 2024. All rights reserved.