带PUT的ASP.NET Web API路由
我正在尝试为我认为非常简单的事情设置WebAPI路由。然而,Web API中的路由似乎与不同的HTTP谓词不一致。假设我有这个控制器和这些动作带PUT的ASP.NET Web API路由,asp.net,asp.net-mvc,asp.net-web-api-routing,Asp.net,Asp.net Mvc,Asp.net Web Api Routing,我正在尝试为我认为非常简单的事情设置WebAPI路由。然而,Web API中的路由似乎与不同的HTTP谓词不一致。假设我有这个控制器和这些动作 public class AvalancheController : ApiControllerBase { // GET api/avalanche public IEnumerable<Avalanche> Get() {} // GET api/avalanche/5 public Avalanche
public class AvalancheController : ApiControllerBase
{
// GET api/avalanche
public IEnumerable<Avalanche> Get() {}
// GET api/avalanche/5
public Avalanche Get(int id) {}
// GET api/avalanche/ActionTest/5
[ActionName("ActionTest")]
public Avalanche GetActionTest(int id) {}
// GET api/avalanche/ActionTest/2
[ActionName("ActionTest2")]
public Avalanche GetActionTest2(int id) {}
// POST api/avalanche
public void Post([FromBody]Avalanche value) {}
// PUT api/avalanche/5
public void Put(int id, [FromBody]Avalanche value) {}
// PUT api/avalanche/test/5
[ActionName("Test")]
public void PutTest(int id, [FromBody]Avalanche value) {}
// DELETE api/avalanche/5
public void Delete(int id) {}
}
最后,我定义了以下路线
config.Routes.MapHttpRoute(
name: "ActionRoutes",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: new
{
controller = "Avalanche",
action = "(ActionTest|ActionTest2|Test)"
}
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
GET api/Avalanche/ActionTest/{id}
GET api/Avalanche/ActionTest2/{id}
PUT api/Avalanche/Test/{id}
GET api/Avalanche
POST api/Avalanche
DELETE api/Avalanche/{id}
为什么默认的PUT路由没有被拾取?默认GET和默认PUT的路由有什么不同?我尝试过用各种可以想象的方式来装饰函数,但我得到了同样的结果
我主要想知道如何获取要拾取的默认PUT路由。如果您对如何修改这些路由有任何建议,这样我就不必为每个控制器指定一个路由来指定操作名称,这也将非常棒
谢谢
伊恩
编辑:今天早上我注意到以下路线也没有定义
GET api/Avalanche/{id}
很高兴你找到了解决问题的办法。但我会根据我在REST服务中的学习情况提供反馈。RESTWebService的想法是将每个url解析为一个资源(或者可能是实体),并根据HttpVerb决定操作。在本例中,您有三个GET操作,这些操作与您的修改配合得很好 但我认为,控制器也可以重新安排为具有单一GET操作和单一责任,从而提高可维护性。例如: 雪崩控制器
public class AvalancheController : ApiControllerBase
{
public IEnumerable<Avalanche> GET()
{
}
public void POST(Avalanche avalanche)
{
}
}
public class AvalancheDetailsController : ApiControllerBase
{
public Avalanche GET(int id)
{
}
public int PUT(int id)
{
}
public int DELETE(int id)
{
}
}
可以假设它处理单个雪崩,下面是要定义的操作
GET:返回单个雪崩POST:未使用
PUT:更新单个雪崩
删除:删除单个雪崩
现在我假设我们对控制器有了明确的区分。在您提到的OP中,可以有不同的GET操作,但它只返回单个
Avalanche
。因此,我将更改GET方法,以对象作为输入,并检查值,即
public class AvalanceRequest
{
public int? Id {get;set;}
public string Name {get;set;}
}
public class AvalancheDetailsController : ApiControllerBase
{
public Avalanche GET(AvalanceRequest request)
{
//write business logic based on parameters
if(request.Id.HasValue)
//return avalanche;
if(request.Name.IsNullOrEmpty())
//return avalanche
}
//other methods
}
在处理URL时,我并没有真正使用WebAPI,而是尝试使用ServiceStack开发REST服务。它允许附加独立于控制器名称的url
Urlapi/Avalanche-->AvalancheController(基于HttpVerb调用操作)
api/Avalanche/Id-->AvalancheDetailsController(基于HttpVerb调用操作) 我不知道是否可以在WebAPI中同样附加url,否则您将使用默认配置并通过调用。api/雪崩和api/雪崩详细信息/id
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
很抱歉发了这么长的帖子,希望有意义。有趣的方法。我得好好考虑一下。这是我的第一个RESTAPI,所以我当然愿意接受所有的想法。我一直遵循的想法是,容器将描述所操作的主要数据类型,并使用操作来描述更困难的操作。例如,如果需要返回雪崩项目数组(如GetAvalanchCreatedWithinTerrange())的更复杂的查找,该怎么办?“每个动词有一个功能的想法很快就被打破了。”IanLee,我还在学习。对,实施前想一想比较好。对于你的问题,因为它是IEnumerable上的一个过滤器