2016-07-07 152 views
1

我使用WebAPI 2.2,基于属性的路由,我似乎无法弄清楚为什么查询字符串不工作或如何启用它们。我已经阅读过其他关于这个问题的SO问题,但他们并不完全适用于我。WebAPI 2.2,基于属性的路由和查询字符串

这里是一个非常简单的APIController:

[Route("api/HelloMessage")] 
public async Task<IHttpActionResult> Get() 
{ 
    var result = await Task.FromResult(new string[] { "Hello", "World" }).ConfigureAwait(false); 
    return Ok(result); 
} 

[Route("api/HelloMessage/{id}")] 
public async Task<IHttpActionResult> Get(int id) 
{ 
    var result = await Task.FromResult($"Hello {id}").ConfigureAwait(false); 
    return Ok(result); 
} 

(也去WebApiConfig.cs,并注释掉与MapHttpRoute创建的默认路由)

如果我http://localhost/api/HelloMessage/1打它,它效果很好。

但是,如果我用http://localhost/api/HelloMessage?id=1命中它,它会绑定到无参数版本。我哪里错了?

一个奇怪的事情:

如果我重新启用MapHttpRoute代码,然后路由作品(所以ID = 1级的路由参数化的方法?)。

我很想知道为什么这不适用于基于属性的路由。这是一个错误,还是我做错了?

这里的MapHttpRoute代码,这将使它的工作:

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

回答

1

这是由设计。默认的基于约定的路由将映射像api/{controller}/{id}这样的路由到您的无参数动作,因为{id}是可选的,如defaults: new { id = RouteParameter.Optional }所述。

使用属性路由,但您在路由过程中拥有更多的控制权和灵活性。

例如,在属性路由就可以使id可选这样

[Route("api/HelloMessage/{id?}")] 
public async Task<IHttpActionResult> Get(int id) {...} 

但是,这将导致与第一条路线有冲突,因为现在它们都匹配api/HelloMessage

如果你想要http://localhost/api/HelloMessage?id=1通过从uri中检索id来工作,那么你需要首先删除没有参数的动作,或者改变它的路径以使其不同,并使其他动作的id可选。

框架工作将匹配URI中的?id=1与参数并将值传递给参数。

+0

谢谢恩科西。我发现使用HttpMapRoute()获得的行为与使用基于属性的路由获得的行为如此不同是非常奇怪的。我想知道他们为什么使他们的功能如此不同。 – JMarsch

+0

我相信我读过的地方有不同的团队在MVC和Web Api框架上工作。他们可能会共享类似的功能,但是在不同的环境下它的开发方式不同它最终在vNext版本中合并为一个通用版本,最终成为asp dot net核心。 – Nkosi