允许浏览器从 Windows service-hosted WCF 服务请求 JSONP
Allow browser to request JSONP from Windows service-hosted WCF service
我正在尝试安装一个托管的 windows service-hosted WCF 服务,它可以为我的网页提供一些关于安装它的机器的信息。我的想法是我页面的所有访问者都将安装此服务,并且该页面可以使用 javascript 调用本地主机服务以获取其后的数据。
我们的一位开发人员通过为服务启用 CORS 将其组合在一起
CarlosFigueira's example here。它在除 Edge 之外的所有浏览器中都运行良好,它会给出错误 SCRIPT7002: XMLHttpRequest: Network Error 0x2efd
。我想不出任何原因,也找不到任何相关信息,所以我想也许我应该尝试 jsonp 方法。
我认为 jsonp 应该绕过 same-origin 政策,但我只能让它与上面的 CORS-enabled WCF 服务一起工作**还在原地。一旦我删除它并只使用常规 ServiceHost
,我就开始收到 400 - 错误的请求响应。
** "work" 我的意思是浏览器成功发出请求并收到响应。但是,响应是普通的 json,而不是 jsonp。我读到 WCF 4.5 应该自动识别 "callback" 参数并将 json 包装在 "P" 中,但这似乎并没有发生。我认为这是一个不相关的次要问题。
但主要问题是,我认为 jsonp 应该是一种发出 cross-domain 请求的方式,所以为什么我必须启用所有 CORS header 东西我的 WCF 服务使其工作?
Windows 服务启动:
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]
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) {
}
});
我从头开始了一个自托管虚拟服务,并将问题缩小到我的配置。它需要使用 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,它只会显示空白页面。之后,它实际上 returns JSON 数据和 jQuery 可以成功地对 URL.[=14= 进行 JSONP AJAX 调用]
我仍然不清楚使用 webHttp 绑定和端点以及 crossDomainScriptAccessEnabled=true
实际发生了什么变化以允许调用。响应的内容类型可能?如有任何意见,我们将不胜感激。
现在我只需要验证它在所有浏览器中都能正常工作。如果有人知道为什么 Edge 不支持启用 CORS 的服务,请发表评论。
我正在尝试安装一个托管的 windows service-hosted WCF 服务,它可以为我的网页提供一些关于安装它的机器的信息。我的想法是我页面的所有访问者都将安装此服务,并且该页面可以使用 javascript 调用本地主机服务以获取其后的数据。
我们的一位开发人员通过为服务启用 CORS 将其组合在一起
CarlosFigueira's example here。它在除 Edge 之外的所有浏览器中都运行良好,它会给出错误 SCRIPT7002: XMLHttpRequest: Network Error 0x2efd
。我想不出任何原因,也找不到任何相关信息,所以我想也许我应该尝试 jsonp 方法。
我认为 jsonp 应该绕过 same-origin 政策,但我只能让它与上面的 CORS-enabled WCF 服务一起工作**还在原地。一旦我删除它并只使用常规 ServiceHost
,我就开始收到 400 - 错误的请求响应。
** "work" 我的意思是浏览器成功发出请求并收到响应。但是,响应是普通的 json,而不是 jsonp。我读到 WCF 4.5 应该自动识别 "callback" 参数并将 json 包装在 "P" 中,但这似乎并没有发生。我认为这是一个不相关的次要问题。
但主要问题是,我认为 jsonp 应该是一种发出 cross-domain 请求的方式,所以为什么我必须启用所有 CORS header 东西我的 WCF 服务使其工作?
Windows 服务启动:
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]
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) {
}
});
我从头开始了一个自托管虚拟服务,并将问题缩小到我的配置。它需要使用 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,它只会显示空白页面。之后,它实际上 returns JSON 数据和 jQuery 可以成功地对 URL.[=14= 进行 JSONP AJAX 调用]
我仍然不清楚使用 webHttp 绑定和端点以及 crossDomainScriptAccessEnabled=true
实际发生了什么变化以允许调用。响应的内容类型可能?如有任何意见,我们将不胜感激。
现在我只需要验证它在所有浏览器中都能正常工作。如果有人知道为什么 Edge 不支持启用 CORS 的服务,请发表评论。