从包含Controllers和ApiControllers

时间:2016-03-10 00:47:41

标签: c# asp.net-mvc asp.net-web-api

现有项目的控制器继承自:

  • ControllerRouteTable.Routes.MapRoute"{controller}/{action}/{id}"
  • ApiControllerGlobalConfiguration.Configure以及MapRoute"api/{controller}/{id}"的回调。

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

  1. 继承自其中任何一个和
  2. 的控制器的名称或类型
  3. 操作方法名称
  4. 然后从网站方面,我如何为Web API方面生成正确的URL?

    我现在使用反射获取操作和控制器名称,然后使用UrlHelper.Action(actionName, controllerName, routeValueDictionary)获取网站路由的正确URL。

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

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

    更新

    继续研究后,我发现the Url.HttpRouteUrl method可以生成WebAPI网址,但这需要知道路由名称,而不是操作方法名称。

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

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

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

3 个答案:

答案 0 :(得分:5)

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

  • 使用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;
    

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

RestfulController

使用第一种方法,当您在 MVC 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 });时,Controller中的值为url

但是如果添加新路线 ConstraintApi

/api/restful/123

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

您在宣布路线时应该了解订单。如果路线/api2/restful/123在路线DefaultApi之前添加,则生成的网址为ConstraintApi

答案 1 :(得分:3)

Hyprlinkr库允许您使用路由配置从Controller和Action创建URI。

答案 2 :(得分:0)

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