Asp.net web api 如何修改ASP NET Web API路由匹配以允许内部带有斜杠的参数?

Asp.net web api 如何修改ASP NET Web API路由匹配以允许内部带有斜杠的参数?,asp.net-web-api,asp.net-mvc-routing,Asp.net Web Api,Asp.net Mvc Routing,我们在后端使用RavenDB,因此所有DB键都是包含前斜杠的字符串,例如users/1 好了,如果不使用catch-all(这意味着密钥必须是URL上的最后一个内容),就无法使用默认的ASP NET Web API路由匹配引擎来匹配这样的参数。我尝试添加一个regex约束,即users/d+,但似乎没有什么不同,路径不匹配 我需要替换哪些位来进行足够的自定义路由匹配,以允许这样做,最好是不破坏路由匹配的其余部分。例如,使用url:“{*route}”和进行完全正则表达式匹配的自定义约束可以工作,

我们在后端使用RavenDB,因此所有DB键都是包含前斜杠的字符串,例如
users/1

好了,如果不使用catch-all(这意味着密钥必须是URL上的最后一个内容),就无法使用默认的ASP NET Web API路由匹配引擎来匹配这样的参数。我尝试添加一个regex约束,即
users/d+
,但似乎没有什么不同,路径不匹配

我需要替换哪些位来进行足够的自定义路由匹配,以允许这样做,最好是不破坏路由匹配的其余部分。例如,使用
url:“{*route}”
和进行完全正则表达式匹配的自定义约束可以工作,但可能会意外地与其他路由配置一起工作


如果您的答案带有一些示例代码,那就更好了。

似乎可以通过定义自定义路由来实现这一点。在MVC4(最新稳定版本4.0.30506.0)中,不可能按照规范实现
IHttpRoute
,而是通过定义自定义MVC级别
Route
并将其直接添加到
RouteTable
。有关详细信息,请参阅。下面的
RegexRoute
实现基于答案中的mods实现

定义
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;
    }
}
将处理程序和路由直接添加到
RouteTable

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

        config.MessageHandlers.Add(new RouteByPassingHandler());
RouteTable.Routes.Add(新的RegexRoute(@“^api/home/index/(?\d+)$”,“test”,新的{controller=“home”,action=“index”});
添加(新的RouteByPassingHandler());


编辑:当API是自托管(而不是使用WebHost)时,此解决方案会出现问题,需要进一步的工作才能使其与这两种API一起工作。如果有人对此感兴趣,请留下评论,我将发布我的解决方案。

看这里,请再次阅读问题:
不使用“一网打尽”,这意味着密钥必须是URL上的最后一个内容
抱歉-错过了这一点。据我所知,这不能用默认的路由引擎来完成。您要么必须使用catch all,要么考虑编写自定义路由约束(但仍将使用catch all,但会给您更多的灵活性),正确的方法是覆盖IHttpRoute并在GetRouteData中进行处理,但它似乎永远不会被调用!!看-也许你有什么见解可以分享。找到了一个方法!看看我的答案。
RouteTable.Routes.Add(new RegexRoute(@"^api/home/index/(?<id>\d+)$", "test", new { controller = "Home", action = "Index" }));

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