加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – WebAPI 2.0发布和删除路由

发布时间:2020-12-15 08:46:58 所属栏目:百科 来源:网络整理
导读:我在同一个控制器上有两个动作,具有相同的路由,但是单独的HttpMethod要求(POST与DELETE). [AllowAnonymous]public class TestController : ApiController{ [Route("~/api/test")] [HttpDelete] public IHttpActionResult Endpoint1() { return this.Ok("endp
我在同一个控制器上有两个动作,具有相同的路由,但是单独的HttpMethod要求(POST与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");
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读