有没有办法告诉路由我的默认操作名称等于HTTP Action Verb?

时间:2013-05-01 18:03:44

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

我在MSDN上查看了this document,无法得出答案。

考虑到我的路线定义如下:

    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谓词匹配的Action(如果存在,则在尝试使用之前)

2 个答案:

答案 0 :(得分: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){}

然后,您应该能够点击上面提到的所有端点。

答案 1 :(得分: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。

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

如果有任何改变,请告诉我。