I'm trying to call a WCF service from an ajax call with jQuery. I manage to call the WCF from SOAP-UI and from Excel/VBA. My problem comes from the OPTIONS request that's sent and no POST follows:
- if I set URL to
http://mywcf/service.svc
, OPTIONS is sent and I get a400 Bad Request
status and POST request is not sent. In this case, there's missingHTTP/1.1
in header (comparing with SOAP-UI headers). - if I set URL to
http://mywcf/service.svc HTTP/1.1
, OPTIONS is sent and I get a200 OK
status but POST request is not sent. In this case,HTTP/1.1
seems to be interpreted as a filename.
Can someone tell me how to call a POST action on a WCF from javascript and to add HTTP/1.1
header without corrupting service URL?
Here is a extract from my ajax call:
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' });
Values in my 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>
3 Answers
Answers 1
To consume a web service using jQuery, that is to make a call to the WCF service, you either use jQuery.ajax() or jQuery.getJSON(). In this article I used the jQuery.ajax()method.
To set the request, first define a variable. This will be helpful when you are calling multiple methods and creating a different js file to call the WCF service.
<script type="text/javascript"> var Type; var Url; var Data; var ContentType; var DataType; var ProcessData;
The following function initializes variables which are defined above to make a call to the service.
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(); }
The CallService function sends requests to the service by setting data in $.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; }
Note: The following code checks the result.GetUserResult statement, so your result object gets the property your service method name + Result. Otherwise, it will give an error like object not found in 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>
Answers 2
Add webHttpBinding endpoint
<services> <service name="Contract"> <endpoint address="json" binding="webHttpBinding" contract="IContract" bindingConfiguration="ActionsHttpBinding" behaviorConfiguration="ActionrestfulBehavior"/> </service>
then call the endpoint from ajax as post or get, see below example :
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) { });
Answers 3
Add below code to your global.asax.cs, and remove customHeaders from your web config.
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(); } }
Also you need remove OPTIONSVerbHandler for enabling 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>
0 comments:
Post a Comment