在WinForms应用程序中使用WebView2以POST方式发送JSON数据,是实现与特定Web API交互、提交表单数据或进行其他需要POST方法的操作的常见需求。本文将详细介绍如何在WinForms中使用WebView2控件执行POST请求,包括使用NavigateWithWebResourceRequest方法和通过JavaScript执行POST请求的两种主要方法。


目录

  1. 前提条件

  2. 方法一:使用 NavigateWithWebResourceRequest 执行POST请求

  3. 方法二:通过JavaScript在WebView2中执行POST请求

  4. 完整示例:在WinForms中集成WebView2并执行POST请求

  5. 注意事项

  6. 常见问题及解决方法

  7. 参考资料

  8. 总结


1. 前提条件

在开始之前,请确保已经完成以下准备工作:

  • WebView2 控件已成功添加到 WinForms 项目中:确保WebView2控件已正确集成。

  • 安装WebView2运行时:确保系统中安装了WebView2运行时。

  • 项目目标框架:建议使用 .NET Framework 4.6.2 及以上,或 .NET Core/5+/6+。


2. 方法一:使用 NavigateWithWebResourceRequest 执行POST请求

NavigateWithWebResourceRequest 方法允许构建一个完整的HTTP请求,包括请求方法(如POST)、请求头和请求正文,从而实现更灵活的导航和数据提交。

步骤概述

  1. 创建CoreWebView2WebResourceRequest对象,配置HTTP方法、URL、请求头和请求内容。

  2. 调用NavigateWithWebResourceRequest方法,传递构建的请求对象。

  3. 处理导航完成后的响应,如获取响应状态或内容。

示例代码

以下示例展示如何在WinForms应用程序中使用WebView2控件执行一个简单的POST请求,将数据发送到目标URL。

