JavaScript CORS used to call asmx web-services

The following example shows how to implement a server implementing an asmx web-service and a JavaScript client invoking it from a different domain. The particularity is that this cross-site invocation requires CORS (Cross-origin resource sharing), supported in IE8+ and other popular browsers.


The server (part 1)

To create the server, I create in Visual Studio an empty web application. Then I add a Search.asmx web-service, adding the following method:

[WebMethod]

public string DateTimeNow(string Where)

{

return DateTime.Now.ToLongTimeString() + " in " + Where;

}

Then to test it I easily deploy it to the Azure Website http://corsserviceapplication.azurewebsites.net/.


The client

To create the client, I create in Visual Studio another empty web application. I add a reference to the jQuery NuGet package, then I add a simple html page and an App.js file.

Here the html page:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>My CORS Client Page</title>

<script src="Scripts/jquery-2.1.4.js"></script>

<script src="Scripts/App.js"></script>

</head>

<body>

<input id="city" type="text" value="Basel" />

<input type="button" value="Press here" onclick="test_cors_client(false, document.getElementById('city').value);" />

</body>

</html>


The App.js file is copied here too:
function test_cors_client(simple, where)
{
function escapeHTML(str) {
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

var soapEnv, soapAction;
if (simple) {
soapEnv =
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> \
<soap:Body> \
<HelloWorldResponse xmlns=\"http://tempuri.org/\"> \
<HelloWorldResult>string</HelloWorldResult> \
</HelloWorldResponse> \
</soap:Body> \
</soap:Envelope>";
soapAction = "http://tempuri.org/HelloWorld";
}
else {
soapEnv =
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"> \
<soap:Body> \
<DateTimeNow xmlns=\"http://tempuri.org/\"> \
<Where>" + escapeHTML(where) + "</Where> \
</DateTimeNow> \
</soap:Body> \
</soap:Envelope>";
soapAction = "http://tempuri.org/DateTimeNow";
}

$.ajax({
//url: "http://localhost:8118/Search.asmx",
url: "http://corsserviceapplication.azurewebsites.net/Search.asmx",
type: "POST",
dataType: "xml",
data: soapEnv,
complete: processResult,
contentType: "text/xml; charset=\"utf-8\"",
headers: {
"SOAPAction": soapAction
}
});
function processResult(xData, status) {
if (status != "success") {
alert("error\n\n" + xData.responseText);
return;
}
alert("success\n\n" + xData.responseText);
}
/* var createCORSRequest = function (method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// Most browsers.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// IE8 & IE9
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// CORS not supported.
xhr = null;
}
return xhr;
};

//var url = "http://localhost:8118/Search.asmx";
var url = 'http://corsserviceapplication.azurewebsites.net/Search.asmx';
var method = 'POST';
var xhr = createCORSRequest(method, url);
xhr.setRequestHeader("Content-Type", "text/xml; charset=\"utf-8\"");

xhr.onload = function (e) {
// Success code goes here.
alert('success\n\n' + e.target.responseText);
};

xhr.onerror = function (e) {
// Error code goes here.
alert('error\n\n' + e.target);
};

xhr.setRequestHeader("SOAPAction", soapAction);
xhr.send(soapEnv);*/
}

This file contains both the jQuery implementation using $.ajax, and the XmlHttpRequest + XDomainRequest produced using test-cors.org.
Trying the example, you will see that it works when the example is run locally (with Service.asmx copied in the same client website), but not with CORS.

The server (part 2)

To enable CORS on the server, we need to add additional headers on the server, and one quick method is to modify the web.config as here below:

<?xml version="1.0" encoding="utf-8"?>

<!--

For more information on how to configure your ASP.NET application, please visit

http://go.microsoft.com/fwlink/?LinkId=169433

-->

<configuration>

<system.web>

<compilation debug="true" targetFramework="4.5" />

<httpRuntime targetFramework="4.5" />

</system.web>


<system.webServer>

<httpProtocol>

<customHeaders>

<add name="Access-Control-Allow-Origin" value="*" />

<add name="Access-Control-Allow-Headers" value="Content-Type, SOAPAction" />

</customHeaders>

</httpProtocol>

</system.webServer>

</configuration>


Now it will be possible to invoke the Search.asmx web-service even from another domain through CORS and here is the zip file containing the complete solution: CORS_Test.zip (704.8KB).


A few links used for reference:

Add comment

Loading