【问题标题】:Web.API MapHttpRoute parametersWeb.API MapHttpRoute 参数
【发布时间】:2013-02-08 01:15:17
【问题描述】:

我的 Web.API 路由出现问题。我有以下两条路线:

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

config.Routes.MapHttpRoute(
    name: "MethodTwo",
    routeTemplate: "api/{controller}/{action}/{directory}/{report}",
    defaults: new { directory = RouteParameter.Optional, report = RouteParameter.Optional }
);

在我的控制器中这两种方法:

[HttpGet]
[ActionName("methodone")]
public string MethodOne(string id, string type)
{
    return string.Empty;
}

[HttpGet]
[ActionName("methodtwo")]
public string MethodTwo(string directory, string report)
{
    return string.Empty;
}

这两个人似乎不能并存。如果我在 WebApiConfig 中注释掉 MethodOne 路由,则 MethodTwo 路由有效。评论 MethodTwo 路线允许 MethodOne 工作。不加注释,MethodOne 有效,但 MethodTwo 无效。

我希望对这两种方法都使用一条路由,那么它们似乎必须具有相同的参数名称。谁编写具有通用参数名称的方法?坏的。我真的不希望我的方法具有相同的参数名称(如 p1、p2、p3),所以我想我可以为新方法创建一个路由。但即使这样似乎也行不通。

我真的很想念 WCF 休息时的 WebGet(UriTemplate="")

我有一个控制器,它有很多方法,有些有 1、2、3 甚至更多参数。我不敢相信我不能在 MapHttpRoute 方法中使用有意义的参数名称。

我可以将这些内容完全注释掉并使用WebGet()……但在我到达那里之前,我想看看我是否遗漏了什么。

【问题讨论】:

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


    【解决方案1】:

    您看到此问题的原因是您的第一个路由将匹配两个请求。 URL 中的 id 和 type 标记将匹配两个请求,因为当路由运行时,它会尝试解析 URL 并将每个段与您的 URL 匹配。

    因此,您的第一条路线将愉快地匹配两个请求,如下所示。

    ~/methodone/1/mytype => action = methodone, id = 1, and type = mytype
    ~/methodtwo/directory/report => action = methodtwo, id = directory, and type = report
    

    要解决这个问题,您应该使用类似的路由

    config.Routes.MapHttpRoute(
        name: "MethodOne",
        routeTemplate: "api/{controller}/methodone/{id}/{type}",
        defaults: new { id = RouteParameter.Optional, type = RouteParameter.Optional }
    );
    
    config.Routes.MapHttpRoute(
        name: "MethodTwo",
        routeTemplate: "api/{controller}/methodtwo/{directory}/{report}",
        defaults: new { directory = RouteParameter.Optional, report = RouteParameter.Optional }
    );
    

    即使您使用 WebGet,您也可能需要做一些类似的事情来消除我认为的这两种方法的歧义。

    【讨论】:

    • 我会试一试,让你知道它是否有效。令人遗憾的是,我现在需要为每个想要正确命名参数的方法执行此操作。走 Youssef 链接或 WebGet 的路线可能会更容易——那些工作更少,更清晰。
    • 所以这确实有效 - 谢谢。但是,恕我直言,这是废话。不是您的解决方案,而是整个路线的方法。我要么必须为每个方法都有一个路由,这不是很好,要么使用旧的 WebGet 或属性中的新 GET - 并注释掉所有路由的东西。我承认我不是一个庞大的网络人,所以也许我正在做一些非标准的事情,但与 UriTemplate 相比,这似乎是一种极其有限的方法。
    • 我听到了。我们为 Web API v1 支持的路由仅适用于基于 HTTP 动词的路由或仅基于操作的路由。但是,如果您有一个基于 HTTP 动词和基于动作的动作,它就不能很好地工作,因为我们正在努力在下一版本中改进这个故事。
    • 我听到了。我们为 Web API v1 支持的路由分别适用于基于 HTTP 动词的路由或基于操作的路由。但是,它并不能很好地工作,因为我们正在努力改进故事,请参阅aspnetwebstack.codeplex.com/workitem/184
    【解决方案2】:

    来自http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection

    您还可以提供约束,以限制 URI 段如何 匹配占位符:

    constraints: new { id = @"\d+" } // 仅当 "id" 为 1 或 更多的数字。

    将此约束添加到“MethodOne”(api/{controller}/{action}/{id}/{type})意味着它仅在 {id} 是数字时匹配数字,否则它将匹配“MethodTwo” ("api/{controller}/{action}/{directory}/{report}")。

    【讨论】:

      【解决方案3】:

      您可以选择在查询字符串中传递参数,例如 /MethodTwo?directory=a&report=b,但如果您希望它们显示在路径中,这看起来是基于属性的路由的理想选择。 Filip 在这里有一篇很棒的帖子:

      http://www.strathweb.com/2012/05/attribute-based-routing-in-asp-net-web-api/

      【讨论】:

      • 我确实尝试过这个......似乎还可以,只是从 WCF 中的 UriTemplate 转到不太热的东西,然后不得不使用单独的包,这有点令人沮丧。 :P 我也可以使用旧的 WebGet 东西,但是我必须为每个方法显式地映射整个路由。我希望新系统更加灵活。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-23
      • 1970-01-01
      • 2012-08-16
      • 1970-01-01
      • 1970-01-01
      • 2016-03-28
      相关资源
      最近更新 更多