C# 有没有办法告诉路由我的默认操作名等于HTTP操作动词?

C# 有没有办法告诉路由我的默认操作名等于HTTP操作动词?,c#,asp.net-web-api,asp.net-mvc-routing,asp.net-web-api-routing,C#,Asp.net Web Api,Asp.net Mvc Routing,Asp.net Web Api Routing,我已经浏览了MSDN,没有找到答案 考虑到我的路线定义如下: config.Routes.MapHttpRoute( name: "DefaultWithActionAndID", routeTemplate: "v{version}/{controller}/{action}/{id}", defaults: null, constraints: new { action = @"[a-zA-Z]+

我已经浏览了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}
现在我有两个控制器,如下所示:

    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}
我希望能够像这样调用所有这些端点:

    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()方法,因为操作名与默认名称不匹配,并且找不到

    // 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}

我如何告诉Routing使用与我的HTTP谓词名称匹配的操作(如果在尝试按我的方式使用之前存在),您需要以下设置:

一,

二,

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

[ActionName("Something")]
public Item GetSomething(int id){}
    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" }) }
        );
三,

我不完全确定这些-您是否尝试过在上面的路由中添加默认路由:

defaults: new { id = RouteParameter.Optional }
四,

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


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

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

[ActionName("Something")]
public Item GetSomething(int id){}
    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){}

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

请包含“如果我添加了默认操作名称…”的代码。为什么不将
某物
放在另一个控制器中?更新了问题,提供了失败案例的更多详细信息。问题似乎在于路由没有额外的优先级(寻找与HTTP谓词或
{Verb}{controller}
模式匹配的方法名,就像MVC一样)。实际上,一个
{verb}
标记将是一个不错的添加。这里的问题是(就像在链接文档中一样),如果您有一个不包含
{action}
的路由,然后WebApi路由使用匹配的基本参数类型和/或任何复杂参数尝试控制器中的所有公共方法。@EricFalsken-我现在明白你的意思了。我认为一个解决办法是对路由
v{version}/{controller}/{action}/{id}
action
施加约束,这样只允许
Something
constraints=new{action=“Something”}
。但是额外的规则和(我之前不知道的)HTTPMethodConstrain并没有让我走上正确的方向。