在包含Controllers和ApiControllers的项目中从ApiController和Action名称获取Url
现有项目具有从以下任一项inheritance的控制器:
-
Controller
:RouteTable.Routes.MapRoute
with"{controller}/{action}/{id}"
。 -
ApiController
:GlobalConfiguration.Configure
和回调MapRoute
中的"api/{controller}/{id}"
。
一切正常,但我需要在这两种类型的控制器中生成动作方法的URL。 鉴于:
- 从这些中的任何一个inheritance的控制器的名称或类型
- 动作方法名称
然后从网站方面,我如何为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 Controller
, url
的值是/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,那么在那里做一个假的重定向,并从框架中获取路由数据。