How to wire the readystatecomplete event from the XMLHttp object in InternetExplorer (.NET)

I have a web page that has a global variable in the jscript called xmlhttp.  It is the build in XMLHttp object in Internet Explorer.  I am hosting the WebBrowser control in a C# (.NET managed code) application and I want to know when the XMLHttp object is done.  This occurs after the document complete event so how do I do this?

 Answer:

This worked for me!  Using Visual Studio 2008:

Create a new C# Windows Form Application Called XMLHttpReadyState
Add a WebBrowser control to the form
Double click on the WebBrowser in the form to add the documentComplete event handler.
Add a function to wire the XMLHttp Event.

Here is the commented code.  Let me know if this is useful and if it works out for you!

 

using

System;

using

System.Collections.Generic;

using

System.ComponentModel;

using

System.Data;

using

System.Drawing;

using

System.Linq;

using

System.Text;

using

System.Windows.Forms;

using

System.Runtime.InteropServices;

namespace

XMLHttpReadyState

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

{

//when the document is done loading, wire up the XMLHttp object (if it exists)

wireXMLHttpReadyState();

}

// This class is used for the readystatechange callback. This callback expects an IDispatch interface.

// The constructor takes an Object which is the XMLHttp Obj so we can easily get the readystate.

// You could also simply go get the ready state by navigating down from the webbrowser document object.

[

ComVisible(true)] //this is necessary or you get an Invalid Cast exception

public class ReadyState

{

public ReadyState(Object theXMLHttpObj) { setObj( theXMLHttpObj); }

// DispId 0 is what the XMLHttpObj will call, the name does not matter

[

DispId(0)]

public void onMyImplOfreadystatechange()

{

if (m_XMLHttpObj != null)

{

Object theState = null;

theState = m_XMLHttpObj.GetType().InvokeMember(

"readyState", System.Reflection.BindingFlags.GetProperty, null, m_XMLHttpObj, null);

MessageBox.Show(theState.ToString());

// State 4 means done

if ((int)theState == 4)

{

// done so release the XMLHttpObj

setObj(

null);

}

}

else

{

// should not happen!

MessageBox.Show("XMLHTTP obj not set");

}

}

public void setObj(Object theObj){m_XMLHttpObj=theObj;}

private Object m_XMLHttpObj;

}

private void wireXMLHttpReadyState()

{

// get the DomDocument

Object aDomObj = webBrowser1.Document.DomDocument;

if (aDomObj!=null)

{

Object theScript = aDomObj.GetType().InvokeMember("Script", System.Reflection.BindingFlags.GetProperty, null, aDomObj, null);

if (theScript != null)

{

// Get the script engine interface

Object theXMLHttpObj = theScript.GetType().InvokeMember("xmlHttp", System.Reflection.BindingFlags.GetProperty, null, theScript, null);

if (theXMLHttpObj != null)

{

// wrap the Object as an IDispatch COM interface and...

Object toPass = new DispatchWrapper(new ReadyState(theXMLHttpObj));

// pass it to the method in an argument array

Object[] aArgs = new Object[1];

aArgs[0] = toPass;

theXMLHttpObj.GetType().InvokeMember(

"onreadystatechange", System.Reflection.BindingFlags.SetProperty, null, theXMLHttpObj, aArgs);

}

}

}

}

}

}

Sample HTML:

<html>
<body onload='doxmlstuff();'>
<script language="javascript">
var xmlHttp = null;
if (window.XMLHttpRequest) {
// If IE7, Mozilla, Safari, and so on: Use native object.
xmlHttp = new XMLHttpRequest();
}
else
{
if (window.ActiveXObject) {
// ...otherwise, use the ActiveX control for IE5.x and IE6.
xmlHttp = new ActiveXObject('MSXML2.XMLHTTP.3.0');
}
}
var MyName = "Bill Gates";
function ShowName()
{
alert("MyName = " + MyName);
}
function doxmlstuff()
{
if(xmlHttp)
{

xmlHttp.open("GET", "https://jsandersrvista/test.xml", true);
xmlHttp.send();
}
}
</script>
Hello there.<br>
</body>
</html>