Monday, May 6, 2013

ASP.NET AJAX Extension XML web services not work in IE10

This problem occurs when you are
  1. Using ASP.NET AJAX Extension to call web services (no matter 1.1 or the one in .net 3.0)
  2. Your web services return an XML node and the response format of script method set to XML instead of JSON
  3. Using IE10 as the browser
Then you will find that, the callback of the web service just give you a null result and nothing more.

After searching the google and find that there are little information regarding the problem, and the only hints I find is that the IE10 change to use the document as the default response type instead of an XML document. After debug into the ScriptResource.axd and find that inside the function get_xml of XMLHttpExecutor, there is a line a.setProperty that throw an Exception and this cause the result to be null.

The object is a document object while it expect that it is an xml object, and it seems match with the finding in google. The solution to that is to change the responseType of the XMLHttpRequest to "msxml-document" but as the XMLHttpRequest actually is generated in the ScriptResource.axd automatically, so we need to do something to override it.

So the final solution is to override the executeRequest function after the page load as follow

Sys.Net.XMLHttpExecutor.prototype.executeRequest = function () {
this._webRequest = this.get_webRequest();
var c = this._webRequest.get_body(), a = this._webRequest.get_headers();
this._xmlHttpRequest = new XMLHttpRequest;
this._xmlHttpRequest.onreadystatechange = this._onReadyStateChange;
var e = this._webRequest.get_httpVerb();
this._xmlHttpRequest.open(e, this._webRequest.getResolvedUrl(), true);
if (a)
  for (var b in a) {
    var f = a[b];
    if (typeof f !== "function")
      this._xmlHttpRequest.setRequestHeader(b, f)
  }
  if (e.toLowerCase() === "post") {
    if (a === null || !a["Content-Type"])
      this._xmlHttpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    if (!c)
      c = ""
  }
// only add this line
  try { this._xmlHttpRequest.responseType = "msxml-document"; } catch (err) { }
  var d = this._webRequest.get_timeout();
  if (d > 0)
    this._timer = window.setTimeout(Function.createDelegate(this, this._onTimeout), d);
  this._xmlHttpRequest.send(c);
  this._started = true
}

The whole function are copied from the auto generated script, and only added one line to change the responseType of the XMLHttpRequest.

However, according to the Microsoft, it seems to be a temporary solution and finally need to migrate to use other method.....anyway hope this can help someone who did not find out a solution for that problem.

2 comments: