【问题标题】:Is there a way to tell routing that my default action name is equal to the HTTP Action Verb?有没有办法告诉路由我的默认操作名称等于 HTTP 操作动词?
【发布时间】:2013-04-25 18:43:20
【问题描述】:

我在 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 动词匹配的操作

【问题讨论】:

  • 请包含“如果我添加默认操作名称...”的代码。
  • 为什么不把Something放到另一个控制器里?
  • 用失败案例的更多细节更新了问题。问题似乎是路由没有额外的优先级(寻找与 HTTP 动词或 {verb}{controller} 模式匹配的方法名称,就像 MVC 一样)。实际上,{verb} 令牌将是一个很好的补充。

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


【解决方案1】:

如果您将路线定义如下:

    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){}

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

【讨论】:

  • 差不多。但是额外的规则和(我之前不知道的)HttpMethodConstraint 让我朝着正确的方向前进。
【解决方案2】:

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

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 能够正常工作

如果这有什么改变,请告诉我。

【讨论】:

  • 这里要注意的是(就像在链接文档中一样)如果您有一个不包含 {action} 的路由,那么 WebApi Routing 会尝试控制器中的所有公共方法与匹配的原始参数类型和/或任何复杂的参数。
  • @EricFalsken - 我现在明白你的意思了。我认为一种解决方法是对路由v{version}/{controller}/{action}/{id}action 施加约束,以便只允许Somethingconstraints = new {action = "Something"}
猜你喜欢
  • 2020-03-27
  • 1970-01-01
  • 1970-01-01
  • 2018-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多