的X HTTP的方法,覆盖给予NOTFOUND(404)上的ASP.NET Web API [英] X-HTTP-Method-Override gives NotFound (404) on ASP.NET Web API

查看:118
本文介绍了的X HTTP的方法,覆盖给予NOTFOUND(404)上的ASP.NET Web API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现以下<描述的步骤A HREF HTTP方法覆盖=htt​​p://www.asp.net/web-api/overview/working-with-http/http-message-handlers相对= nofollow的>此处。基本上,我创建一个DelegatingHandler,类似以下内容,将其添加为消息处理程序上的Application_Start

公共类MethodOverrideHandler:DelegatingHandler
{
    只读的String [] = _methods {删除,HEAD,PUT};
    常量字符串_header =X-HTTP-方法-覆盖;    保护覆盖任务&LT; Htt的presponseMessage&GT; SendAsync(
        HTT prequestMessage请求的CancellationToken的CancellationToken)
    {
        //检查HTTP POST与X-HTTP-方法,覆盖头部。
        如果(request.Method == HttpMethod.Post&放大器;&安培; request.Headers.Contains(_header))
        {
            //检查头值是在我们的方法列表。
            VaR方法= request.Headers.GetValues​​(_header).FirstOrDefault();
            如果(_methods.Contains(方法,StringComparer.InvariantCultureIgnoreCase))
            {
                //改变请求方法。
                request.Method =新列举HTTPMethod(法);
            }
        }
        返回base.SendAsync(请求的CancellationToken);
    }
}

我有我的控制器定义了以下方法:


  • 人/ {ID} ,GET

  • 人/ {ID} ,PUT

  • 人/ {ID} ,删除

我可以叫他们通过自己的本土的方法和他们的工作预期。然而,当我试着打电话给他们通过POST,用删除或PUT发送 X-HTTP-方法,覆盖头,它给出了一个未找到(404)错误。补充一点,当它给这个错误,它从来没有达到这一点很重要的 MethodOverrideHandler - 我已经把断点是从不打;它命中断点,当我打电话正常DELETE和PUT。

我甚至尝试添加另一种方法:


  • 人/ {ID} ,POST

当我这样做,我得到的不允许的方法(405)代替。

我以为消息处理程序进行路由和控制调度员之前运行。这是为什么给我404?

我不认为这是相关的,但我不使用默认的Web API路由。相反,我使用的是自定义属性,分配给每个方法映射,如:

routes.MapHttpRoute(
    的String.Format({0} _ {1},operation.Name,service.ServiceId)
    的String.Format({0} / {1},service.Route preFIX,routeTemplateAttribute.Template)
    默认值,
    新{列举HTTPMethod = GetHttpMethodConstraint(操作)});

[HttpDelete,RouteTemplate(人/(编号))
公众的Htt presponseMessage deletePerson的(字符串ID)
{
    // ...
}

修改 GetHttpMethodConstraint code是低于

私有静态HttpMethodConstraint GetHttpMethodConstraint(MethodInfo的MethodInfo的)
{
    VAR methodResolver = HttpMethodResolver.FromMethodInfo(MethodInfo的);
    返回新HttpMethodConstraint(methodResolver.Resolve());
}

内部类HttpMethodResolver
{
    私人MethodInfo的_MethodInfo;    私人HttpMethodResolver(MethodInfo的MethodInfo的)
    {
        _MethodInfo = MethodInfo的;
    }    公共静态HttpMethodResolver FromMethodInfo(MethodInfo的MethodInfo的)
    {
        返回新HttpMethodResolver(MethodInfo的);
    }    公共字符串[]解决()
    {
        VAR动词=新的List&LT;&列举HTTPMethod GT;();        如果(MethodHasAttribute&LT; HttpGetAttribute&GT;())
        {
            verbs.Add(HttpMethod.Get);
        }
        否则,如果(MethodHasAttribute&LT; HttpPostAttribute&GT;())
        {
            verbs.Add(HttpMethod.Post);
        }
        否则,如果(MethodHasAttribute&LT; HttpDeleteAttribute&GT;())
        {
            verbs.Add(HttpMethod.Delete);
        }
        否则,如果(MethodHasAttribute&LT; HttpPutAttribute&GT;())
        {
            verbs.Add(HttpMethod.Put);
        }
        其他
        {
            抛出新ServiceModelException(HTTP方法属性应使用);
        }        返回verbs.Select(V =&GT; v.Method).ToArray();
    }    私人布尔MethodHasAttribute&LT; T&GT;()其中T:属性
    {
        返回GetMethodAttribute&LT; T&GT;()!= NULL;
    }    私人ŧGetMethodAttribute&LT; T&GT;()其中T:属性
    {
        返回_methodInfo.GetCustomAttributes(typeof运算(T),真).FirstOrDefault()为T;
    }
}


解决方案

我试图重现你的错误,但我不能。在这里,你可以下载我简单的项目,消息处理程序: HTTPS://dl.dropbox。 COM / U / 20568014 / WebApplication6.zip

我想指出的是执行的操作选择逻辑之前运行的消息处理程序。所以,你的情况,可能是别的东西,因为出现问题导致的问题,我想你应该看看你的其他消息处理,消息处理程序的注册code等原因在于消息处理程序永远不会运行的事实。

另外,我觉得你的 IRouteConstraint 实施 GetHttpMethodConstraint ,看起来可疑我。

下面是我的注册code的消息处理程序:

 保护无效的Application_Start(对象发件人,EventArgs的发送){    无功配置= GlobalConfiguration.Configuration;
    config.Routes.MapHttpRoute(
        DefaultHttpRoute
        API / {}控制器/(编号),
        新{ID = RouteParameter.Optional}
    );    config.MessageHandlers.Add(新MethodOverrideHandler());
}

I am trying to implement HTTP method override following the steps described here. Basically, I am creating a DelegatingHandler, similar to the following, and adding it as a message handler on Application_Start.

public class MethodOverrideHandler : DelegatingHandler      
{
    readonly string[] _methods = { "DELETE", "HEAD", "PUT" };
    const string _header = "X-HTTP-Method-Override";

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Check for HTTP POST with the X-HTTP-Method-Override header.
        if (request.Method == HttpMethod.Post && request.Headers.Contains(_header))
        {
            // Check if the header value is in our methods list.
            var method = request.Headers.GetValues(_header).FirstOrDefault();
            if (_methods.Contains(method, StringComparer.InvariantCultureIgnoreCase))
            {
                // Change the request method.
                request.Method = new HttpMethod(method);
            }
        }
        return base.SendAsync(request, cancellationToken);
    }
}

