WebAPI 2.0发布和删除路由

时间:2015-06-02 03:07:47

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

我在同一个控制器上有两个操作,路由相同,但Snmp snmp = new Snmp(new DefaultUdpTransportMapping()); USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0); SecurityModels.getInstance().addSecurityModel(usm); snmp.getUSM().addUser(securityName, new UsmUser(securityName, authProtocol, authPassphrase, privProtocol, privPassphrase)); 个要求HttpMethodPOST分开。

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时,两个端点都能正常工作。

E.g。

POST

如果我将操作分成单独的控制器,它就不再起作用了:

DELETE /api/test = endpoint1
POST /api/test = endpoint2

E.g。

[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");
    }
}

这是从框架预期的吗?

修改 确切的WebAPI包版本是:5.2.3

2 个答案:

答案 0 :(得分:6)

发生了什么

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");
    }
}

答案 1 :(得分:0)

[HttpDelete(“ DeleteEmployee / {id}”)] 公共异步任务DeleteEmployee(Guid id)