0

I am trying to navigate to a page with a hidden browser from within a C# application, click on a link and verify the click worked. Flow: - navigate to "http://mypage" - click on a link, the link HTML code is (calling a ComponentArt CallBack):

<div id="ctl00_ctl00_PlaceHolderMain_Colleague1_linkAdd" onclick="colleagueCallback.callback('SOMENAME'); return false;">

Add colleague - wait for the click to get the result and update the page - verify the click worked

My problem: The click does not seem to fully complete, unless I call the WebBroser.Print() (which I do not need, just tried a million ways to figure out what is going on after the click, only Print is making the click complete).

The code, which works absolutely fine, navigate is working, it can find the tags I am looking for, the click event is firing (I get an intermediary change), but the callback does not complete, as it turns out only using the WebBrowser.Print(), all the other WebBrowser.Invalidate(), WebBrowser.Update(), WebBrowser.DocumentStream.Flush() or WebBroser.ResumeLayout() won't finalize the ASP callback within the page ...:

tempIE = new WebBrowser();
tempIE.Navigate("http://mypage");
while (tempIE.ReadyState != WebBrowserReadyState.Complete)
{
      Application.DoEvents();
}
tempIE.AllowNavigation = true;
HtmlElement addDivTag = tempIE.Document.GetElementById("ctl00_ctl00_PlaceHolderMain_Colleague1_linkAdd");
if (addDivTag == null)
    throw (new Exception("Session.FollowPerson: could not find the Add tag"));
if ( addDivTag.FirstChild == null )
    throw (new Exception("Session.FollowPerson: could not find the add link"));
addDivTag.FirstChild.InvokeMember("click");
while (tempIE.ReadyState != WebBrowserReadyState.Complete)
{
    Application.DoEvents();
}

After this I am verifying if one of the tags has been changed by the ComponentArt server CallBack but only getting the intermediary tag. The change I am monitoring is:

<a href="javascript:void(0)">Add colleague</a>

will change intermediary to (while making the add logic in the CallBack):

<img src="/images/loading.gif">

in the end should change to:

<br>Is your colleague</br>

Anyone knows what exaclty is going on in the WebBroser.Print() that makes the page fully complete the callback ?

OliCS
  • 3
  • 2

1 Answers1

0

I believe WebBrowser does its work in a separate thread. Print would therefore use a thread synch mechanism, like a WaitXXX type function (which allows the message pump to keep running while causing the GUI thread to wait for an event).

The DoEvents may not be giving your thread a chance to run (are you using a single processor cpu?). Try inserting a Thread.Sleep(200) and see if the behavior changes. If so, consider changing to one of the WaitXXX functions (I'll look up the one I'm thinking of, and post an edit).

EDIT The were MsgWaitXXX functions and you would need to P/Invoke them if you choose to use them.

I would recommend you hook the WebBrowser.Navigated event. Break your logic into two parts. The first part would call Navigate and flag your UI as waiting for something, the second part would be done in your Navigated handler when the event fires.

Les
  • 10,335
  • 4
  • 40
  • 60
  • I already thought the ReadyState would not work perfectly and added a very big delay (Thread.Sleep(50000)). When I do the same flow from IE manually, it takes much less that that for the click to complete. Have also added the DocumentCompleted event handler, which fires but the click is still not completed (a separate view of the page shows the action did not complete) – OliCS Nov 09 '10 at 15:55
  • As another test, instead of waiting, try hooking the Navigated event. When you do, does it fire? – Les Nov 09 '10 at 15:58
  • one thing I can say, DocumentCompleted does not fire after I click the link ... even when I use the Print() to force the commit. – OliCS Nov 09 '10 at 15:59
  • Have you tried moving the AllowNavigation = true, to just before your call to Navigate? – Les Nov 09 '10 at 16:30
  • Does your callback have errors in it? Do you have ScriptErrorsSuppressed == true? – Les Nov 09 '10 at 17:01
  • One more question. Is your code running inside of an event handler? Application.DoEvents() may not be letting the WebBrowser's message pump run. – Les Nov 09 '10 at 17:15
  • The whole code listed here is working fine, it's only the last click which it does fire but somehow does not complete within the WebBrowser or on the server side (unlikely, the page works just fine from anywhere else like IE). Will try to wireup to the Navigated event and enable some more error messages if possible, although the callback seems to be fine. – OliCS Nov 10 '10 at 07:27
  • I get the Navigated as well as the DocumentCompleted after the initial Navigate() call. I do not get any event after the click, is this the regular behavior ? (the click does submit the form at some point) – OliCS Nov 10 '10 at 12:06
  • I tried everything after the click: tempIE.DocumentStream.Flush(); tempIE.Invalidate(); tempIE.Update(); tempIE.Select(); tempIE.Focus(); tempIE.ResumeLayout(true); tempIE.Show(); //amaizingly the following 2 lines will work and click will complete //tempIE.ShowPrintPreviewDialog(); //tempIE.Print(); – OliCS Nov 10 '10 at 12:40
  • When I wire up Navigated and DocumentCompleted, they work fine. However, if I try to call the click event from the DocumentCompleted event handler, the ReadyState does not change. I have to exit the function to allow the next events to fire. This is normal because the WebBrowser is probably waiting for the handler to complete before proceeding. But that doesn't explain the Print() behavior you are seeing. – Les Nov 12 '10 at 02:32
  • Figured out the issue. During validation, after the InvokeMethod("click") used Thread.Sleep() to wait for the update. Looks like WebBrowser's events get screwedup if its thred is suspended during navigation. Application.DoEvents() are not able to recover anything, somehow the Print() and related methods do, have still no idea how. What I did is a loop to download separately the page again and again to validate the change happen, no sleeps in the loop anymore. You could do it in separate threads with a semaphor or something ... no such complexity needed for me now. – OliCS Nov 15 '10 at 20:26