3

我在 MSDN 上浏览了这个文档,但无法找到答案。

考虑到我有这样定义的路线:

    config.Routes.MapHttpRoute(
        name: "DefaultWithActionAndID",
        routeTemplate: "v{version}/{controller}/{action}/{id}",
        defaults: null,
        constraints: new {
            action = @"[a-zA-Z]+",
            id = @"\d+"
        }
    );

    config.Routes.MapHttpRoute(
        name: "DefaultWithID",
        routeTemplate: "v{version}/{controller}/{id}",
        defaults: null,
        constraints: new {
            id = @"\d+"
        }
    );

    config.Routes.MapHttpRoute(
        name: "DefaultWithoutActionOrId",
        routeTemplate: "v{version}/{controller}",
        defaults: null,
    );

现在我有两个看起来像这样的控制器:

public class ItemController:ApiController{
    [HttpGet]
    public Item Get(int id){}

    [HttpGet]
    public Item GetSomething(int id){}

    [HttpPut]
    public Item Put(Item newItem){}
}

public class AnotherController:ApiController{
    [HttpPut]
    public HttpResponseMessage Put(Something item){}
}

我希望能够像这样调用所有这些端点:

GET /api/Item/344
GET /api/Item?id=344
GET /api/Item/Something/2334
GET /api/Item/Something?id=2334
PUT /api/Item     body={newItem}
PUT /api/Another  body={newSomething}

这将起作用,但前提是我将“Get”添加为默认操作名称。如果我没有在我的路由中指定默认操作名称,那么它会抱怨多个匹配的操作名称。如果我确实添加了默认操作名称,那么我无法在没有错误的情况下将 PUT 调用到 Put() 方法,因为操作名称与默认值不匹配并且找不到。

    // Will work in some cases, but not all
    config.Routes.MapHttpRoute(
        name: "DefaultWithID",
        routeTemplate: "v{version}/{controller}/{id}",
        defaults: new {
            action="Get",
            id=RouteParameters.Optional
        },
        constraints: new {
            id = @"\d+"
        }
    );

    // Works
GET /api/Item/344
GET /api/Item?id=344
GET /api/Item/Something/2334
GET /api/Item/Something?id=2334

// Doesn't work
PUT /api/Item     body={newItem}
PUT /api/Another  body={newSomething}

如果在尝试使用之前存在,我如何告诉路由使用名称与我的 HTTP 动词匹配的操作

4

2 回答 2

3

如果您按如下方式定义路线:

    config.Routes.MapHttpRoute(
            name: "DefaultWithActionAndID",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new {action = @"[a-zA-Z]+", id = @"\d*" }
            );

    config.Routes.MapHttpRoute(
        name: "DefaultWithID",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { action = "GET", id = RouteParameter.Optional },
        constraints: new { id = @"\d*", httpMethod = new HttpMethodConstraint(new string[] { "GET" }) }
        );

    config.Routes.MapHttpRoute(
        name: "DefaultWithoutActionOrId",
        routeTemplate: "api/{controller}",
        defaults: new { action = "PUT" },
        constraints: new { httpMethod = new HttpMethodConstraint(new string[] { "PUT" }) }
        );

并将ActionName属性放在您的 GetSomething 方法上,如下所示:

[ActionName("Something")]
public Item GetSomething(int id){}

然后,您应该能够访问上述所有端点。

于 2013-05-02T07:57:42.603 回答
0

在我看来,您需要以下设置:

1.

/api/Item/344
{controller}/{id}

2.

/api/Item/Something/2334
{controller}/{action}/{id}

并按如下方式装饰“GetSomething”方法:

[ActionName("Something")]
public Item GetSomething(int id){}

3.

/api/Item?id=344
/api/Item/Something?id=2334

我不完全确定这些 - 您是否尝试过为上述路由添加默认值:

defaults: new { id = RouteParameter.Optional }

4.

PUT如果应用#3,我希望能正常工作

让我知道这是否会改变任何事情。

于 2013-05-01T20:12:52.910 回答