我有这个WebAPI控制器,有两种方法。这个控制器更像是一个实用型控制器,而不是真正专注于一种类型的实体,就像大多数示例和样板模板一样。无论如何,我的两种方法是这样的:
// api/Custom/SayHello
[HttpGet]
public async Task<string> SayHello()
{
return await Task.FromResult("Hello World Async").ConfigureAwait(false);
}
// api/Custom/SayFloat
[HttpGet]
public async Task<float> SayFloat()
{
return await Task.FromResult(1000.0f).ConfigureAwait(false);
}
我已经完成了很多路由模板组合,我的最新组合就是:
config.Routes.MapHttpRoute("DefaultApiWithId",
"Api/{controller}/{id}",
new { id = RouteParameter.Optional });
/* ----- this is trying to match my utility controller and its actions ----- */
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "Api/{controller}/{action}"
);
我收到此错误:找到了与请求匹配的多个操作....
所以我目前的“解决方法”是创建一个控制器,每个我希望公开的实用工具方法。我想我必须使用路由模板尝试一些东西。有什么想法吗?
答案 0 :(得分:4)
这个问题的另一个答案是正确的。但是,我想提供一个我喜欢的替代方案Attribute Routing。
Web API的第一个版本使用基于约定的路由。在这种类型的路由中,您可以定义一个或多个路由模板,这些模板基本上是参数化字符串。当框架收到请求时,它会根据路由模板匹配URI。
另一方面,使用属性路由,您可以使用属性修饰控制器和操作,从而实现更灵活的路由方案。
[Route("api/custom")]
public class CustomController : ApiController
...
// api/Custom/SayHello
[Route("SayHello")]
[HttpGet]
public async Task<string> SayHello()
{
return await Task.FromResult("Hello World Async").ConfigureAwait(false);
}
// api/Custom/SayFloat
[Route("SayFloat")]
[HttpGet]
public async Task<float> SayFloat()
{
return await Task.FromResult(1000.0f).ConfigureAwait(false);
}
答案 1 :(得分:1)
Web API将按照找到的顺序匹配路线,因此您需要更改路线的顺序:
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "Api/{controller}/{action}"
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routetemplate "Api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
虽然有一个警告,但这将停止使用id参数的defaultapi路由。我可能最好明确声明你的控制器:
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "Api/Custom/{action}",
defaults: new { controller = "Custom" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routetemplate "Api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);