我需要向可执行文件托管的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>
现在我的上面代码的问题在于它位于IIS托管服务的 web.config 文件中。我需要能够在 app.config 中为我的服务描述该自定义标头,我在可执行文件中托管(我在下面提供了相关方法)。
我一直在努力解决这个问题,到目前为止,除了我寻求帮助的配置混乱之外,我的理解是这种语法可以用于调用服务:< / p>
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主体完美配合。我知道邮递员(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>
我还要注意,请求方法显示为&#34; OPTIONS&#34;而不是POST,这应该是它应该是什么,并且是我在专用服务器上运行所有这些代码时看到的行为。
POST方法默认为OPTIONS方法的原因是什么?我假设我回到原点解决这个问题我需要在我的非IIS托管Web服务上启用CORS。再次感谢您的帮助或见解!
更新
我已经包含了对请求的小提琴检查和请求的Chrome开发者工具网络视图的屏幕上限。
答案 0 :(得分:2)
这可以帮助您解决问题所在。我看到的屏幕截图(主要是小提琴)是预检。那些是选项。但是如果你通过了预检,那么你的帖子应该被发送掉,所以在那之后应该有另一个条目。这是一个很好的Post in Fiddle的例子。
预检(原始):
OPTIONS http://localhost:5000/api/values/dui/ HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://evil.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Access-Control-Request-Headers: access-control-allow-origin, content-type
Accept: */*
Referer: http://localhost:3000/validator
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8
紧随其后的是帖子
请求(原始):
POST http://localhost:5000/api/values/dui/ HTTP/1.1
Host: localhost:5000
Connection: keep-alive
Content-Length: 17
access-control-allow-origin: *
accept: application/json
Origin: http://evil.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
content-type: application/json
Referer: http://localhost:3000/validator
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
{"name":"test"}
来自我的API(原始)的回复:
HTTP/1.1 200 OK
Date: Thu, 09 Mar 2017 16:42:27 GMT
Content-Type: application/json; charset=utf-8
Server: Kestrel
Content-Length: 57
{"name":"Hey Test, Im The Dude man.","link":"dude.png"}
我不认为你正在通过飞越前飞行。我不确定Chrome中的响应来自哪里,但您需要确保设置为通过预检。因此,应用程序中的代码必须具有正确的cors配置以及服务器(在IIS中使用web.config)。我遇到类似的问题,使用dotnet核心webApi和React UI正确设置Cors(查看here)。你可以在这里看到我是如何处理它的。希望这可以帮助。但我会专注于预检,确保通过。如果是这样的话,请转到邮政本身。例如,如果您在设置的帖子(application / json)中没有看到您的内容类型,那么您的自定义标题会在某处被破坏。抱歉,我无法精确确定您需要设置的位置,但选项是预检是正常的。我不会专注于那个。
*******解决方案更新已添加**********
我相信你需要这样的东西来解决你的问题。基本上你需要在WebService本身添加标题。
&#34;添加global.asax文件并将以下代码添加到Application_BeginRequest。以下是代码段。&#34;
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
完整参考是here。这篇文章是最近的。这应该可以解决您的问题。