【问题标题】:How to route PUT and DELETE requests for the same url to different controller methods如何将相同 url 的 PUT 和 DELETE 请求路由到不同的控制器方法
【发布时间】:2012-06-10 19:31:59
【问题描述】:

我正在寻找这个问题的答案,发现this question,确实非常相似。但是,那里发布的解决方案似乎对我不起作用......我想知道这是否与问题的年龄有关。

给定以下网址:

/my/items/6

我希望此 URL 的 HTTP PUT 请求由一种操作方法处理,而 HTTP DELETE 请求由另一种操作方法处理。下面是我定义的路线(注意这些路线是基于一个区域,所以context 是一个AreaRegistrationContext 实例,如果这很重要的话):

context.MapRoute(null,
    "my/items/{id}",
    new { area = "AreaName", controller = "ControllerName", action = "Replace" },
    new
    {
        httpMethod = new HttpMethodConstraint("POST", "PUT"),
    }
);

context.MapRoute(null,
    "my/items/{id}",
    new { area = "AreaName", controller = "ControllerName", action = "Destroy" },
    new
    {
        httpMethod = new HttpMethodConstraint("POST", "DELETE"),
    }
);

URL 生成适用于这两种路由,但是在路由传入请求时会出现问题。只有第一个声明的路由正确映射到其各自的操作。

我挖掘了HttpMethodConstraint源代码,发现它不关心"X-HTTP-Method-Override"参数,只关心HttpContext.Request.HttpMethod

我能够使用以下自定义路由约束类解决此问题:

public class HttpMethodOverrideConstraint : HttpMethodConstraint
{
    public HttpMethodOverrideConstraint(params string[] allowedMethods) 
        : base(allowedMethods) { }

    protected override bool Match(HttpContextBase httpContext, Route route, 
        string parameterName, RouteValueDictionary values, 
        RouteDirection routeDirection)
    {
        var methodOverride = httpContext.Request
            .Unvalidated().Form["X-HTTP-Method-Override"];

        if (methodOverride == null)
            return base.Match(httpContext, route, parameterName, 
                values, routeDirection);

        return 
            AllowedMethods.Any(m => 
                string.Equals(m, httpContext.Request.HttpMethod, 
                    StringComparison.OrdinalIgnoreCase))
            &&
            AllowedMethods.Any(m => 
                string.Equals(m, methodOverride, 
                    StringComparison.OrdinalIgnoreCase))
        ;
    }
}

...以及这些路由定义:

context.MapRoute(null,
    "my/items/{id}",
    new { area = "AreaName", controller = "ControllerName", action = "Replace" },
    new
    {
        httpMethod = new HttpMethodOverrideConstraint("POST", "PUT"),
    }
);

context.MapRoute(null,
    "my/items/{id}",
    new { area = "AreaName", controller = "ControllerName", action = "Destroy" },
    new
    {
        httpMethod = new HttpMethodOverrideConstraint("POST", "DELETE"),
    }
);

我的问题:是否真的需要自定义路由约束来完成此任务? 或者有什么方法可以使其与标准 MVC 和路由类一起开箱即用?

【问题讨论】:

标签: asp.net-mvc asp.net-mvc-3 url-routing asp.net-mvc-routing


【解决方案1】:

【讨论】:

  • 是的,我的动作方法已经用 [HttpPut] 和 [HttpDelete] 修饰了。没有区别。
  • 然后去掉路由,在动作方法中添加ActionName属性。
  • 我不明白ActionNameAttribute 如何帮助操作方法选择器更好地匹配路由与操作方法。您能否指出任何其他支持您的 [ActionName(...)] 理由的参考资料?
  • 查看我在上面标记为重复的链接。
猜你喜欢
  • 2011-01-09
  • 2017-04-05
  • 2017-04-15
  • 2012-12-03
  • 1970-01-01
  • 1970-01-01
  • 2021-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多