jQuery .ajax() 405(不允许的方法)/跨域

Posted

技术标签:

【中文标题】jQuery .ajax() 405(不允许的方法)/跨域【英文标题】:jQuery .ajax() 405 (Method Not Allowed) / Cross Domain 【发布时间】:2014-06-22 05:51:39 【问题描述】:

我在 SO 上看到了很多关于此的问题,但我找不到我的代码中缺少的内容。

我正在实施CORS,因为我不想使用JSONP

我知道这是preflighted request,我想我添加的是正确的headers

错误是该网站似乎不喜欢我的WCF,并且每次我发出请求时,即使我有Access-Control-Allow-Methods 标头,也会调用OPTION 方法。

我只想用contentType: "application/json", 给我的WCF 打一个POST 电话

WCF 是自托管的,网络应用程序位于 IIS 7.5


Chrome 显示的内容:


提琴手展示了什么


合同

<OperationContract()>
<WebInvoke(Method:="POST",
           RequestFormat:=WebMessageFormat.Json,
           ResponseFormat:=WebMessageFormat.Json,
           BodyStyle:=WebMessageBodyStyle.WrappedRequest)>
<FaultContract(GetType(ServiceFault))>
Function LookUpPerson(person As Person) _
                     As List(Of Person)

app.config

<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<bindings>
  <webHttpBinding>
    <binding name="webHttpBindingWithJsonP"
             crossDomainScriptAccessEnabled="true">
      <security mode="None" />
    </binding>
  </webHttpBinding>
</bindings>

<services>
  <service name="Project.Services.Person">  
    <endpoint address="ws"  binding="wsHttpBinding"     contract="Project.Services.Interfaces.IPublic" />   
    <endpoint address=""    binding="webHttpBinding"    contract="Project.Services.Interfaces.IPublic"
              behaviorConfiguration="jsonBehavior"/>
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8732/" />
      </baseAddresses>
    </host>
  </service>
</services>

<extensions>
  <behaviorExtensions>
    <add name="customHeaders"
         type="Project.Services.Utilities.EnableCrossOriginResourceSharingBehavior, Project.Services, Version=1.0.0.0, Culture=neutral"/>
  </behaviorExtensions>
</extensions>

<endpointBehaviors>
  <behavior name="jsonBehavior">
    <webHttp/>
    <customHeaders />
  </behavior>
</endpointBehaviors>

javascript

$.ajax(
    url: "http://192.168.0.61:8282/Project.Services.Person/LookUpPerson",
    type: "POST",
    contentType: "application/json",
    crossDomain: true,
    dataType: "json",
    data:  person: JSON.stringify(person) ,
    success: function (data) 
        // doing something
    ,
    error: function (error) 
        // doing something
    
);

根据http://enable-cors.org/server_wcf.html,在 WCF 上,我有以下处理程序

Public Class CustomHeaderMessageInspector
        Implements IDispatchMessageInspector

        Private requiredHeaders As Dictionary(Of String, String)
        Public Sub New(headers As Dictionary(Of String, String))
            requiredHeaders = If(headers, New Dictionary(Of String, String)())
        End Sub

        Public Function AfterReceiveRequest(ByRef request As System.ServiceModel.Channels.Message,
                                            channel As System.ServiceModel.IClientChannel,
                                            instanceContext As System.ServiceModel.InstanceContext) _
                                        As Object _
                                        Implements System.ServiceModel.Dispatcher.IDispatchMessageInspector.AfterReceiveRequest
            Return Nothing
        End Function

        Public Sub BeforeSendReply(ByRef reply As System.ServiceModel.Channels.Message,
                                   correlationState As Object) _
                               Implements System.ServiceModel.Dispatcher.IDispatchMessageInspector.BeforeSendReply
            Dim httpHeader = TryCast(reply.Properties("httpResponse"), HttpResponseMessageProperty)
            For Each item In requiredHeaders
                httpHeader.Headers.Add(item.Key, item.Value)
            Next
        End Sub

    End Class

