首页 文章

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

提问于
浏览
10

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

  • ControllerRouteTable.Routes.MapRoute"{controller}/{action}/{id}" .

  • ApiControllerGlobalConfiguration.Configure 并在回调 MapRoute 中使用 "api/{controller}/{id}" .

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

  • 从其中任何一个继承的控制器的名称或类型,和

  • 一个动作方法名称

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

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

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

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

Update

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

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

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

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

3 回答

  • 0

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

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

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

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

    使用第一种方法,当您在MVC Controller 中执行 var url = Url.RouteUrl(new { id = 123, controller = "restful", httproute = true }); 时, 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 返回的网址是 /api2/restful/123 .

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

  • 5

    Hyprlinkr库,允许您使用路径配置从Controller和Action创建URI .

  • 3

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

相关问题