如何从 javascript 调用 WCF 服务?
Posted
技术标签:
【中文标题】如何从 javascript 调用 WCF 服务?【英文标题】:How to call a WCF service from javascript? 【发布时间】:2017-11-29 12:12:24 【问题描述】:我正在尝试使用 jQuery 从 ajax 调用中调用 WCF 服务。 我设法从 SOAP-UI 和 Excel/VBA 调用 WCF。 我的问题来自已发送的 OPTIONS 请求并且没有 POST 跟随:
如果我将 URL 设置为http://mywcf/service.svc
,则会发送 OPTIONS,我会收到 400 Bad Request
状态,但不会发送 POST 请求。在这种情况下,标头中缺少 HTTP/1.1
(与 SOAP-UI 标头相比)。
如果我将 URL 设置为 http://mywcf/service.svc HTTP/1.1
,则会发送 OPTIONS 并且我会收到 200 OK
状态,但不会发送 POST 请求。在这种情况下,HTTP/1.1
似乎被解释为文件名。
谁能告诉我如何从 javascript 调用 WCF 上的 POST 操作并添加 HTTP/1.1
标头而不破坏服务 URL?
这是我的 ajax 调用的摘录:
var soapData = ''
+'<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:mic="http://microsoft.wcf.documentation">'
+' <soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wsrm="http://docs.oasis-open.org/ws-rx/wsrm/200702">'
+' <wsrm:Sequence>'
+' <wsrm:Identifier>s:Sender a:ActionNotSupported</wsrm:Identifier>'
+' <wsrm:MessageNumber>1</wsrm:MessageNumber>'
+' </wsrm:Sequence>'
+' <wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence</wsa:Action>'
+' <wsa:ReplyTo>'
+' <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>'
+' </wsa:ReplyTo>'
+' <wsa:MessageID>uuid:'+ MsgUid +'</wsa:MessageID>'
+' <wsa:To>'+ Url +'</wsa:To>'
+' </soap:Header>'
+' <soap:Body xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">'
+' <wsrm:CreateSequence>'
+' <wsrm:AcksTo xmlns:wsa="http://www.w3.org/2005/08/addressing">'
+' <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>'
+' </wsrm:AcksTo>'
+' <wsrm:Offer>'
+' <wsrm:Identifier>urn:soapui:'+ SeqUid +'</wsrm:Identifier>'
+' </wsrm:Offer>'
+' </wsrm:CreateSequence>'
+' </soap:Body>'
+'</soap:Envelope>';
$.ajax(
type: 'POST',
url: 'http://mywcf/service.svc', // with or without +' HTTP/1.1'
data: soapData,
contentType: 'application/soap+xml;charset=UTF-8',
dataType: 'xml'
);
我的 WCF 中的值 web.config
:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="POST, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
【问题讨论】:
一个明显的问题是您通话中的网址。您需要在 url 中包含 WCF 方法名称 @Sparrow 我设法在不设置方法名称的情况下从 VBA 和 SOAP-UI 调用 WCF。当我在 ajax 调用中添加方法名称时,它似乎被解释为文件名。我不认为这是一个解决方案。 请否决票解释他们的选择,谢谢。 那么您可能没有在配置文件中正确设置 wcf。你在使用 Visual Studio 吗?如果是,那么我认为您应该使用“WCF 测试客户端”工具并检查它是如何进行调用的。那将是起点。 @Sparrow 我真的没有 WCF 开发的权利。因为我可以通过 VBA 和 SOAP-UI 调用 WCF,所以我相信即使使用 OPTIONS 预检也可以使用 AJAX 调用来实现。 “WCF 测试客户端”调用我的 Web 方法失败,但它不是很冗长,所以我不知道会发生什么。 【参考方案1】:要使用 jQuery 使用 Web 服务,即调用 WCF 服务,您可以使用 jQuery.ajax() 或 jQuery.getJSON()。在本文中,我使用了 jQuery.ajax() 方法。
要设置请求,首先定义一个变量。当您调用多个方法并创建不同的 js 文件来调用 WCF 服务时,这将很有帮助。
<script type="text/javascript">
var Type;
var Url;
var Data;
var ContentType;
var DataType;
var ProcessData;
以下函数初始化上面定义的变量以调用服务。
function WCFJSON()
var userid = "1";
Type = "POST";
Url = "Service.svc/GetUser";
Data = '"Id": "' + userid + '"';
ContentType = "application/json; charset=utf-8";
DataType = "json"; varProcessData = true;
CallService();
CallService 函数通过在 $.ajax 中设置数据向服务发送请求。
// Function to call WCF Service
function CallService()
$.ajax(
type: Type, //GET or POST or PUT or DELETE verb
url: Url, // Location of the service
data: Data, //Data sent to server
contentType: ContentType, // content type sent to server
dataType: DataType, //Expected data format from server
processdata: ProcessData, //True or False
success: function(msg) //On Successfull service call
ServiceSucceeded(msg);
,
error: ServiceFailed// When Service call fails
);
function ServiceFailed(result)
alert('Service call failed: ' + result.status + '' + result.statusText);
Type = null;
varUrl = null;
Data = null;
ContentType = null;
DataType = null;
ProcessData = null;
注意:以下代码检查 result.GetUserResult 语句,因此您的结果对象获取您的服务方法名称 + Result 的属性。否则,它会给出一个错误,比如在 Javascript 中找不到对象。
function ServiceSucceeded(result)
if (DataType == "json")
resultObject = result.GetUserResult;
for (i = 0; i < resultObject.length; i++)
alert(resultObject[i]);
function ServiceFailed(xhr)
alert(xhr.responseText);
if (xhr.responseText)
var err = xhr.responseText;
if (err)
error(err);
else
error( Message: "Unknown server error." )
return;
$(document).ready(
function()
WCFJSON();
);
</script>
【讨论】:
【参考方案2】:添加 webHttpBinding 端点
<services>
<service name="Contract">
<endpoint address="json" binding="webHttpBinding" contract="IContract" bindingConfiguration="ActionsHttpBinding" behaviorConfiguration="ActionrestfulBehavior"/>
</service>
然后从 ajax 调用端点作为 post 或 get,参见下面的示例:
var data = JSON.stringify(
param1: val1,
param2: val2
);
$.ajax(
url: "http://mywcf/service.svc/json/FunctionName",
type: "POST",
data: data,
contentType: "application/json; charset=utf-8",
dataType: "json",
processData: true
).then(function (rsutlt)
).fail(function (fail)
);
【讨论】:
【参考方案3】:将以下代码添加到您的 global.asax.cs,并从您的网络配置中删除 customHeaders。
protected void Application_BeginRequest(object sender, EventArgs e)
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, 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();
您还需要删除 OPTIONSVerbHandler 以启用 cors。
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
【讨论】:
以上是关于如何从 javascript 调用 WCF 服务?的主要内容,如果未能解决你的问题,请参考以下文章
稳步减慢从 javascript 对 WCF 服务的 ajax 调用