Web Api 2.0路由 - 多个动作匹配

时间:2014-11-21 08:32:14

标签: asp.net asp.net-web-api asp.net-web-api2

我有这个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}"
            );

我收到此错误:找到了与请求匹配的多个操作....

所以我目前的“解决方法”是创建一个控制器,每个我希望公开的实用工具方法。我想我必须使用路由模板尝试一些东西。有什么想法吗?

2 个答案:

答案 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 }
    );