2016-11-03 111 views
1

我試圖安裝託管的Windows服務託管的WCF服務,它可以爲我的網頁提供關於它所安裝的機器的一些信息。這個想法是,我的頁面的所有訪問者將安裝此服務,並且頁面可以使用javascript調用localhost服務以獲取其後的數據。允許瀏覽器從Windows服務託管的WCF服務請求JSONP

我們的開發人員之一通過使用 CarlosFigueira's example here啓用CORS服務將這一切放在一起。它在除了Edge以外的所有瀏覽器都很好用,它給出了錯誤SCRIPT7002: XMLHttpRequest: Network Error 0x2efd。我想不出任何理由,也無法找到任何信息,所以我想也許我應該嘗試一種jsonp方法。

我以爲jsonp應該繞過同源策略,但我只能使它工作**與上述啓用CORS的WCF服務的東西仍然在原地。只要我刪除它,只是使用一個普通的ServiceHost,我開始得到一個400 - 錯誤的請求響應。

**「工作」是指瀏覽器成功發出請求並收到響應。但是,響應是普通的json,而不是jsonp。我讀過WCF 4.5應該自動識別「callback」參數並將json包裝在「P」中,但似乎並未發生。我認爲這是一個無關的次要問題。

但主要問題是,我認爲jsonp應該是一種製作跨域請求的方式,爲什麼我必須啓用我的WCF服務上的所有CORS標頭才能使其工作?

Windows服務的OnStart:

CorsEnabledServiceHostFactory serviceHostFactory = new CorsEnabledServiceHostFactory(); 
serviceHost = serviceHostFactory.GetServiceHost(typeof(LPA.MachineDataService), baseAddresses); //Works 

//LPA.MachineDataService singleton = new LPA.MachineDataService(); 
//serviceHost = new System.ServiceModel.ServiceHost(singleton, baseAddresses); //Doesn't work 

serviceHost.Open(); 

的ServiceContract:

[ServiceContract] 
public interface IMachineDataService 
{ 
    [WebGet(UriTemplate = "GetValues", ResponseFormat=WebMessageFormat.Json)] 
    LPA.MachineData GetValues(); 
} 

服務實現:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
public class MachineDataService : IMachineDataService 
{ 
    public LPA.MachineData GetValues() 
    { 
     LPA.MachineData result = null; 

     try 
     { 
      WebOperationContext.Current.OutgoingResponse.Headers[HttpResponseHeader.CacheControl] = "no-cache"; 

      result = PcValues.GetValues(); 
     } 
     catch (Exception ex) 
     { 
     } 

     return result; 
    } 
} 

從Windows服務的app.config:

<system.serviceModel> 
<behaviors> 
    <serviceBehaviors> 
    <behavior name=""> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="false" /> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" /> 
<standardEndpoints> 
    <webScriptEndpoint> 
    <standardEndpoint crossDomainScriptAccessEnabled="true" name=""></standardEndpoint> 
    </webScriptEndpoint> 
    <webHttpEndpoint> 
    <standardEndpoint crossDomainScriptAccessEnabled="true" name=""></standardEndpoint> 
    </webHttpEndpoint> 
</standardEndpoints> 

</system.serviceModel> 

jQuery的電話:

var valuesAddress = "http://localhost:56731/ValuesService/GetValues"; 

$.ajax({ 
    type: "GET", 
    url: valuesAddress, 
    dataType: "jsonp", 
    success: function (result) { 
     $("[data-authinfo]").val(result); 
    }, 
    error: function (xhr, status, code) { 

    } 
}); 

回答

0

我開始從頭自託管的虛擬服務和縮小的問題我的配置。它需要使用webHttpBinding作爲REST服務,我想,沒有明確指定,它是使用basicHttpBinding。我刪除了標準的端點和配置端點自己這樣的:

<system.serviceModel> 
    <behaviors> 
    <endpointBehaviors> 
     <behavior name="webHttpBehavior"> 
     <webHttp/> 
     </behavior> 
    </endpointBehaviors> 
    </behaviors> 
    <bindings> 
    <webHttpBinding> 
     <binding name="webHttpBinding" crossDomainScriptAccessEnabled="true" /> 
    </webHttpBinding> 
    </bindings> 
    <services> 
    <service name="LessonPlansAuthentication.MachineDataService"> 
     <endpoint address="" binding="webHttpBinding" 
       bindingConfiguration="webHttpBinding" 
       behaviorConfiguration="webHttpBehavior" 
       contract="LessonPlansAuthentication.IMachineDataService"/> 
    </service> 
    </services> 
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" /> 
</system.serviceModel> 

如果我試圖使這一變化之前訪問在瀏覽器的URL,它只是顯示一個空白頁。之後,它實際上會返回JSON數據,並且jQuery可以成功地對URL進行JSONP AJAX調用。

我仍然不清楚使用webHttp綁定&端點以及crossDomainScriptAccessEnabled=true實際上是否允許調用。響應的內容類型可能是?任何意見,將不勝感激。

現在我只需驗證它適用於所有瀏覽器。如果有人知道Edge爲什麼不支持啓用CORS的服務,請留下評論。