似乎可以通过定义自定义路由来做到这一点。在 MVC4(最后一个稳定版本 4.0.30506.0)中,不可能IHttpRoute
按照规范实现,而是定义自定义 MVC 级别Route
并将其直接添加到RouteTable
. 详情见1、2。_ _ 下面的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;
}
}
添加这个DelegatingHandler
以避免NullReference
由于其他一些错误:
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());
瞧!
编辑:当 API 是自托管的(而不是使用 WebHost)时,此解决方案会出现问题,并且需要进一步的工作才能使其与两者一起使用。如果有人对此感兴趣,请发表评论,我会发布我的解决方案。