表单上的InvokeMember(“ submit”)不会重定向浏览器

三宝汀

我正在使用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");
 }

提交后(按预期工作),我本以为加载重定向页面后将触发下一个documentcomplete事件。相反,将加载同一页(带有表单)。

有什么我想念的吗?

谢谢

三宝汀

好的,抱歉,我继续尝试其他事情。

无论如何,这确实很粗糙,但是您应该能够选择所需的钻头。

最初的想法是从Noseratio这里找到的

通过在事件后监视文档的状态,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;
    }

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

表单上的InvokeMember(“ submit”)不会重定向浏览器

来自分类Dev

如何重定向到特定浏览器上的页面?

来自分类Dev

在浏览器中以角度重定向和返回时保持表单值

来自分类Dev

ASP.NET MVC 3-仅在某些浏览器上重定向循环

来自分类Dev

当我从网址重定向时,Android应用程序已在浏览器上打开

来自分类Dev

重定向到浏览器刷新按钮上的其他页面,请单击

来自分类Dev

AngularJS仅在浏览器的后退按钮上重定向路由

来自分类Dev

ASP.NET MVC 3-仅在某些浏览器上重定向循环

来自分类Dev

浏览器是否在安全站点上遵循从HTTP到HTTPS的301重定向?

来自分类Dev

ASP.NET MVC网站被重定向到本地IIS,而不是在任何浏览器上的IIS Express

来自分类Dev

Nginx重定向可在浏览器上使用,但使用curl时,它仅输出301永久移动

来自分类Dev

Azure上的重定向规则将浏览器重定向到app.js文件

来自分类Dev

在注册表单上,表单字段不会在提交时自动保存在浏览器中。(ReactJs)

来自分类Dev

e.preventDefault不会停止表单上的重定向

来自分类Dev

为什么浏览器不遵循HTTP 302重定向来呈现渲染的GitHub README.md上的图像资源?

来自分类Dev

提交表单上的浏览器缓存问题

来自分类Dev

如何在浏览器上输出Django表单

来自分类Dev

由于浏览器版本而重定向

来自分类Dev

防止从浏览器栏重定向

来自分类Dev

通过浏览器后退按钮访问表单不会触发“确认表单重新提交”

来自分类Dev

Spring重定向不会将浏览器URL更改为适当的URL

来自分类Dev

如果使用了CORS,Edge浏览器不会重定向呼叫

来自分类Dev

重定向后浏览器不会从带有www的域发送cookie

来自分类Dev

Spring重定向不会将浏览器URL更改为适当的URL

来自分类Dev

JavaScript发布表单不会重定向

来自分类Dev

在Django上保存表单后重定向

来自分类Dev

表单POST上的OpenIdConnect重定向

来自分类Dev

浏览器自动填写表单字段时,不会触发$ parsers \ $ formatters函数

来自分类Dev

Windows上的Web浏览器中不会显示流浪汉服务器的内容

Related 相关文章

  1. 1

    表单上的InvokeMember(“ submit”)不会重定向浏览器

  2. 2

    如何重定向到特定浏览器上的页面?

  3. 3

    在浏览器中以角度重定向和返回时保持表单值

  4. 4

    ASP.NET MVC 3-仅在某些浏览器上重定向循环

  5. 5

    当我从网址重定向时,Android应用程序已在浏览器上打开

  6. 6

    重定向到浏览器刷新按钮上的其他页面,请单击

  7. 7

    AngularJS仅在浏览器的后退按钮上重定向路由

  8. 8

    ASP.NET MVC 3-仅在某些浏览器上重定向循环

  9. 9

    浏览器是否在安全站点上遵循从HTTP到HTTPS的301重定向?

  10. 10

    ASP.NET MVC网站被重定向到本地IIS,而不是在任何浏览器上的IIS Express

  11. 11

    Nginx重定向可在浏览器上使用,但使用curl时,它仅输出301永久移动

  12. 12

    Azure上的重定向规则将浏览器重定向到app.js文件

  13. 13

    在注册表单上,表单字段不会在提交时自动保存在浏览器中。(ReactJs)

  14. 14

    e.preventDefault不会停止表单上的重定向

  15. 15

    为什么浏览器不遵循HTTP 302重定向来呈现渲染的GitHub README.md上的图像资源?

  16. 16

    提交表单上的浏览器缓存问题

  17. 17

    如何在浏览器上输出Django表单

  18. 18

    由于浏览器版本而重定向

  19. 19

    防止从浏览器栏重定向

  20. 20

    通过浏览器后退按钮访问表单不会触发“确认表单重新提交”

  21. 21

    Spring重定向不会将浏览器URL更改为适当的URL

  22. 22

    如果使用了CORS,Edge浏览器不会重定向呼叫

  23. 23

    重定向后浏览器不会从带有www的域发送cookie

  24. 24

    Spring重定向不会将浏览器URL更改为适当的URL

  25. 25

    JavaScript发布表单不会重定向

  26. 26

    在Django上保存表单后重定向

  27. 27

    表单POST上的OpenIdConnect重定向

  28. 28

    浏览器自动填写表单字段时,不会触发$ parsers \ $ formatters函数

  29. 29

    Windows上的Web浏览器中不会显示流浪汉服务器的内容

热门标签

归档