代码示例(C#)

using System;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Windows.Forms;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;

namespace WebView2PostExample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitializeAsync();
        }

        private async void InitializeAsync()
        {
            try
            {
                // 初始化 WebView2
                await webView21.EnsureCoreWebView2Async(null);

                // 订阅导航完成事件(可选)
                webView21.CoreWebView2.NavigationCompleted += CoreWebView2_NavigationCompleted;

                // 导航到初始页面(可选)
                webView21.CoreWebView2.Navigate("https://www.example.com"); // 替换为初始URL
            }
            catch (Exception ex)
            {
                MessageBox.Show($"WebView2 初始化失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private async void btnPost_Click(object sender, EventArgs e)
        {
            try
            {
                // 确保WebView2已初始化
                if (webView21.CoreWebView2 == null)
                {
                    MessageBox.Show("WebView2尚未初始化。请稍候再试。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                // 构建POST数据(示例为JSON格式)
                var postData = new
                {
                    name = "张三",
                    age = 30
                };
                string json = JsonSerializer.Serialize(postData);
                byte[] dataBytes = Encoding.UTF8.GetBytes(json);
                var stream = new MemoryStream(dataBytes);

                // 创建请求
                var request = webView21.CoreWebView2.Environment.CreateWebResourceRequest(
                    "https://www.example.com/api", // 替换为目标URL
                    "POST",
                    stream,
                    "Content-Type: application/json");

                // 执行POST请求
                webView21.CoreWebView2.NavigateWithWebResourceRequest(request);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"执行POST请求失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void CoreWebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
        {
            if (e.IsSuccess)
            {
                // 可选:获取响应状态
                Console.WriteLine("导航完成,加载成功。");
            }
            else
            {
                MessageBox.Show($"导航失败,错误代码: {e.WebErrorStatus}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

设计器文件(Form1.Designer.cs)

确保Form1.Designer.cs包含WebView2控件和一个按钮用于触发POST请求。

namespace WebView2PostExample
{
    partial class Form1
    {
        private Microsoft.Web.WebView2.WinForms.WebView2 webView21;
        private System.Windows.Forms.Button btnPost;

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
            this.btnPost = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.webView21)).BeginInit();
            this.SuspendLayout();
            // 
            // webView21
            // 
            this.webView21.CreationProperties = null;
            this.webView21.DefaultBackgroundColor = System.Drawing.Color.White;
            this.webView21.Location = new System.Drawing.Point(12, 12);
            this.webView21.Name = "webView21";
            this.webView21.Size = new System.Drawing.Size(776, 400);
            this.webView21.TabIndex = 0;
            this.webView21.ZoomFactor = 1D;
            // 
            // btnPost
            // 
            this.btnPost.Location = new System.Drawing.Point(12, 420);
            this.btnPost.Name = "btnPost";
            this.btnPost.Size = new System.Drawing.Size(100, 30);
            this.btnPost.TabIndex = 1;
            this.btnPost.Text = "执行POST";
            this.btnPost.UseVisualStyleBackColor = true;
            this.btnPost.Click += new System.EventHandler(this.btnPost_Click);
            // 
            // Form1
            // 
            this.ClientSize = new System.Drawing.Size(800, 462);
            this.Controls.Add(this.btnPost);
            this.Controls.Add(this.webView21);
            this.Name = "Form1";
            this.Text = "WebView2 执行POST请求示例";
            ((System.ComponentModel.ISupportInitialize)(this.webView21)).EndInit();
            this.ResumeLayout(false);
        }
    }
}

代码解释

  1. 初始化WebView2控件

    await webView21.EnsureCoreWebView2Async(null);
    

    确保WebView2控件已初始化。

  2. 构建POST数据

    var postData = new
    {
        name = "张三",
        age = 30
    };
    string json = JsonSerializer.Serialize(postData);
    byte[] dataBytes = Encoding.UTF8.GetBytes(json);
    var stream = new MemoryStream(dataBytes);
    

    构建要发送的JSON数据,并转换为MemoryStream

  3. 创建WebResourceRequest对象

    var request = webView21.CoreWebView2.Environment.CreateWebResourceRequest(
        "https://www.example.com/api", // 替换为目标URL
        "POST",
        stream,
        "Content-Type: application/json");
    

    创建一个POST请求,设置目标URL、请求方法、请求内容和请求头。

  4. 执行POST请求

    webView21.CoreWebView2.NavigateWithWebResourceRequest(request);
    

    使用NavigateWithWebResourceRequest方法执行构建的POST请求。

  5. 处理导航完成事件

    private void CoreWebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
    {
        if (e.IsSuccess)
        {
            // 可选:获取响应状态
            Console.WriteLine("导航完成,加载成功。");
        }
        else
        {
            MessageBox.Show($"导航失败,错误代码: {e.WebErrorStatus}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
    

    订阅并处理导航完成事件,可以在此处进一步处理响应内容(需额外实现)。

注意事项

  • URL和内容类型:确保目标URL正确,且Content-Type与发送的数据格式匹配(如application/json)。

  • 跨域请求:如果目标URL与当前页面不同域,可能会遇到跨域限制。

  • 错误处理:在实际应用中,应增加更多的错误处理和异常捕获机制。

  • 响应处理NavigateWithWebResourceRequest 方法不直接返回响应内容。如果需要获取响应内容,需要使用其他方法,如拦截网络请求。


3. 方法二:通过JavaScript在WebView2中执行POST请求

除了使用NavigateWithWebResourceRequest方法,还可以通过在WebView2中执行JavaScript代码(如使用Fetch API或XMLHttpRequest)来执行POST请求。这种方法适用于需要在网页上下文中执行复杂交互或获取响应内容的场景。

步骤概述

  1. 在WebView2中注入并执行JavaScript代码,使用Fetch API或XMLHttpRequest发送POST请求。

  2. 通过WebView2的WebMessageReceived事件接收从网页传回的响应数据。

  3. 处理接收到的数据,如显示在WinForms应用中或进行其他操作。

示例代码

以下示例展示如何在WinForms应用程序中使用WebView2控件,通过JavaScript执行POST请求,并将响应结果传回应用程序。

代码示例(C#)

using System;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;

namespace WebView2PostExample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitializeAsync();
        }

        private async void InitializeAsync()
        {
            try
            {
                // 初始化 WebView2
                await webView21.EnsureCoreWebView2Async(null);

                // 订阅 WebMessageReceived 事件
                webView21.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;

                // 导航到一个空白页,准备执行JavaScript
                webView21.CoreWebView2.NavigateToString("<html><body></body></html>");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"WebView2 初始化失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private async void btnPost_Click(object sender, EventArgs e)
        {
            try
            {
                // 确保WebView2已初始化
                if (webView21.CoreWebView2 == null)
                {
                    MessageBox.Show("WebView2尚未初始化。请稍候再试。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                // 构建POST数据(示例为JSON格式)
                var postData = new
                {
                    name = "张三",
                    age = 30
                };
                string json = JsonSerializer.Serialize(postData);

                // 构建JavaScript代码,使用Fetch API发送POST请求
                string script = $@"
                    fetch('https://www.example.com/api', {{
                        method: 'POST',
                        headers: {{
                            'Content-Type': 'application/json'
                        }},
                        body: '{json}'
                    }})
                    .then(response => response.json())
                    .then(data => {{
                        window.chrome.webview.postMessage(JSON.stringify(data));
                    }})
                    .catch(error => {{
                        window.chrome.webview.postMessage(JSON.stringify({{ error: error.message }}));
                    }});
                ";

                // 执行JavaScript代码
                await webView21.CoreWebView2.ExecuteScriptAsync(script);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"执行POST请求失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
        {
            try
            {
                string message = e.TryGetWebMessageAsString();
                var response = JsonSerializer.Deserialize<Dictionary<string, object>>(message);

                if (response.ContainsKey("error"))
                {
                    MessageBox.Show($"POST请求错误: {response["error"]}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    // 处理成功响应
                    string jsonResponse = JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = true });
                    textBoxHtml.Text = jsonResponse;
                    MessageBox.Show("成功获取POST响应!", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"处理响应失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

设计器文件(Form1.Designer.cs)

确保Form1.Designer.cs包含WebView2控件、一个按钮用于触发POST请求和一个文本框用于显示响应内容。

namespace WebView2PostExample
{
    partial class Form1
    {
        private Microsoft.Web.WebView2.WinForms.WebView2 webView21;
        private System.Windows.Forms.Button btnPost;
        private System.Windows.Forms.TextBox textBoxHtml;

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
            this.btnPost = new System.Windows.Forms.Button();
            this.textBoxHtml = new System.Windows.Forms.TextBox();
            ((System.ComponentModel.ISupportInitialize)(this.webView21)).BeginInit();
            this.SuspendLayout();
            // 
            // webView21
            // 
            this.webView21.CreationProperties = null;
            this.webView21.DefaultBackgroundColor = System.Drawing.Color.White;
            this.webView21.Location = new System.Drawing.Point(12, 12);
            this.webView21.Name = "webView21";
            this.webView21.Size = new System.Drawing.Size(776, 300);
            this.webView21.TabIndex = 0;
            this.webView21.ZoomFactor = 1D;
            // 
            // btnPost
            // 
            this.btnPost.Location = new System.Drawing.Point(12, 318);
            this.btnPost.Name = "btnPost";
            this.btnPost.Size = new System.Drawing.Size(100, 30);
            this.btnPost.TabIndex = 1;
            this.btnPost.Text = "执行POST";
            this.btnPost.UseVisualStyleBackColor = true;
            this.btnPost.Click += new System.EventHandler(this.btnPost_Click);
            // 
            // textBoxHtml
            // 
            this.textBoxHtml.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
                                                                            | System.Windows.Forms.AnchorStyles.Left) 
                                                                            | System.Windows.Forms.AnchorStyles.Right)));
            this.textBoxHtml.Location = new System.Drawing.Point(12, 354);
            this.textBoxHtml.Multiline = true;
            this.textBoxHtml.Name = "textBoxHtml";
            this.textBoxHtml.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.textBoxHtml.Size = new System.Drawing.Size(776, 84);
            this.textBoxHtml.TabIndex = 2;
            // 
            // Form1
            // 
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.textBoxHtml);
            this.Controls.Add(this.btnPost);
            this.Controls.Add(this.webView21);
            this.Name = "Form1";
            this.Text = "WebView2 执行POST请求示例";
            ((System.ComponentModel.ISupportInitialize)(this.webView21)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();
        }
    }
}

代码解释

  1. 初始化WebView2控件

    await webView21.EnsureCoreWebView2Async(null);
    webView21.CoreWebView2.NavigateToString("<html><body></body></html>");
    

    使用NavigateToString导航到一个空白页,为执行JavaScript做好准备。

  2. 按钮点击事件处理

    private async void btnPost_Click(object sender, EventArgs e)
    {
        try
        {
            // 确保WebView2已初始化
            if (webView21.CoreWebView2 == null)
            {
                MessageBox.Show("WebView2尚未初始化。请稍候再试。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
    
            // 构建POST数据(示例为JSON格式)
            var postData = new
            {
                name = "张三",
                age = 30
            };
            string json = JsonSerializer.Serialize(postData);
    
            // 构建JavaScript代码,使用Fetch API发送POST请求
            string script = $@"
                fetch('https://www.example.com/api', {{
                    method: 'POST',
                    headers: {{
                        'Content-Type': 'application/json'
                    }},
                    body: '{json}'
                }})
                .then(response => response.json())
                .then(data => {{
                    window.chrome.webview.postMessage(JSON.stringify(data));
                }})
                .catch(error => {{
                    window.chrome.webview.postMessage(JSON.stringify({{ error: error.message }}));
                }});
            ";
    
            // 执行JavaScript代码
            await webView21.CoreWebView2.ExecuteScriptAsync(script);
        }
        catch (Exception ex)
        {
            MessageBox.Show($"执行POST请求失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
    
    • 构建POST数据:创建要发送的数据,并序列化为JSON字符串。

    • 构建JavaScript代码:使用Fetch API发送POST请求,设置请求头和请求体。

    • 发送消息:通过window.chrome.webview.postMessage将响应数据传回C#应用程序。

    • 执行脚本:使用ExecuteScriptAsync方法在WebView2中执行JavaScript代码。

  3. 处理WebMessageReceived事件

    private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
    {
        try
        {
            string message = e.TryGetWebMessageAsString();
            var response = JsonSerializer.Deserialize<Dictionary<string, object>>(message);
    
            if (response.ContainsKey("error"))
            {
                MessageBox.Show($"POST请求错误: {response["error"]}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                // 处理成功响应
                string jsonResponse = JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = true });
                textBoxHtml.Text = jsonResponse;
                MessageBox.Show("成功获取POST响应!", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"处理响应失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
    
    • 接收消息:通过WebMessageReceived事件接收来自网页的消息。

    • 解析消息:将接收到的JSON字符串反序列化为字典对象。

    • 处理响应:根据响应内容显示消息或错误信息。

注意事项

  • 跨域限制:确保目标URL允许跨域POST请求,否则可能会遇到CORS(跨域资源共享)问题。

  • 安全性:仅在受信任的网页上执行JavaScript代码,避免潜在的安全风险。

  • 响应处理:根据实际需求,可能需要进一步处理响应数据,如错误处理、数据解析等。

  • 字符转义:在构建JavaScript代码时,确保JSON字符串中的特殊字符(如单引号)已正确转义,以避免JavaScript语法错误。


4. 完整示例:在WinForms中集成WebView2并执行POST请求

为了更清晰地展示如何在WinForms应用程序中集成WebView2控件并执行POST请求,以下是一个完整的示例项目。

步骤1:创建新的WinForms项目

  1. 打开Visual Studio

  2. 创建新项目

    • 选择 “Windows Forms 应用程序 (.NET Framework)”“.NET Core”,点击 “下一步”

    • 配置项目名称(例如 WebView2PostExample)和位置,点击 “创建”

步骤2:安装WebView2 NuGet包

  1. 打开NuGet包管理器

    • 右键点击项目,选择 “管理NuGet程序包…”

  2. 搜索并安装Microsoft.Web.WebView2

    • “浏览” 标签下,搜索 Microsoft.Web.WebView2

    • 选择 Microsoft.Web.WebView2 包(由Microsoft发布),点击 “安装”

    • 接受许可协议,等待安装完成。

步骤3:设计界面

  1. 打开设计器视图

    • 在解决方案资源管理器中,双击 Form1.cs,进入设计器视图。

  2. 添加WebView2控件

    • 如果WebView2控件已显示在工具箱中,直接拖放到窗体上。

    • 否则,手动添加:

      • 右键点击 “工具箱”,选择 “选择项…”

      • “.NET Framework 组件” 选项卡中,找到 Microsoft.Web.WebView2.WinForms.WebView2

      • 勾选该控件,点击 “确定”

    • 将WebView2控件调整为适合窗体的大小。

  3. 添加按钮控件

    • 从工具箱中拖放一个 Button 控件到窗体上。

    • 设置按钮的属性:

      • NamebtnPost

      • Text执行POST

    • 将按钮放置在WebView2控件的下方或适当位置。

  4. 添加文本框控件

    • 从工具箱中拖放一个 TextBox 控件到窗体上。

    • 设置文本框的属性:

      • NametextBoxHtml

      • MultilineTrue

      • ScrollBarsVertical

      • DockBottom 或根据需要调整位置。

    • 调整文本框的大小以适应显示响应内容。

步骤4:编写代码

Form1.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Windows.Forms;
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;

namespace WebView2PostExample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitializeAsync();
        }

        private async void InitializeAsync()
        {
            try
            {
                // 初始化 WebView2
                await webView21.EnsureCoreWebView2Async(null);

                // 导航到初始页面(可选)
                webView21.CoreWebView2.Navigate("https://www.example.com"); // 替换为初始URL
            }
            catch (Exception ex)
            {
                MessageBox.Show($"WebView2 初始化失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private async void btnPost_Click(object sender, EventArgs e)
        {
            try
            {
                // 方法一:使用 NavigateWithWebResourceRequest 执行POST请求
                await ExecutePostWithNavigateWithWebResourceRequest();

                // 方法二:通过JavaScript执行POST请求
                // await ExecutePostWithJavaScript();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"执行POST请求失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        // 方法一:使用 NavigateWithWebResourceRequest 执行POST请求
        private async Task ExecutePostWithNavigateWithWebResourceRequest()
        {
            // 确保WebView2已初始化
            if (webView21.CoreWebView2 == null)
            {
                MessageBox.Show("WebView2尚未初始化。请稍候再试。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // 构建POST数据(示例为JSON格式)
            var postData = new
            {
                name = "张三",
                age = 30
            };
            string json = JsonSerializer.Serialize(postData);
            byte[] dataBytes = Encoding.UTF8.GetBytes(json);
            var stream = new MemoryStream(dataBytes);

            // 创建请求
            var request = webView21.CoreWebView2.Environment.CreateWebResourceRequest(
                "https://www.example.com/api", // 替换为目标URL
                "POST",
                stream,
                "Content-Type: application/json");

            // 订阅 NavigationCompleted 事件(可选)
            webView21.CoreWebView2.NavigationCompleted += CoreWebView2_NavigationCompleted;

            // 执行POST请求
            webView21.CoreWebView2.NavigateWithWebResourceRequest(request);
        }

        // 方法二:通过JavaScript执行POST请求
        private async Task ExecutePostWithJavaScript()
        {
            // 确保WebView2已初始化
            if (webView21.CoreWebView2 == null)
            {
                MessageBox.Show("WebView2尚未初始化。请稍候再试。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // 订阅 WebMessageReceived 事件
            webView21.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;

            // 构建POST数据(示例为JSON格式)
            var postData = new
            {
                name = "张三",
                age = 30
            };
            string json = JsonSerializer.Serialize(postData);

            // 构建JavaScript代码,使用Fetch API发送POST请求
            string script = $@"
                fetch('https://www.example.com/api', {{
                    method: 'POST',
                    headers: {{
                        'Content-Type': 'application/json'
                    }},
                    body: '{json}'
                }})
                .then(response => response.json())
                .then(data => {{
                    window.chrome.webview.postMessage(JSON.stringify(data));
                }})
                .catch(error => {{
                    window.chrome.webview.postMessage(JSON.stringify({{ error: error.message }}));
                }});
            ";

            // 执行JavaScript代码
            await webView21.CoreWebView2.ExecuteScriptAsync(script);
        }

        private void CoreWebView2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
        {
            if (e.IsSuccess)
            {
                MessageBox.Show("POST请求执行完成,导航成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);

                // 可选:获取响应内容
                // 需要使用拦截器或其他方法获取响应内容
            }
            else
            {
                MessageBox.Show($"导航失败,错误代码: {e.WebErrorStatus}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
        {
            try
            {
                string message = e.TryGetWebMessageAsString();
                var response = JsonSerializer.Deserialize<Dictionary<string, object>>(message);

                if (response.ContainsKey("error"))
                {
                    MessageBox.Show($"POST请求错误: {response["error"]}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    // 处理成功响应
                    string jsonResponse = JsonSerializer.Serialize(response, new JsonSerializerOptions { WriteIndented = true });
                    textBoxHtml.Text = jsonResponse;
                    MessageBox.Show("成功获取POST响应!", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"处理响应失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

设计器文件(Form1.Designer.cs)

namespace WebView2PostExample
{
    partial class Form1
    {
        private Microsoft.Web.WebView2.WinForms.WebView2 webView21;
        private System.Windows.Forms.Button btnPost;
        private System.Windows.Forms.TextBox textBoxHtml;

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
            this.btnPost = new System.Windows.Forms.Button();
            this.textBoxHtml = new System.Windows.Forms.TextBox();
            ((System.ComponentModel.ISupportInitialize)(this.webView21)).BeginInit();
            this.SuspendLayout();
            // 
            // webView21
            // 
            this.webView21.CreationProperties = null;
            this.webView21.DefaultBackgroundColor = System.Drawing.Color.White;
            this.webView21.Location = new System.Drawing.Point(12, 12);
            this.webView21.Name = "webView21";
            this.webView21.Size = new System.Drawing.Size(776, 300);
            this.webView21.TabIndex = 0;
            this.webView21.ZoomFactor = 1D;
            // 
            // btnPost
            // 
            this.btnPost.Location = new System.Drawing.Point(12, 318);
            this.btnPost.Name = "btnPost";
            this.btnPost.Size = new System.Drawing.Size(100, 30);
            this.btnPost.TabIndex = 1;
            this.btnPost.Text = "执行POST";
            this.btnPost.UseVisualStyleBackColor = true;
            this.btnPost.Click += new System.EventHandler(this.btnPost_Click);
            // 
            // textBoxHtml
            // 
            this.textBoxHtml.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
                                                                            | System.Windows.Forms.AnchorStyles.Left) 
                                                                            | System.Windows.Forms.AnchorStyles.Right)));
            this.textBoxHtml.Location = new System.Drawing.Point(12, 354);
            this.textBoxHtml.Multiline = true;
            this.textBoxHtml.Name = "textBoxHtml";
            this.textBoxHtml.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.textBoxHtml.Size = new System.Drawing.Size(776, 84);
            this.textBoxHtml.TabIndex = 2;
            // 
            // Form1
            // 
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.textBoxHtml);
            this.Controls.Add(this.btnPost);
            this.Controls.Add(this.webView21);
            this.Name = "Form1";
            this.Text = "WebView2 执行POST请求示例";
            ((System.ComponentModel.ISupportInitialize)(this.webView21)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();
        }
    }
}

运行应用程序

  1. 按 F5 运行应用程序。

  2. 观察结果

    • WebView2控件会导航到指定的初始URL(如 https://www.example.com)。

    • 点击 “执行POST” 按钮,将执行POST请求到指定的API端点(如 https://www.example.com/api)。

    • 根据方法的不同:

      • 方法一:导航到API端点,处理导航完成事件。

      • 方法二:通过JavaScript执行POST请求,并在响应后将数据传回WinForms应用程序,显示在文本框中。


5. 注意事项

1. 跨域请求(CORS)

  • 问题:如果POST请求的目标URL与当前加载的页面不同域,可能会遇到CORS(跨域资源共享)限制,导致请求失败。

  • 解决方法

    • 确保目标服务器已正确设置CORS头,允许来自应用程序的请求。

    • 如果控制目标服务器,可以在服务器端添加必要的CORS配置。

    • 使用同域策略,或通过代理服务器中转请求。

2. 响应内容处理

  • 方法一NavigateWithWebResourceRequest 方法不直接提供响应内容。如果需要获取响应内容,需要使用WebView2的拦截器(如AddWebResourceRequestedFilterWebResourceRequested事件)来捕获响应。

  • 方法二:通过JavaScript执行POST请求,可以更方便地获取响应内容,并通过postMessage将其传回WinForms应用程序。

3. 安全性

  • 信任来源:确保仅向受信任的API端点发送POST请求,避免潜在的安全风险。

  • 数据验证:在应用程序中验证和处理从网页或API接收的数据,防止潜在的注入攻击。

4. 错误处理

  • 捕获异常:在执行POST请求和处理响应时,确保捕获并处理可能出现的异常,提升应用程序的稳定性。

  • 反馈用户:在发生错误时,向用户提供明确的错误信息和可能的解决方案。

5. 性能优化

  • 避免频繁请求:合理安排POST请求的频率,避免过于频繁的请求导致性能下降或被目标服务器限制。

  • 资源管理:确保在不需要时释放WebView2控件的资源,避免内存泄漏。


6. 常见问题及解决方法

问题1:使用 NavigateWithWebResourceRequest 方法后,无法获取POST响应内容

原因

  • NavigateWithWebResourceRequest 方法用于导航,而非直接获取响应内容。要获取响应内容,需要使用WebView2的拦截器功能。

解决方法

  1. 使用WebResourceRequested事件拦截响应

    webView21.CoreWebView2.WebResourceRequested += CoreWebView2_WebResourceRequested;
    
  2. 实现事件处理程序以捕获响应内容

    private void CoreWebView2_WebResourceRequested(object sender, CoreWebView2WebResourceRequestedEventArgs e)
    {
        if (e.Request.Uri == "https://www.example.com/api" && e.Request.Method == "POST")
        {
            var response = e.Response;
            if (response != null)
            {
                using (var stream = response.Content)
                using (var reader = new StreamReader(stream))
                {
                    string responseBody = reader.ReadToEnd();
                    // 处理响应内容
                    MessageBox.Show($"响应内容: {responseBody}", "响应", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
        }
    }
    

    注意:读取响应内容需要处理流的异步读取和线程安全问题,建议使用异步方法。

问题2:通过JavaScript执行POST请求时,postMessage未接收响应

原因

  • JavaScript代码存在错误。

  • WebMessageReceived事件未正确订阅或处理。

  • CORS限制导致请求失败。

解决方法

  1. 检查JavaScript代码是否正确

    • 使用浏览器的开发者工具(F12)查看控制台是否有错误。

  2. 确认WebMessageReceived事件已正确订阅

    webView21.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;
    
  3. 处理CORS问题

    • 确保目标服务器允许来自应用程序的跨域请求。

    • 检查网络响应,确认请求是否成功。

问题3:JSON反序列化失败或返回的HTML包含转义字符

原因

  • 返回的JSON格式不正确。

  • 未正确解析JSON字符串。

解决方法

  • 使用正确的JSON解析方法,例如:

    string htmlContent = JsonSerializer.Deserialize<string>(result);
    
  • 确保JavaScript返回的字符串已正确序列化:

    window.chrome.webview.postMessage(JSON.stringify(data));
    

问题4:执行POST请求后页面导航失败

原因

  • URL格式不正确。

  • 网络连接问题。

  • 目标服务器不可达或有故障。

解决方法

  • 检查目标URL是否正确,确保以 http://https:// 开头。

  • 检查网络连接,确保可以访问目标服务器。

  • 尝试在普通浏览器中访问目标URL,确认服务器是否正常。


7. 参考资料


8. 总结

在WinForms应用程序中使用WebView2以POST方式发送JSON数据,可以通过多种方法实现,包括使用NavigateWithWebResourceRequest方法和通过JavaScript执行POST请求。根据具体需求和场景,选择合适的方法来实现数据提交和响应处理。

关键要点

  1. 集成WebView2控件:确保WebView2控件已正确添加到项目中,并已初始化。

  2. 选择POST方法

    • 方法一:使用NavigateWithWebResourceRequest构建和执行POST请求。

    • 方法二:通过JavaScript在网页上下文中执行POST请求,并通过postMessage与应用程序通信。

  3. 处理响应:根据选择的方法,使用适当的事件和方法来获取和处理POST请求的响应内容。

  4. 错误处理与安全性:确保添加必要的错误处理机制,并遵循安全最佳实践,保护应用程序和用户数据。