【发布时间】:2017-07-28 04:15:32
【问题描述】:
我需要向可执行文件托管的 WCF 服务发出跨域 POST 请求,而不是来自 IIS。目的是从 Web 客户端传入一个 id 字符串数组,WCF 服务将使用它来查找和返回与这些 id 相关的日志。
我相信我已经接近了,我缺少的主要部分是 app.config 文件中的一个配置,它添加了一个自定义标头。我会注意到,在我的解决方案的其他地方,有一个 web.config 用于描述我正在寻找的行为的另一个服务,其中包括:
<httpProtocol>
<customHeaders>
<!-- http://stackoverflow.com/questions/12458444/enabling-cross-origin-resource-sharing-on-iis7 -->
<add name="Access-Control-Allow-Headers" value="X-Requested-With,Content-Type,Accept" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Timing-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
现在我对 above 代码的问题是它驻留在 IIS 托管服务的 web.config 文件中。我需要能够在 app.config 中为我在可执行文件中托管的服务描述该自定义标头(我在下面提供了相关方法)。
我已经尝试解决这个问题好几天了,到目前为止,除了我正在寻求帮助的配置混乱之外,我的理解是这种语法可以调用服务:
var settings: JQueryAjaxSettings = {};
settings.async = true;
settings.crossDomain = true;
settings.url = this.getLogEntriesByIdResource;
settings.method = "POST";
settings.type = "POST";
settings.dataType = 'JSON';
settings.headers = {
"content-type": "application/json",
"cache-control": "no-cache"
}
settings.data = JSON.stringify(ids);
jQuery.ajax(settings).done(function (response) {
console.log(response);
});
这是在上面代码调用的 WCF 端点上的一个很好的传递:
[OperationContract, CorsEnabled]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json,
UriTemplate = "GetLogEntriesById")]
[Description("Request entities or entity updates for a particular time and place")]
public List<LogEntryInfo> GetLogEntriesById(string[] ids)
{
List<LogEntryInfo> results = new List<LogEntryInfo>();
List<ILogEntry> rels = Gateway.MongoDbInstance.ReturnLogEntries(ids.ToList());
rels.ForEach(e => results.Add(new LogEntryInfo(e)));
return results;
}
另外,这里是设置我的 webServiceHost 的代码:
public LogEntryRestService(string baseAddress, string endpoint)
{
_baseAddress = baseAddress;
_endpoint = endpoint;
_webServiceHost = new WebServiceHost(this, new Uri(baseAddress));
var webBinding = new WebHttpBinding(WebHttpSecurityMode.None) { CrossDomainScriptAccessEnabled = true };
ServiceEndpoint ep = _webServiceHost.AddServiceEndpoint(typeof(LogEntryRestService), webBinding, endpoint);
WebHttpBehavior webBehavior = new WebHttpBehavior();
webBehavior.HelpEnabled = true;
ep.EndpointBehaviors.Add(webBehavior);
ep.EndpointBehaviors.Add(new EnableCorsEndpointBehavior());
Program.LogMessage(string.Format("Initializing LogEntry REST endpoint BaseAddress: {0} EndpointName: {1}",
_webServiceHost.BaseAddresses[0], endpoint));
_webServiceHost.Open();
}
我还要指出,来自 Postman 的标准调用(带有指定给端点的 JSON 正文)运行良好。我知道 Postman(Chrome 扩展程序)不像网页那样遵守 CORS。我的调用 ajax 代码与 Postman 为 jQuery ajax 提供的建议调用代码相同,所以我认为这意味着我遇到了 CORS 问题。
我对所有这些配置和 CORS 绥靖感到有些疲惫,我真的很感谢新的眼睛和帮助!
更新
所以我尝试将我当前的代码(我在上面分享的内容)部署到一个实际的服务器实例,而不是在我的本地机器上进行调试,并发现一切正常。但是,我 am 仍然在本地收到我想解决的错误。当我的本地调试客户端调用我的本地调试服务时,此响应描述了该错误:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Service</title>
<style>BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;}</style>
</head>
<body>
<div id="content">
<p class="heading1">Service</p>
<p xmlns="">Method not allowed. Please see the <a rel="help-page" href="http://localhost/LogEntryService/help">service help page</a> for constructing valid requests to the service.</p>
</div>
</body>
</html>
我还要注意,请求方法显示为“OPTIONS”而不是 POST,这是它应该是的,也是我在专用服务器上运行所有这些代码时看到的行为。
POST 方法默认为 OPTIONS 方法的任何原因?我假设我回到了原点,为了解决这个问题,我需要在我的非 IIS 托管 Web 服务上启用 CORS。再次感谢您的帮助或见解!
更新
我在屏幕截图下方包含了请求的提琴手检查和请求的 Chrome 开发工具网络视图。
【问题讨论】:
-
我不是 jquery 专家,但 content-type: application/json 会触发预检响应,我知道。你有错误吗??我没有在您的帖子中看到任何错误。
-
哦,我应该添加我的错误,感谢您指出这一点。而且我认为你是对的,尽管我知道我需要以某种方式指定 JSON 内容类型,因为这就是我计划将字符串数组传递给我的 web 方法的方式。自从最初发布以来,我也取得了一些进展,我现在将更新我的帖子。感谢您的观看!
-
你有fiddler吗?我会查看提琴手的流量。如果您的标头发生变化,则很可能意味着您没有发送自定义标头,并且最终会得到一个默认标头,该标头可能会更改您发送的值(尽管我不知道这是否会影响该方法)。如果发生这种情况,您需要彻底确认应用程序中的 cors 配置。也不要以html格式发布您的错误消息,请发布错误消息。
-
发布您尝试发送的帖子的小提琴检查员。
-
邮递员不会有 cors 问题。我相信它会欺骗另一个域中的应用程序。 fiddler 是您的应用程序调用您的 Web 服务时发生的事情的真实故事。你看到中间。向我展示一个有助于诊断的原始小提琴请求或响应。