2016-11-03 164 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的服务,请留下评论。