我正在使用WebBrowser控件来测试表单提交,在这种特殊情况下,该操作是一个重定向到另一个结果页面的MVC操作.
代码非常简单……
void _browser_DocumentCompleted(object sender,WebBrowserDocumentCompletedEventArgs e) { var parentForm = _my_find_form_function(); parentForm.SetAttribute("action","http://localhost/tests/TestSubmission"); parentForm.InvokeMember("submit"); }
提交后(按预期工作)我会认为在加载重定向页面后会触发下一个documentcompleted事件.相反,加载相同的页面(与表单).
有什么我想念的吗?
谢谢
解决方法
好的,对不起延迟,我转向别的……
无论如何,它真的很粗糙,但你应该能够选择你需要的位.
通过监视事件之后的文档状态,raiseynamicevent方法以与async nav类似的方式工作.当再次确定时,返回.应该处理ajax的东西.我需要重新考虑一下,并用它来解决许多错误,但希望能有所帮助.
/// the _profileQueue was a queue of URLs i wanted to nav through and find an /// form elem and "click" the submit button on private async void Next() { Submission res = null; if (_profileQueue.TryDequeue(out res)) { // dirty,but hold the details of the url i'm navigating to in the Tag _browser.Tag = res; var cts = new CancellationTokenSource(Properties.Settings.Default.BrowserNavigationTimeout); // cancel in 10s var html = await LoadDynamicPage(res.SiteProfile.URL,cts.Token); // this parses the dom once loaded (awaits for the page) ProcessSiteProfile(); Next(); } } // navigate and download async Task<string> LoadDynamicPage(string url,CancellationToken token) { // navigate and await DocumentCompleted var tcs = new TaskCompletionSource<bool>(); WebBrowserDocumentCompletedEventHandler handler = (s,arg) => tcs.TrySetResult(true); // i'm keeping the tcs in a concurrentdictionary against the browser object // again,this is pretty dirty but obviously felt like i needed it. _browserTasks[_browser] = tcs; using (token.Register(() => tcs.TrySetCanceled(),useSynchronizationContext: true)) { // nav to page async this._browser.DocumentCompleted += handler; try { if (!string.IsNullOrWhiteSpace(url)) { this._browser.Navigate(url); await tcs.Task; // wait for DocumentCompleted } } finally { this._browser.DocumentCompleted -= handler; } } // get the root element var documentElement = this._browser.Document.GetElementsByTagName("html")[0]; // poll the current HTML for changes asynchronosly var html = documentElement.OuterHtml; while (true) { // wait asynchronously,this will throw if cancellation requested await Task.Delay(Properties.Settings.Default.BrowserNavigationWait,token); // continue polling if the WebBrowser is still busy if (this._browser.IsBusy) continue; var htmlNow = documentElement.OuterHtml; if (html == htmlNow) break; // no changes detected,end the poll loop html = htmlNow; } // consider the page fully rendered token.ThrowIfCancellationRequested(); // remove from task dictionary _browserTasks[this._browser] = null; return html; } async void ProcessSiteProfile() { // now process submission HtmlElement parentForm = null; ///////////////// // parse dom to find the form you're looking for // couple of helpers below /////////////////////// parentForm = HtmlElementQuery(_browser.Document,"myTextFieldInput"); var sub = (_browser.Tag as Submission); HtmlDocument doc = _browser.Document; if (parentForm != null) { var elements = parentForm.GetElementsByTagName("input"); foreach (HtmlElement el in elements) { // If there's more than one button,you can check the // element.InnerHTML to see if it's the one you want if (el.GetAttribute("type").ToLower() == "submit") { var cts = new CancellationTokenSource(Properties.Settings.Default.BrowserNavigationTimeout); // cancel in 10s var html = await RaiseDynamicEvent(el,"click",cts.Token); } } } } // used to raise an event with a dom element that would cause the document to change async Task<string> RaiseDynamicEvent(HtmlElement element,string evt,arg) => tcs.TrySetResult(true); _browserTasks[_browser] = tcs; using (token.Register(() => tcs.TrySetCanceled(),useSynchronizationContext: true)) { this._browser.DocumentCompleted += handler; try { element.InvokeMember(evt); try { await tcs.Task; // wait for DocumentCompleted } catch (TaskCanceledException) { // no the end of the world } } finally { this._browser.DocumentCompleted -= handler; } } // get the root element var documentElement = this._browser.Document.GetElementsByTagName("html")[0]; // poll the current HTML for changes asynchronosly var html = documentElement.OuterHtml; while (true) { // wait asynchronously,this will throw if cancellation requested await Task.Delay(500,end the poll loop html = htmlNow; } // consider the page fully rendered token.ThrowIfCancellationRequested(); // remove from task dictionary _browserTasks[this._browser] = null; return html; } // couple of useful helpers HtmlElement FindParentByElement(string elementName,HtmlElement element) { if (element.Parent != null) { if (element.Parent.TagName.ToLower() == elementName.ToLower()) { return element.Parent; } else { return FindParentByElement(elementName,element.Parent); } } else { return null; } } HtmlElement HtmlElementQuery(HtmlDocument container,string query) { HtmlElement el = null; if (query.StartsWith("#")) { el = container.GetElementById(query.TrimStart('#')); } else { el = container.All[query]; } return el; }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。