gpt4 book ai didi

c# - 表单上的 InvokeMember ("submit") 不重定向浏览器

转载 作者:行者123 更新时间:2023-11-30 12:46:00 24 4
gpt4 key购买 nike

我正在使用 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 事件将在加载重定向页面后触发。相反,加载相同的页面(带有表单)。

有什么我想念的吗?

谢谢

最佳答案

好的,抱歉耽搁了,我去忙别的事了......

无论如何,它真的很粗糙,但您应该能够选择您需要的部分。

最初的想法来自Noseratio找到 here .

raisedynamicevent 方法的工作方式与异步导航类似,通过在事件发生后监视文档的状态。再次确定时,返回。应该处理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, CancellationToken token)
{
// navigate and await DocumentCompleted
var tcs = new TaskCompletionSource<bool>();
WebBrowserDocumentCompletedEventHandler handler = (s, 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, 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;
}

// 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;
}

关于c# - 表单上的 InvokeMember ("submit") 不重定向浏览器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21751062/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com