在包含Controllers和ApiControllers的项目中从ApiController和Action名称获取Url

现有项目具有从以下任一项inheritance的控制器:

  • ControllerRouteTable.Routes.MapRoute with "{controller}/{action}/{id}"
  • ApiControllerGlobalConfiguration.Configure和回调MapRoute中的"api/{controller}/{id}"

一切正常,但我需要在这两种类型的控制器中生成动作方法的URL。 鉴于:

  1. 从这些中的任何一个inheritance的控制器的名称或类型
  2. 动作方法名称

然后从网站方面,我如何为Web API方面生成正确的URL?

我正在使用reflection来获取动作和控制器名称,然后通过使用UrlHelper.Action(actionName, controllerName, routeValueDictionary)获取网站路由的正确URL。

但是,这种方法(当然)为WebAPI端生成这样的URL: /ApiControllerName/Get?parameter1=value当需要/api/ApiControllerName?parameter1=value以及单独知道它是GET请求时。

目的:这是针对网站的烟雾测试页面,该页面使用属性和reflection来决定吸烟测试的内容。 能够在整个项目中使用相同的属性会很好,而且能够使用知道路由表的正确UrlHelper并且可以生成正确的前缀(如/api/ ,这将是非常好的,而不是代码假设,也许是错误的,API路由是用api注册的,而不是webapi

更新

在继续研究之后,我找到了可以生成WebAPI URL 的Url.HttpRouteUrl方法 ,但这需要知道路由名称,而不是操作方法名称。

我已经对此做了更多的研究,并且没有更接近解决方案。 看起来如果你知道相应路线的路线名称, 你可以轻松地制作一个Url 。 这里和这里也有一些可能的提示。 但是,如果有多个WebApi路由,您如何知道哪一个与您想要的控制器和操作相匹配? 重新实现MVC本身在选择控制器和动作方面已经做的事情是愚蠢的。 我想我可以使用每个WebApi路由从给定参数构造一个URL,然后通过它的步调运行URL(使用上面的一些链接)并查看它是否与所需的控制器匹配… yuck。

必须有一个更简单的方法。

现在我将继续前进,但是希望有人可以帮助我。

这里有几种方法可以做到:

  • 使用RouteUrl()方法:

     var url1 = Url.RouteUrl(new { id = 1, controller = "...", httproute = true }); 

诀窍当然是httproute = true 。 设置此属性,通知您只需要http路由(Web Api路由)。

  • 使用HttpRouteUrl()方法:

     var url2 = Url.HttpRouteUrl(null, new { id = 2, controller = ".." }); 
  • 另一种方法是直接使用路由和httproute值:

     var values = new RouteValueDictionary(new { id = 3, controller = "...", httproute = true }); var url3 = RouteTable.Routes.GetVirtualPath(Request.RequestContext, values).VirtualPath; 

这三种方式基本相同。 由于您未指定路线,系统将根据路线值尝试查找第一个匹配项。 例如,假设您有一个名为RestfulController并且Web api路由的配置如下:

 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); 

使用第一种方法,当你执行var url = Url.RouteUrl(new { id = 123, controller = "restful", httproute = true });MVC Controllerurl的值是/api/restful/123

但是如果你添加一个新路线ConstraintApi

 config.Routes.MapHttpRoute( name: "ConstraintApi", routeTemplate: "api2/{controller}/{id}", defaults: new { id = RouteParameter.Optional }, constraints: new { controller = "restful" } ); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); 

RouteUrl返回的url是/api2/restful/123

在宣布路线时,您应该知道订单。 如果在路径ConstraintApi之前添加路由DefaultApi ,则生成的url为/api/restful/123

有一个Hyprlinkr库,它允许您使用路由配置从Controller和Action创建URI。

这似乎更像是一个黑客,但如果你只打算用它进行测试,那值得一试。 如您所述,您可以生成带有路由名称的URL。 因此,您可以获取所有路径名称并生成所有可能的URL。 然后,您需要检查URL是否解析为您需要的操作。 为此,您可以使用以下内容: https : //stackoverflow.com/a/19382567/1410281 。 基本的想法是,如果你有一个URL,那么在那里做一个假的重定向,并从框架中获取路由数据。