WebAPI - 属性路由使用WebAPI Cors中断DELETE?

时间:2013-07-23 00:58:41

标签: .net routing asp.net-web-api cors

使用以下路线:

routes.MapHttpRoute(
           name: "Set",
           routeTemplate: "api/set/{id}",
           defaults: new { controller = "Set", id = RouteParameter.Optional }
           );

映射到以下方法:

    [HttpDelete]
    [AcceptVerbs("DELETE")]
    public HttpResponseMessage DeleteSet(int id)
    {
     //stuff
    }

我可以通过此调用删除集:

   DELETE api/set/1

enter image description here

但如果我删除上述路由以支持属性路由:

    [HttpDelete("api/set/{id}")]
    [AcceptVerbs("DELETE")]
    public HttpResponseMessage DeleteSet(int id)
    {
     //stuff
    }

并添加到我的配置中:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute("http://localhost:11089", "*", "*");
        config.MapHttpAttributeRoutes(); // new, working with stuff other than delete
        config.EnableCors(cors);  // already working, not new
     }
 }

由于CORS问题导致同一请求中断:

enter image description here

在图像中,您会看到一个查询参数,但这适用于仅具有ID的简单DELETE查询。到底他妈发生了什么?我们已经投入了大量时间进行属性映射,因为DELETE不起作用,所以必须回滚所有东西。

这是DELETE的另一个实例,它打破了一个简单的id:

enter image description here

以上来自此请求:

var options = {
            url: apiEndpoint + 'card/' + id,
            type: 'DELETE',
            dataType: 'json',
            xhrFields: {
                withCredentials: true
            }
        };

        return $.ajax(options)

更新 如果我们将所有删除方法都加上'[AcceptVerbs("OPTIONS")]',那么它就可以了。看起来不那么优雅,如果有人有权威的答案我想留下这个。

1 个答案:

答案 0 :(得分:4)

您似乎遇到了将CORS与属性路由一起使用的已知问题。以下问题目前正在跟踪。

http://aspnetwebstack.codeplex.com/workitem/954

这是由于属性路由在生成路由时创建的httpmethod约束。

变通办法(这里有几个选项):

  • 使用HttpOptions动词属性显式修饰动作,以便添加此约束并且您的OPTIONS请求可以通过。

  • 创建一个自定义路径构建器,将OPTIONS添加到所有路径(如果您愿意,可以修改此行为)。一些示例代码:

    config.MapHttpAttributeRoutes(new CustomRouteBuilder());
    
    public class CustomRouteBuilder : HttpRouteBuilder
    {
        public override IHttpRoute BuildHttpRoute(HttpRouteValueDictionary defaults, HttpRouteValueDictionary constraints, 
                                                    string routeTemplate)
        {
            HttpMethodConstraint currentMethodConstraint = (HttpMethodConstraint)constraints["httpMethod"];
            List<HttpMethod> methods = currentMethodConstraint.AllowedMethods.ToList();
            if (!methods.Contains(HttpMethod.Options))
            {
                methods.Add(HttpMethod.Options);
            }
    
            HttpMethodConstraint newMethodConstraint = new HttpMethodConstraint(methods.ToArray());
            HttpRouteValueDictionary newConstraints = new HttpRouteValueDictionary();
            newConstraints["httpMethod"] = newMethodConstraint;
            return base.BuildHttpRoute(defaults, newConstraints, routeTemplate);
        }
    }