• 背水一战 Windows 10 (64)


    [源码下载]


    背水一战 Windows 10 (64) - 控件(WebView): 加载指定 HttpMethod 的请求, 自定义请求的 http header, app 与 js 的交互



    作者:webabcd


    介绍
    背水一战 Windows 10 之 控件(WebView)

    • 加载指定 HttpMethod 的请求
    • 自定义请求的 http header
    • app 与 js 的交互



    示例
    1、演示 WebView 如何加载指定 HttpMethod 的请求以及如何自定义请求的 http header
    WebApi/Controllers/WebViewPostController.cs

    /*
     * 用于 WebView 演示“如何加载指定 HttpMethod 的请求,以及如何自定义请求的 http header”
     */
    
    using System.IO;
    using System.Linq;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web.Http;
    
    namespace WebApi.Controllers
    {
        public class WebViewPostController : ApiController
        {
            [HttpPost]
            public async Task<HttpResponseMessage> Post()
            {
                Stream stream = await this.Request.Content.ReadAsStreamAsync();
                StreamReader sr = new StreamReader(stream);
                string postData = sr.ReadToEnd();
                sr.Dispose();
    
                string myHeader = this.Request.Headers.GetValues("myHeader").FirstOrDefault();
    
                HttpResponseMessage result = new HttpResponseMessage
                {
                    Content = new StringContent($"post data: {postData}<br /> myHeader: {myHeader}", Encoding.UTF8, "text/html")
                };
    
                return result;
            }
        }
    }

    Controls/WebViewDemo/WebViewDemo3.xaml

    <Page
        x:Class="Windows10.Controls.WebViewDemo.WebViewDemo3"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.Controls.WebViewDemo"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="Transparent">
            <StackPanel Margin="10 0 0 0">
    
                <WebView Name="webView" Width="800" Height="300" HorizontalAlignment="Left" />
    
            </StackPanel>
        </Grid>
    </Page>

    Controls/WebViewDemo/WebViewDemo3.xaml.cs

    /*
     * WebView - 内嵌浏览器控件(继承自 FrameworkElement, 请参见 /Controls/BaseControl/FrameworkElementDemo/)
     *     
     *     
     * 本例用于演示 
     * 1、WebView 如何加载指定 HttpMethod 的请求
     * 2、WebView 如何自定义请求的 http header
     */
     
    using System;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.Web.Http;
    
    namespace Windows10.Controls.WebViewDemo
    {
        public sealed partial class WebViewDemo3 : Page
        {
            public WebViewDemo3()
            {
                this.InitializeComponent();
    
                this.Loaded += WebViewDemo3_Loaded;
            }
    
            private void WebViewDemo3_Loaded(object sender, RoutedEventArgs e)
            {
                // 实例化 HttpRequestMessage(可以指定请求的 HttpMethod 以及自定义请求的 http header)
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("http://localhost:44914/api/webviewpost"));
    
                // 构造 post 数据
                httpRequestMessage.Content = new HttpStringContent("hello webabcd");
    
                // 自定义 http header
                httpRequestMessage.Headers.Append("myHeader", "hello header");
    
                // 通过 NavigateWithHttpRequestMessage 加载指定的 HttpRequestMessage 对象
                webView.NavigateWithHttpRequestMessage(httpRequestMessage);
            }
        }
    }


    2、演示 app 与 js 的交互
    MyRuntimeComponent/JS2WRC.cs

    /*
     * 用于演示 javascript 调用 windows runtime component 中定义的方法
     */
    
    using Windows.Foundation.Metadata;
    
    namespace MyRuntimeComponent
    {
        [AllowForWeb] // 允许 js 调用
        public sealed class JS2WRC // 注意:在 winrc 中用 c# 写的类必须是 sealed 的
        {
            public string hello(string name)
            {
                return $"hello: {name}";
            }
        }
    }

    Controls/WebViewDemo/WebViewJavaScript.html

    <!--此 html 用于演示 app 与 js 间的交互-->
    
    <!doctype html>
    <html>
    <head>
        <title>i am title</title>
        <script type='text/javascript'>
    
            // app 调用 js 函数
            function appToJs(name) {
                return 'app to js: ' + name;
            }
    
            // js 传递数据到 app
            function jsToApp() {
                window.external.notify('js to app');
            }
    
            // js 调用 wrc
            function jsToWRC() {
                if (window.js2wrc_object) {
                    // js 调用 wrc(在 windows runtime component 中定义的方法)
                    var result = js2wrc_object.hello("webabcd");
                    document.getElementById("div").innerHTML = result;
                }
            }
    
            // 弹出 alert 框
            function showAlert() {
                // 在 uwp 的 webview 中是不能弹出 alert 框的(可以在 c# 中拐弯抹角的实现,参见本例的 c# 端的代码)
                alert("hello: alert");
            }
    
        </script>
    </head>
    <body>
        
        <p>
            <input type='button' onclick='jsToApp();' value='js 传递数据到 app' />
        </p>
    
        <p>
            <input type='button' onclick='jsToWRC();' value='js 调用 wrc' />
        </p>
    
        <p>
            <div id="div"></div>
        </p>
    
        <p>
            <input type='button' onclick='showAlert();' value='弹出 alert 框' />
        </p>
        
    </body>
    </html>

    Controls/WebViewDemo/WebViewDemo4.xaml

    <Page
        x:Class="Windows10.Controls.WebViewDemo.WebViewDemo4"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.Controls.WebViewDemo"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="Transparent">
            <StackPanel Margin="10 0 10 10">
    
                <TextBlock Name="lblMsg" Margin="5" />
    
                <Button Name="btnAppToJavaScript" Content="app 调用 WebView 加载的 html 中的 JavaScript 函数" Click="btnAppToJavaScript_Click" Margin="5" />
    
                <Button Name="btnEval" Content="通过 eval 访问 DOM" Click="btnEval_Click" Margin="5" />
    
                <Button Name="btnRegisterJavaScript" Content="通过 eval 向 html 注册 JavaScript 脚本" Click="btnRegisterJavaScript_Click" Margin="5" />
    
                <!--
                    通过 ms-appx-web 加载包内的 html 页面
                -->
                <WebView Name="webView" Width="480" Height="320" Source="ms-appx-web:///Controls/WebViewDemo/WebViewJavaScript.html" HorizontalAlignment="Left" Margin="5" 
                         NavigationStarting="WebView_NavigationStarting" NavigationCompleted="WebView_NavigationCompleted" />
    
            </StackPanel>
        </Grid>
    </Page>

    Controls/WebViewDemo/WebViewDemo4.xaml.cs

    /*
     * WebView - 内嵌浏览器控件(继承自 FrameworkElement, 请参见 /Controls/BaseControl/FrameworkElementDemo/)
     *     InvokeScriptAsync() - 调用指定的 js 函数,并返回 js 函数的返回值
     *     ScriptNotify - 收到 js 通过 window.external.notify('') 传递过来的数据时触发的事件
     *     AllowedScriptNotifyUris - 允许触发 ScriptNotify 事件的 uri 列表
     *     AddWebAllowedObject() - 将 windows runtime component 中定义的对象注册到 WebView 加载的页面(需要在 WebView 的 NavigationStarting 事件中调用)
     *
     * 
     * 本例用于演示
     * 1、app 与 js 的交互
     * 2、如何将 windows runtime component 中定义的对象注册到 WebView 加载的页面,以便通过 js 调用 wrc
     */
    
    /*
     * 特别注意:各种 uri schema 对于 ScriptNotify 的支持情况如下
     * 1、http:// 不支持
     * 2、https:// 支持,需要在 appxmanifest 中设置允许的 URI(http 的不行,只能是 https 的),也可以通过 WebView 的 AllowedScriptNotifyUris 属性来设置或获取
     *    <ApplicationContentUriRules>
     *       <Rule Match="https://aaa.aaa.aaa" Type="include" />
     *    </ApplicationContentUriRules>
     * 3、ms-appdata:/// 不支持
     * 4、ms-appx-web:/// 支持
     * 5、ms-local-stream:// 支持
     */
    
    using System;
    using System.Collections.Generic;
    using Windows.UI;
    using Windows.UI.Popups;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    
    namespace Windows10.Controls.WebViewDemo
    {
        public sealed partial class WebViewDemo4 : Page
        {
            public WebViewDemo4()
            {
                this.InitializeComponent();
    
                webView.ScriptNotify += webView_ScriptNotify;
                webView.NavigationCompleted += webView_NavigationCompleted;
    
                // 由于本例的 webview 是在 xaml 中声明并指定需要加载的 html 的,所以对于 NavigationStarting 事件的注册来说要在 xaml 做
                // webView.NavigationStarting += WebView_NavigationStarting;
            }
    
            void webView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
            {
                if (args.IsSuccess)
                {
                    // 获取 html 标题
                    lblMsg.Text = "html title: " + webView.DocumentTitle;
                    lblMsg.Text += Environment.NewLine;
    
                    // 获取或设置 html 背景色
                    webView.DefaultBackgroundColor = Colors.Orange;
                    lblMsg.Text += "html backgroundColor: " + webView.DefaultBackgroundColor.ToString();
                }
            }
    
            // 收到 js 通过 window.external.notify('') 传递过来的数据时触发的事件
            private async void webView_ScriptNotify(object sender, NotifyEventArgs e)
            {
                // e.Value - 获取 js 传递过来的数据
                // e.CallingUri - 触发此事件的页面的 uri
    
                if (e.Value.StartsWith("alert:"))
                {
                    // 模拟弹出页面的 alert 框(参见下面的 WebView_NavigationCompleted 中的代码)
                    await new MessageDialog(e.Value.Substring(6), "alert").ShowAsync();
                }
                else
                {
                    await new MessageDialog(e.CallingUri.ToString() + " " + e.Value).ShowAsync();
                }
            }
    
            // app 调用 js
            private async void btnAppToJavaScript_Click(object sender, RoutedEventArgs e)
            {
                List<string> arguments = new List<string> { "webabcd" };
                // 调用 js 方法:sayHelloToJs('webabcd'); 并返回结果
                string result = await webView.InvokeScriptAsync("appToJs", arguments);
    
                await new MessageDialog(result).ShowAsync();
            }
    
            // 通过 eval 访问 DOM
            private async void btnEval_Click(object sender, RoutedEventArgs e)
            {
                // 设置 document.title 的值(用于演示如何通过 eval 设置 DOM)
                List<string> arguments = new List<string> { "document.title = 'hahaha';" };
                await webView.InvokeScriptAsync("eval", arguments);
    
                // 获取 document.title 的值(用于演示如何通过 eval 获取 DOM)
                arguments = new List<string> { "document.title;" };
                string result = await webView.InvokeScriptAsync("eval", arguments);
                await new MessageDialog(result).ShowAsync();
            }
    
            // 通过 eval 向 html 注册 JavaScript 脚本
            private async void btnRegisterJavaScript_Click(object sender, RoutedEventArgs e)
            {
                // 向 html 注册脚本
                List<string> arguments = new List<string> { "function xxx(){return '由 app 向 html 注册的脚本返回的数据';}" };
                await webView.InvokeScriptAsync("eval", arguments);
    
                // 调用刚刚注册的脚本
                string result = await webView.InvokeScriptAsync("xxx", null);
    
                await new MessageDialog(result).ShowAsync();
            }
    
            // js 调用 wrc
            private void WebView_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
            {
                // 注意:需要在 WebView 的 NavigationStarting 事件中调用 AddWebAllowedObject()
                webView.AddWebAllowedObject("js2wrc_object", new MyRuntimeComponent.JS2WRC());
            }
    
            // 模拟弹出页面的 alert 框
            private async void WebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
            {
                // 在 uwp 的 webview 中是不能弹出 alert 框的
                // 可以向页面注入脚本重写 window.alert 函数,使其调用 window.external.notify 通知 c# 端,然后弹出 MessageDialog 框以模拟页面的 alert 框(参见上面的 webView_ScriptNotify 中的代码)
                // 在 uwp 的 webview 中也是不能弹出 confirm 框的,也不能像实现 alert 框那样如法炮制,因为 JavaScript 是运行在单线程上的,其不会等待 c# 调用的结果,所以如何实现 confirm 框还是另想办法吧
                await webView.InvokeScriptAsync("eval", new string[] { "window.alert = function (alertMessage) {window.external.notify('alert:' + alertMessage)}" });
            }
        }
    }



    OK
    [源码下载]

  • 相关阅读:
    3. Longest Substring Without Repeating Characters
    2. Add Two Numbers
    Concurrent Programming(5)
    Concurrent Programming(4)
    Concurrent Programming(3)
    Concurrent Programming(2)
    Concurrent Programming(1)
    Lua用table模拟二维数组
    C#深入研究ArrayList动态数组自动扩容原理
    ==与Equals的作用
  • 原文地址:https://www.cnblogs.com/webabcd/p/7541327.html
Copyright © 2020-2023  润新知