Public Class EnableCrossOriginResourceSharingBehavior
        Inherits BehaviorExtensionElement
        Implements IEndpointBehavior

        Public Sub AddBindingParameters(endpoint As ServiceEndpoint, bindingParameters As System.ServiceModel.Channels.BindingParameterCollection) _
                                        Implements System.ServiceModel.Description.IEndpointBehavior.AddBindingParameters

        End Sub

        Public Sub ApplyClientBehavior(endpoint As ServiceEndpoint, clientRuntime As System.ServiceModel.Dispatcher.ClientRuntime) _
                                         Implements System.ServiceModel.Description.IEndpointBehavior.ApplyClientBehavior

        End Sub

        Public Sub ApplyDispatchBehavior(endpoint As ServiceEndpoint, endpointDispatcher As System.ServiceModel.Dispatcher.EndpointDispatcher) _
                                        Implements System.ServiceModel.Description.IEndpointBehavior.ApplyDispatchBehavior
            Dim requiredHeaders = New Dictionary(Of String, String)()

            requiredHeaders.Add("Access-Control-Allow-Origin", "*")
            requiredHeaders.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
            requiredHeaders.Add("Access-Control-Allow-Headers", "Origin, Content-Type, Accept")
            requiredHeaders.Add("Access-Control-Max-Age", "1728000")

            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(New CustomHeaderMessageInspector(requiredHeaders))
        End Sub

        Public Sub Validate(endpoint As ServiceEndpoint) _
            Implements System.ServiceModel.Description.IEndpointBehavior.Validate

        End Sub

        Public Overrides ReadOnly Property BehaviorType() As Type
            Get
                Return GetType(EnableCrossOriginResourceSharingBehavior)
            End Get
        End Property

        Protected Overrides Function CreateBehavior() As Object
            Return New EnableCrossOriginResourceSharingBehavior()
        End Function

    End Class

抱歉,帖子太长了,我想具体一点。

提前致谢。


更新

如果我使用 contentType: "text/plain",我会在 chrome 控制台上收到错误消息:

POST http://192.168.0.61:8282/Project.Services.Person/LookUpPerson 400(错误请求)

【问题讨论】:

找不到任何有用的帮助,但找到了关于 CORS 的 this 帖子,其中 OPTIONS 中发送的数据与您的不同。也许它会给你一个线索,但不确定这些是否是你写的同一件事的同义词。 @VitorCanova 谢谢,去看看。 我还没有用 WCF 做到这一点,但我用 WebAPI 做到了。当我收到 400 Bad Request 时,这是因为我在服务器上的方法中抛出了异常。您能否将调试器附加到 WCF 代码并查看请求并逐步执行? @ErikNoren 是的,我在方法上有一个断点,但它没有被触发 ***.com/questions/17333013/… 【参考方案1】:

我遇到了同样的问题,这为我解决了问题。

改变

[WebInvoke(Method = "Post")]

[WebInvoke(Method = "*")]

因为尽管您接受POST,现代浏览器将始终发送OPTIONS

【讨论】:

With "*" 它允许我访问服务器,但我收到了一个错误请求的新错误。谢谢你 一旦你走到这一步(正确处理 CORS 请求等),你仍然需要一个项目。服务方法中的一些代码如if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS") return null;,以便在飞行前调用期间不会中止(生成400响应)。

以上是关于jQuery .ajax() 405(不允许的方法)/跨域的主要内容,如果未能解决你的问题,请参考以下文章

jQuery .ajax() POST 请求抛出 405(不允许的方法)但 GET 不会

WCF REST 服务返回 405:jQuery AJAX GET 不允许的方法

带有ajax jQuery的405(不允许方法)(POST)方法

“405 方法不允许” - 使用 ASP.NET jQuery ajax POST 时

HTTP 错误 405.0 - 不允许使用 Jquery ajax get 的方法

错误 405(发出 Ajax 请求时不允许使用该方法)