WebAPI 2.0发布和删除路由
本文关键字:删除 路由 0发 WebAPI | 更新日期: 2023-09-27 17:51:24
我在同一个控制器上有两个动作,具有相同的路由,但单独的HttpMethod
要求(POST
vs DELETE
)。
[AllowAnonymous]
public class TestController : ApiController
{
[Route("~/api/test")]
[HttpDelete]
public IHttpActionResult Endpoint1()
{
return this.Ok("endpoint1");
}
[Route("~/api/test")]
[HttpPost]
public IHttpActionResult Endpoint2()
{
return this.Ok("endpoint2");
}
}
这一切都很好——当从DELETE
切换到POST
时,两个端点都可以工作。
。
DELETE /api/test = endpoint1
POST /api/test = endpoint2
如果我将动作分离到单独的控制器中,它将不再工作:
[AllowAnonymous]
public class TestController : ApiController
{
[Route("~/api/test")]
[HttpDelete]
public IHttpActionResult Endpoint1()
{
return this.Ok("endpoint1");
}
}
[AllowAnonymous]
public class TestController2 : ApiController
{
[Route("~/api/test")]
[HttpPost]
public IHttpActionResult Endpoint2()
{
return this.Ok("endpoint2");
}
}
。
DELETE /api/test = endpoint1
POST /api/test = { "Message": "The requested resource does not support http method 'POST'." }
这是框架所期望的吗?
编辑:确切的WebAPI包版本是:5.2.3
怎么回事
Web API 2.0不允许路由在两个不同的控制器上匹配。这在MVC 6(这是一个Web API组合框架)中得到了解决。
我该怎么办
首先像@woogy,你说,这不是一个非常常见的模式,所以大多数用户不应该去这里(或者当它变成RTM时转移到MVC 6)。
根本原因是路由实际上是匹配的,在一个IActionHttpMethodProvider
中定义的动词没有限制路由的匹配,它在多个控制器上匹配,因此失败。
你可以在路由上定义一个约束,这样就可以得到一个更简洁的API。
我们开始吧
定义动词约束
这将限制路由只匹配预定义的动词,所以它不会匹配其他控制器。
public class VerbConstraint : IHttpRouteConstraint
{
private HttpMethod _method;
public VerbConstraint(HttpMethod method)
{
_method = method;
}
public bool Match(HttpRequestMessage request,
IHttpRoute route,
string parameterName,
IDictionary<string, object> values,
HttpRouteDirection routeDirection)
{
// Note - we only want to constraint on the outgoing path
if (routeDirection == HttpRouteDirection.UriGeneration ||
request.Method == _method)
{
return true;
}
return false;
}
}
为新属性定义一个抽象基类
public abstract class VerbRouteAttribute : RouteFactoryAttribute, IActionHttpMethodProvider
{
private string _template;
private HttpMethod _method;
public VerbRouteAttribute(string template, string verb)
: base(template)
{
_method = new HttpMethod(verb);
}
public Collection<HttpMethod> HttpMethods
{
get
{
var methods = new Collection<HttpMethod>();
methods.Add(_method);
return methods;
}
}
public override IDictionary<string, object> Constraints
{
get
{
var constraints = new HttpRouteValueDictionary();
constraints.Add("verb", new VerbConstraint(_method));
return constraints;
}
}
}
这个类合并了3个东西1. 带路由模板的路由属性2. 对路由应用动词路由约束3.指定操作方法选择器,以便系统的其余部分(如帮助页面)像[HttpPost]
/[HttpDelete]
现在让我们定义实现
public class PostRouteAttribute : VerbRouteAttribute
{
public PostRouteAttribute(string template) : base(template, "POST")
{
}
}
public class DeleteRouteAttribute : VerbRouteAttribute
{
public DeleteRouteAttribute(string template) : base(template, "DELETE")
{
}
}
你可以看出这些都是非常琐碎的,只是让这些属性在你的代码中使用得更流畅。
最后让我们应用新属性(并删除方法属性)
[AllowAnonymous]
public class TestController : ApiController
{
[DeleteRoute("api/test")]
public IHttpActionResult Endpoint1()
{
return this.Ok("endpoint1");
}
}
[AllowAnonymous]
public class TestController2 : ApiController
{
[PostRoute("api/test")]
public IHttpActionResult Endpoint2()
{
return this.Ok("endpoint2");
}
}
[HttpDelete("DeleteEmployee/{id}")]public async Task DeleteEmployee(Guid id)