【问题标题】:Web API route mapping to rootWeb API 路由映射到根
【发布时间】:2012-11-05 11:19:09
【问题描述】:

我正在设置一个 ASP.NET MVC 4 Web API 来接受来自第 3 方服务器的请求,但我根本不知道如何设置路由映射。 假设第 3 方服务器期望获得以下响应:

  1. http://[my_server]/authorize?user=[user name]&session=[session token]&item=[item]
  2. http://[my_server]/release?user=[user name]&session=[session token]

或者,请求可以使用专用路径,即:

  1. http://[my_server]/***api***/authorize?user=[user name]&session=[session token]&item=[item]
  2. http://[my_server]/***api***/release?user=[user name]&session=[session token]

我希望能够同时支持这两种选择。

其他请求,遵循更传统的/controller/id 形式,也应该实现,但我想重点关注上述内容(我什至不确定 Web API 是否适合这里)。

我编写了以下控制器:

public class MyController : ApiController
{
    [HttpGet]
    [ActionName("authorize")]
    public string Authorize(string user, string session, string item)
    {
        ...
        // return "OK" or "DENY";
    }

    [HttpGet]
    [ActionName("release")]
    public string Release(string user, string session)
    {
        ...
        return "OK";
    }
}

并尝试了我可以在 SO 和 WebAppConfig.Register 的其他地方找到的所有内容,但是当我在浏览器中尝试请求时,我不断收到 404 错误:

http://localhost:22332/api/authorize?user=ury&session=token&item=an_item

我的问题是,我必须做什么 - 特别是在 WebAppConfig.Register 和控制器中 - 为了满足上述请求(假设我的测试 URL 是正确的......)?

【问题讨论】:

    标签: asp.net-web-api asp.net-mvc-routing asp.net-web-api-routing


    【解决方案1】:

    经过几个小时的工作并得到了Route Debugger 的大力帮助 - 感谢 Phil Haack! - 我找到了问题和解决方案。

    问题:路由映射匹配是有序的,而RouteTable.Routes,应用的路由映射是从其中初始化的,包含相当多的。我正在寻找的请求模式也匹配其中一些映射(例如,“授权”被匹配为控制器)。

    解决方案:在默认映射之前添加“我的”路由映射。

    是的,没错……

    由于HttpRouteCollection 不支持大多数操作,因此生成的代码有点难看,但它可以工作:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            routesCopy = new RouteBase[RouteTable.Routes.Count];
    
            RouteTable.Routes.CopyTo(routesCopy, 0);
    
            config.Routes.Clear();
            config.Routes.MapHttpRoute(name: "AuthorizeWebApiRoute", routeTemplate: "authorize", defaults: new { controller = "My", action = "authorize" });
            config.Routes.MapHttpRoute(name: "ReleaseWebApiRoute", routeTemplate: "release", defaults: new { controller = "My", action = "release" });
    
            foreach (var route in routesCopy)
            {
                RouteTable.Routes.Add(route);
            }
        }
    }
    

    只要“我的”路由映射与默认映射不匹配(我将它们具体化到不匹配),我都很好 - 我认为...

    【讨论】:

      【解决方案2】:

      您会被用于将 URL 中的控制器名称与控制器类匹配的 Web API 约定绊倒。

      如果你的控制器名称是“MyController”,那么请求的 URL 是:

      http://localhost:22332/api/my/authorize?user=ury&session=token&item=an_item
      

      要支持 URL 中没有“api”位的请求,只需在 WebApiConfig.cs 的 Register 方法中添加第二个路由定义。由于您还在 URL 中使用“操作”,因此您需要以下两条路由:

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

      如果你想省略“api”前缀以及控制器参数,我认为你需要一个不同的路由定义。比如:

          public static void Register(HttpConfiguration config) {
              config.Routes.MapHttpRoute(
                  name: "ActionOnlyRoute",
                  routeTemplate: "{action}",
                  defaults: new { controller = "My" }
              );
          }
      

      在这里,我们只会在 URL 中查找“动作”并将所有内容路由到您的“MyController”类。

      【讨论】:

      • 谢谢马克。我不仅想省略“api”,还想省略控制器前缀,而且我没有使用 {id} 参数(除非我遗漏了什么)。我确实尝试了 routeTemplate: "{action}",但我得到了 404 页面。
      • 好的,我已经更新了我的答案。希望这就是你所追求的。
      • 听起来很简单,但还是不行...我得到 404,找不到资源(资源是“授权”、“释放”等)。我一遍又一遍地检查拼写(通常的嫌疑人),没关系。知道如何找出问题所在吗?
      猜你喜欢
      • 1970-01-01
      • 2019-03-29
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多