簡體   English   中英

自托管 WCF REST 服務 JSON POST 方法不允許

[英]Self Hosted WCF REST service JSON POST Method Not Allowed

到目前為止,我已經在 inte.net 上看到了數千個這樣的“WCF”問題,但我開始認為這是不可能的。 請有人告訴我我錯了...

背景:我正在使用自托管 WCF 服務(因此 Global.asax.cs 在這里無濟於事)。 端點也是以編程方式定義的。 合同用 WebInvoke(Method="POST") 修飾,我正在調用該服務的 JQuery。

預檢最初適用於 OPTIONS 方法,但 POST 方法失敗並顯示 405 Method Not Allowed。 GET 函數也能完美運行。

我已經搜索了 inte.net 並進行了大約一個月的試驗,但它就是不動。 該服務已經對另一個通過 TCP 調用它的客戶做出了很好的響應......請一些天才幫助我。 謝謝

PS:我認為 POST 響應真的很奇怪,是 Allow: OPTIONS ......當然不應該在那里?

CORS

    public class CORSEnablingBehavior : BehaviorExtensionElement, IEndpointBehavior
    {
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
    {
        var requiredHeaders = new Dictionary<string, string>();

        requiredHeaders.Add("Access-Control-Allow-Origin", "*");
        requiredHeaders.Add("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
        requiredHeaders.Add("Access-Control-Allow-Headers", "Origin, Cache-Control, Connection, Pragma, Content-Length, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, User-Agent");

        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CORSHeaderInjectingMessageInspector(requiredHeaders));
    }

應用配置

  <system.serviceModel>
<behaviors>
  <endpointBehaviors>
    <behavior name="SOAPDemoEndpointBehavior">
    </behavior>
    <behavior>
      <webHttp/>
      <crossOriginResourceSharingBehavior/>
    </behavior>
  </endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<extensions>
  <behaviorExtensions>
    <add name="crossOriginResourceSharingBehavior" type="Application.Host.CORSEnablingBehavior, Application.Host, Version=1.0.0.0, Culture=neutral"/>
  </behaviorExtensions>
</extensions>
<bindings>
  <basicHttpBinding>
    <binding name="OrdersMappingSoap"/>
  </basicHttpBinding>

  <!--2015-08-26-->
  <webHttpBinding>
    <binding name="webHttpBindingWithJson"
          crossDomainScriptAccessEnabled="true" />
  </webHttpBinding>

界面

[OperationContract(Name = "Relational")] 
[FaultContract(typeof(ValidationFault))]
[WebInvoke(Method = "POST", UriTemplate = "GetCustomerRelational", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
CustomerFullModel GetCustomerRelational(int clientHandle, object customerID, bool loadRelationalData);

JQuery

 jQuery.ajax({ crossDomain: true, type: "POST", contentType: "application/json", url: "http://localhost:8086/CustomerService/rest/GetCustomerRelational/", data: JSON.stringify({ "clientHandle": 1824, "customerID": "ABB029", "loadRelationalData": true }), dataType: "json", success: function(result) { console.log("Success..."); document.getElementById("lblResponse").innerHTML = "Success: " + JSON.stringify(result.NormalResult); }, error: function(x, s, t) { console.log("Error..."); document.getElementById("lblResponse").innerHTML = x.responseText; } });
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

預檢請求

 OPTIONS http://localhost:8086/CustomerService/rest/GetCustomerRelational/ HTTP/1.1 Host: localhost:8086 Connection: keep-alive Access-Control-Request-Method: POST Origin: null User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 Access-Control-Request-Headers: accept, content-type Accept: */* Referer: http://stacksnippets.net/js Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8

飛行前響應

 HTTP/1.1 200 OK Content-Length: 0 Server: Microsoft-HTTPAPI/2.0 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: Origin, Cache-Control, Connection, Pragma, Content-Length, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, User-Agent Date: Wed, 26 Aug 2015 13:13:59 GMT

POST請求

 POST http://localhost:8086/CustomerService/rest/GetCustomerRelational/ HTTP/1.1 Host: localhost:8086 Connection: keep-alive Content-Length: 69 Accept: application/json, text/javascript, */*; q=0.01 Origin: null User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36 Content-Type: application/json Referer: http://stacksnippets.net/js Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.8 {"clientHandle":1824,"customerID":"ABB029","loadRelationalData":true}

POST 響應

 HTTP/1.1 405 Method Not Allowed Allow: OPTIONS Content-Length: 1565 Content-Type: text/html; charset=UTF-8 Server: Microsoft-HTTPAPI/2.0 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS Access-Control-Allow-Headers: Origin, Cache-Control, Connection, Pragma, Content-Length, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, User-Agent Date: Wed, 26 Aug 2015 13:14:02 GMT <p>Method not allowed.</p>

我想到了。

此WCF與其他所有WCF之間的主要區別在於,我的數據庫是自托管的,而其他所有文件則托管在IIS上(大多數情況下)。

感謝本文的ASP.NET兼容模式 ,答案就在於攔截預檢請求。 IIS托管的WCF要求在global.asax文件中進行攔截,如下所示:

protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            //These headers are handling the "pre-flight" OPTIONS call sent by the browser
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE,OPTIONS");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            HttpContext.Current.Response.End();
        }
    }

但是,這在自托管WCF中是不可能的。 但是,我們仍然可以使用app.config中的這一行使用ASP.NET功能

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

然后最后在服務類中利用它:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class TestService : ValidationModel, ITestService
{

我意識到僅將其設置為“允許”並沒有幫助,它必須為“必需”。

最后,為了開始預檢,需要在接口和服務中包含以下代碼:

[OperationContract]
    [FaultContract(typeof(ValidationFault))]
    [WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
    void GetOptions();

public void GetOptions()
    {
        WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
    }

現在,具有復雜參數的POST方法將通過預檢測試並通過響應執行該方法。

如果您在自托管服務中處理這種情況,則以下過程對我有用:

  1. 將 OPTIONS 方法添加到您的界面中(瀏覽器在調用您的 POST 方法之前調用 OPTIONS 來驗證 CORS)

    [OperationContract] [WebInvoke(Method = "OPTIONS", UriTemplate = "*")] void GetOptions();

  2. 在您的 ServiceBehavior 中實施 class

     public void GetOptions() { WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*"); WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST"); WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept"); WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;

    }

  3. class 可能必須具有此屬性:

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM