且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何修改ASP NET的Web API路线相匹配,让里面的斜线参数?

更新时间:2022-02-23 01:05:43

这似乎是可以通过定义一个定制的路由做到这一点。在MVC4(最新稳定释放4.0.30506.0),它是不可能通过实施 IHttpRoute 根据规范,但通过定义一个定制的MVC级做路线并直接将它添加到 RouteTable 。有关详情请参见 1 ,的 2 。下面的 RegexRoute 的实施是基于执行这里与答案的href=\"http://***.com/questions/12544150/asp-net-web-api-rtm-and-subdomain-routes\">here.

It seems that it is possible to do this by defining a custom route. In MVC4 (last stable released 4.0.30506.0), it is not possible to do by implementing IHttpRoute as per specification but by defining a custom MVC-level Route and adding it directly to the RouteTable. For details see 1, 2. The RegexRoute implementation below is based on the implementation here with mods from the answer here.

定义 RegexRoute

public class RegexRoute : Route
{
    private readonly Regex urlRegex;

    public RegexRoute(string urlPattern, string routeTemplate, object defaults, object constraints = null)
        : base(routeTemplate, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(), HttpControllerRouteHandler.Instance)
    {
        urlRegex = new Regex(urlPattern, RegexOptions.Compiled);
    }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        string requestUrl = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

        Match match = urlRegex.Match(requestUrl);

        RouteData data = null;

        if (match.Success)
        {
            data = new RouteData(this, RouteHandler);

            // add defaults first
            if (null != Defaults)
            {
                foreach (var def in Defaults)
                {
                    data.Values[def.Key] = def.Value;
                }
            }

            // iterate matching groups
            for (int i = 1; i < match.Groups.Count; i++)
            {
                Group group = match.Groups[i];

                if (group.Success)
                {
                    string key = urlRegex.GroupNameFromNumber(i);

                    if (!String.IsNullOrEmpty(key) && !Char.IsNumber(key, 0)) // only consider named groups
                    {
                        data.Values[key] = group.Value;
                    }
                }
            }
        }

        return data;
    }
}

将此 DelegatingHandler 来避免 NullReference 由于一些其它的错误:

Add this DelegatingHandler to avoid a NullReference due to some other bug:

public class RouteByPassingHandler : DelegatingHandler
    {
        protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            HttpMessageInvoker invoker = new HttpMessageInvoker(new HttpControllerDispatcher(request.GetConfiguration()));
            return invoker.SendAsync(request, cancellationToken);
        }
    }

直接添加处理和路由到 RouteTable

RouteTable.Routes.Add(new RegexRoute(@"^api/home/index/(?<id>\d+)$", "test", new { controller = "Home", action = "Index" }));

        config.MessageHandlers.Add(new RouteByPassingHandler());

乙醚瞧!

修改:这个解决方案有问题,当空气污染指数是自托管(而不是使用一个虚拟主机提供商),需要进一步的工作,使之既工作。如果这是有趣的人,请留下评论,我会后我的解决方案。

EDIT: This solution has problems when the API is self-hosted (instead of using a WebHost) and requires further work to make it work with both. If this is interesting to anyone, please leave a comment and I'll post my solution.