I have the following methods defined on my Controller:

  • persons/{id}, GET
  • persons/{id}, PUT
  • persons/{id}, DELETE

I can call them through their "native" methods and they work as expected. However, when I try to call them through a POST, sending the X-HTTP-Method-Override header with "DELETE" or "PUT", it gives a Not Found (404) error. It is important to add that, when it gives this error, it never reaches the MethodOverrideHandler -- I have put a Breakpoint which is never hit; it does hit the Breakpoint when I call normal DELETE and PUT.

I even tried adding another method:

  • persons/{id}, POST

When I do this, I get a Method Not Allowed (405) instead.

I thought that message handlers were run BEFORE the Routing and Controller dispatchers. Why is this giving me 404?

I do not think this is related, but I am not using default Web API routing. Instead, I am mapping using a custom Attribute, assigned to each method, like this:

routes.MapHttpRoute(
    String.Format("{0}_{1}", operation.Name, service.ServiceId),
    String.Format("{0}/{1}", service.RoutePrefix, routeTemplateAttribute.Template),
    defaults,
    new { httpMethod = GetHttpMethodConstraint(operation) });

[HttpDelete, RouteTemplate("persons/{id}")]
public HttpResponseMessage DeletePerson(string id)
{
    // ...
}

EDIT: GetHttpMethodConstraint code is below.

private static HttpMethodConstraint GetHttpMethodConstraint(MethodInfo methodInfo)
{
    var methodResolver = HttpMethodResolver.FromMethodInfo(methodInfo);
    return new HttpMethodConstraint(methodResolver.Resolve());
}

internal class HttpMethodResolver
{
    private MethodInfo _methodInfo;

    private HttpMethodResolver(MethodInfo methodInfo)
    {
        _methodInfo = methodInfo;
    }

    public static HttpMethodResolver FromMethodInfo(MethodInfo methodInfo)
    {
        return new HttpMethodResolver(methodInfo);
    }

    public string[] Resolve()
    {
        var verbs = new List<HttpMethod>();

        if (MethodHasAttribute<HttpGetAttribute>())
        {
            verbs.Add(HttpMethod.Get);
        }
        else if (MethodHasAttribute<HttpPostAttribute>())
        {
            verbs.Add(HttpMethod.Post);
        }
        else if (MethodHasAttribute<HttpDeleteAttribute>())
        {
            verbs.Add(HttpMethod.Delete);
        }
        else if (MethodHasAttribute<HttpPutAttribute>())
        {
            verbs.Add(HttpMethod.Put);
        }
        else
        {
            throw new ServiceModelException("HTTP method attribute should be used");
        }

        return verbs.Select(v => v.Method).ToArray();
    }

    private bool MethodHasAttribute<T>() where T : Attribute
    {
        return GetMethodAttribute<T>() != null;
    }

    private T GetMethodAttribute<T>() where T : Attribute
    {
        return _methodInfo.GetCustomAttributes(typeof(T), true).FirstOrDefault() as T;
    }
}

解决方案

I have tried to reproduce your error but I wasn't able to. Here, you can download my simple project with your message handler: https://dl.dropbox.com/u/20568014/WebApplication6.zip

I would like to point out that message handlers run before the action selection logic is performed. So, in your case, probably something else causes the problem and I think you should look at your other message handlers, your message handler's registration code, etc because the problem occurs due to the fact that your message handler never runs.

Also, I think your IRouteConstraint implementation, GetHttpMethodConstraint, looks suspicious to me.

Here is my registration code for the message handler:

protected void Application_Start(object sender, EventArgs e) {

    var config = GlobalConfiguration.Configuration;
    config.Routes.MapHttpRoute(
        "DefaultHttpRoute",
        "api/{controller}/{id}",
        new { id = RouteParameter.Optional }
    );

    config.MessageHandlers.Add(new MethodOverrideHandler());
}

这篇关于的X HTTP的方法,覆盖给予NOTFOUND(404)上的ASP.NET Web API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