We have a .Net webservice which runs on one server and a web application (javascript) running on another. The webservice needs to have Windows Authentication.
We keep getting the error 401 Unauthorized on the CORS Preflight call, which preceeds the cross domain webservice call. If we move the webservice on the same machine as the application, the calls run perfectly.
Spent four days now to get it working, hopefully someone here can point me in the right direction...
P.S.: added a JSFiddle which demonstrates the problem.
Example in fiddle
Here is the web.config we use for the webservice
="1.0"="UTF-8"
<configuration>
<appSettings />
<connectionStrings />
<system.web>
<compilation debug="true" />
<authentication mode="Windows" />
<customErrors mode="Off" />
<webServices>
<protocols>
<add name="HttpSoap" />
<add name="HttpGet" />
<add name="HttpPost" />
</protocols>
</webServices>
<httpRuntime maxUrlLength="9999" relaxedUrlToFileSystemMapping="true" maxQueryStringLength="2097151" requestValidationMode="2.0"/>
<pages validateRequest="false" />
</system.web>
<system.webServer>
<defaultDocument>
<files>
<remove value="default.aspx" />
<remove value="Default.asp" />
<remove value="index.html" />
<remove value="iisstart.htm" />
<remove value="index.htm" />
<remove value="Default.htm" />
<add value="webservice.asmx" />
</files>
</defaultDocument>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="http://domain.nl" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Allow-Headers" value="SOAPAction, Content-Type,Authorization" />
<add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
</customHeaders>
</httpProtocol>
<security>
<requestFiltering>
<requestLimits maxUrl="10999" maxQueryString="9999" />
</requestFiltering>
</security>
</system.webServer>
</configuration>
Here is the peace of javascript we are using
SOAPClientParameters = (function () {
function SOAPClientParameters() {
var self = this;
self.list = new Array();
}
SOAPClientParameters.prototype.add = function (name, value) {
var self = this;
self.list[name] = value;
return self;
};
SOAPClientParameters.prototype._serialize = function (o) {
var s = "";
switch (typeof (o)) {
case "string":
s += o;
case "number":
case "boolean":
s += o.toString(); break;
case "object":
if (testNull(o)) { s += ""; }
else if (typeof o === 'Date') {
dateToSqlString(o);
}
else if (typeof o === 'Array') {
for (var p in o) {
if (!isNaN(p))
{
(/function\s+(\w*)\s*\(/ig).exec(o[p].constructor.toString());
var type = RegExp.$1;
switch (type) {
case "":
type = typeof (o[p]);
case "String":
type = "string"; break;
case "Number":
type = "int"; break;
case "Boolean":
type = "bool"; break;
case "Date":
type = "DateTime"; break;
}
s += "<" + type + ">" + SOAPClientParameters._serialize(o[p]) + "</" + type + ">"
}
else
s += "<" + p + ">" + SOAPClientParameters._serialize(o[p]) + "</" + p + ">"
}
}
else
for (var p in o)
s += "<" + p + ">" + SOAPClientParameters._serialize(o[p]) + "</" + p + ">";
break;
default:
throw new Error(500, "SOAPClientParameters: type '" + typeof (o) + "' is not supported");
}
return s;
}
SOAPClientParameters.prototype.toXml = function () {
var self = this;
var xml = "";
for (var p in self.list) {
if (typeof self.list[p] !== 'function') {
xml += "<" + p + ">" + self._serialize(self.list[p]) + "</" + p + ">";
}
}
return xml;
}
return SOAPClientParameters;
}());
SOAPClient = (function () {
function SOAPClient(url, async) {
var self = this;
self.xmlHttp = null;
if (window.XMLHttpRequest) {
self.xmlHttp = new XMLHttpRequest();
if (self.xmlHttp.readyState == null) {
self.xmlHttp.readyState = 1;
self.xmlHttp.addEventListener("load",
function () {
self.xmlHttp.readyState = 4;
if (typeof self.xmlHttp.onreadystatechange == "function")
self.xmlHttp.onreadystatechange();
},
false);
}
} else {
throw 'This browser is not supported!';
}
self.xmlHttp.async = async;
if (self.xmlHttp !== null) {
self.xmlHttp.open("POST", url, self.xmlHttp.async);
self.xmlHttp.url = url;
self.xmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
self.xmlHttp.onerror = function () {
if (self.xmlHttp.async) {
var errorClient = new SOAPClient(self.xmlHttp.url, false);
var exception = errorClient.invoke(self.xmlHttp.func, self.xmlHttp.parameters, function () { }, function () { });
self.xmlHttp.errorCallback(isnull(exception.message, 'Unknown error...'));
}
}
self.xmlHttp.onload = function () {
if ((self.xmlHttp.readyState === 4) && (self.xmlHttp.status !== 200)) {
self.xmlHttp.errorCallback(self.xmlHttp.statusText);
}
}
}
}
SOAPClient.prototype.result = function (data) {
return data;
};
SOAPClient.prototype.invoke = function (method, parameters, successCallback, errorCallback) {
var self = this;
var ns = 'http://domain.com/';
var sr = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<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>" +
"<" + method + " xmlns=\"" + ns + "\">" +
parameters.toXml() +
"</" + method + "></soap:Body></soap:Envelope>";
var soapaction = ((ns.lastIndexOf("/") != ns.length - 1) ? ns + "/" : ns) + method;
self.xmlHttp.function = method;
self.xmlHttp.parameters = parameters;
self.xmlHttp.errorCallback = errorCallback;
self.xmlHttp.setRequestHeader("SOAPAction", soapaction);
if (self.xmlHttp.async) {
self.xmlHttp.onreadystatechange = function () {
if ((self.xmlHttp.readyState == 4) && (self.xmlHttp.status === 200)) {
self.onSuccess();
}
}
}
try {
self.xmlHttp.send(sr);
if (!self.xmlHttp.async) {
self.onSuccess();
}
} catch (ex) {
return ex;
}
}
SOAPClient.prototype.onSuccess = function () {
var self = this;
if ((self.xmlHttp.readyState == 4) && (self.xmlHttp.status === 200)) {
var o = null;
var responseText = self.xmlHttp.response;
}
}
return SOAPClient;
}());