Click here to Skip to main content
15,886,963 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
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

XML
<?xml version="1.0" encoding="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

JavaScript
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; //real code is a little different but includes >
            case "number":
            case "boolean":
                s += o.toString(); break;
            case "object":
                // Date
                if (testNull(o)) { s += ""; }
                else if (typeof o === 'Date') {
                    dateToSqlString(o); // custom external function to create date to string suitable for MSSQL
                }
                else if (typeof o === 'Array') {
                    for (var p in o) {
                        if (!isNaN(p))   // linear array
                        {
                            (/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    // associative array
                            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();
            // patch for Moz (some versions)
            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);
            }
            //req.withCredentials = true; // tried this, but didn't work
        } 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 () { // handle eg. 40x errors
                if (self.xmlHttp.async) {
                    // resend it synchronous and catch the exception
                    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 () { // handle eg. 50x errors
                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;

            // do the success callback here
        }
    }

    return SOAPClient;
}());
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900