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>
Comments
Anonymous
November 12, 2010
Hi, Do you happen to have an update to this sample on a more recent version of VS. I am using VS2008 and .NET 4, the above code doesn't appear to work anymore, it fails on Object theXMLHttpObj = theScript.GetType().InvokeMember("xmlHttp", System.Reflection.BindingFlags.GetProperty, null, theScript, null); ThanxAnonymous
December 01, 2010
I have not tried this lately. I will try and take some time to see that is happening!