坚持这个问题。我有一个包含2个项目的解决方案,其中一个是带有jquery ajax调用的普通旧html,而另一个是WCF服务。 html页面将发出对WCF服务的ajax调用以获取json字符串并将其用于显示目的。
现在问题是每当我在调试模式下运行时,html页面和WCF都将以不同的端口启动。当我执行测试时(即在Firefox中使用调用类型= OPTIONS获取405 Method Not Allowed错误),这已经为我创建了一个跨源问题。我会在我的ajax脚本上检查调用方法,并且WCF服务是相同的(GET)。
我会搜索谷歌,但发现要么我必须在IIS上安装扩展程序或执行某些配置,我发现这很麻烦,因为我正在做的事情很简单。举一个例子,我在web.config中添加了以下配置,但它不起作用:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="MobileService.webHttpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="MobileService.SimpleMemberInfo" behaviorConfiguration="MyServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="MobileService.IMemberInfo" bindingConfiguration="crossDomain" behaviorConfiguration="MobileService.webHttpBehavior">
</endpoint>
</service>
</services>
</system.serviceModel>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET" />
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
</customHeaders>
</httpProtocol>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
任何人都有想法摆脱这个烦人的问题吗?
编辑:只是要添加,我正在使用与VS Studio 2012一起提供的IIS Express运行调试
添加WCF代码并更新了web.config
[ServiceContract]
public interface IMemberInfo
{
[WebInvoke(Method = "GET",
BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json
)]
[OperationContract]
string GetMemberInfoById();
// TODO: Add your service operations here
}
我的剧本:
$(document).ready(function () {
$.ajax("http://localhost:32972/SimpleMemberInfo.svc/GetMemberInfoById", {
cache: false,
beforeSend: function (xhr) {
$.mobile.showPageLoadingMsg();
},
complete: function () {
$.mobile.hidePageLoadingMsg();
},
contentType: 'application/json',
dataType: 'json',
type: 'GET',
error: function () {
alert('Something awful happened');
},
success: function (data) {
var s = "";
s += "<li>" + data + "</li>";
$("#myList").html(s);
}
});
});
答案 0 :(得分:10)
您需要使用JSONP进行跨域调用以绕过浏览器限制,并将crossDomainScriptAccessEnabled
设置为true的web.config更新为圆形服务器。答案中有一个很好的例子:how to avoid cross domain policy in jquery ajax for consuming wcf service?
您可能还遇到GET请求问题。尝试这里概述的修复: Making a WCF Web Service work with GET requests
总而言之,您需要一个看起来像这样的web.config:
<bindings>
<webHttpBinding>
<binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehavior>
<behavior name="restBehavior">
<webHttp />
</behavior>
</endpointBehavior>
<serviceBehavior>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehavior>
</behaviors>
<services>
<service name="..." behaviorConfiguration="MyServiceBehavior">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="crossDomain"
contract="..." behaviorConfigurations="restBehavior" />
</service>
</services>
(请注意,服务和端点都附加了行为,分别允许webHttp调用和httpGet调用,并且绑定已明确启用了跨域访问)。
......像这样装饰的服务方法:
[ServiceContract]
public interface IMyService
{
[WebGet] // Required Attribute to allow GET
[OperationContract]
string MyMethod(string MyParam);
}
...和使用JSONP的客户端调用:
<script type="text/javascript">
$(document).ready(function() {
var url = "...";
$.getJSON(url + "?callback=?", null, function(result) { // Note crucial ?callback=?
// Process result
});
});
</script>
答案 1 :(得分:7)
然而它是一个旧线程,但我想补充一下我对我遇到的问题的评论以及我为CORS工作所获得的解决方案。 我正在以下环境中开发Web服务:
大多数人都提到在web.config中的crossDomainScriptAccessEnabled
下的标记中添加<webHttpBinding>
属性。我不确定这是否有效,但它在3.5版本中不可用,所以我别无选择。我还发现在web.config中添加以下标记将起作用...
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET" />
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
</customHeaders>
</httpProtocol>
但没有运气......继续获得405方法不允许错误
在使用这些选项挣扎很多之后,我找到了另一种解决方案,可以动态地在global.asax文件中添加这些标题,如下所示......
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
并从web.config中删除。发布网站并继续到客户端jquery / ajax ...然后你将从api调用中获取数据。祝你好运!
答案 2 :(得分:2)
只是想在底部附加CORS返工的一些问题 - 它的问题是如果你的输入不支持GET和POST方法,OPTIONS请求实际上并没有返回正确的允许头。它实际上并没有看到WCF端点上实际允许哪些方法 - 当客户端执行OPTIONS请求时,它只是人为地说应用程序中的每个端点都允许“GET,POST”(这实际上是客户端询问什么得到支持)。
这可能没问题,如果你真的不依赖OPTIONS方法中的信息来返回一个有效的方法列表(就像一些CORS请求的情况一样) - 但如果你是,你将需要做一些像这个问题的解决方案: How to handle Ajax JQUERY POST request with WCF self-host
基本上,每个端点都应该实现:
Webinvoke(Method="OPTIONS", UriTemplate="")
并调用一个适当的方法,将适当的标头加载到响应器(包括该端点的正确“Access-Control-Allow-Method”列表)给调用者。托管的WCF端点不会自动为我们执行此操作,但这是一种允许更精细地控制端点的解决方法。 在该解决方案中,在端点实现处加载适当的响应头:
public void GetOptions()
{
// The data loaded in these headers should match whatever it is you support on the endpoint
// for your application.
// For Origin: The "*" should really be a list of valid cross site domains for better security
// For Methods: The list should be the list of support methods for the endpoint
// For Allowed Headers: The list should be the supported header for your application
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization");
}
答案 3 :(得分:1)
答案 4 :(得分:-2)
尝试使用。
format
而不是WebInvoke(Method = "POST")