在 Windows 窗体应用程序中托管 ASP.NET Core API

Posted

技术标签:

【中文标题】在 Windows 窗体应用程序中托管 ASP.NET Core API【英文标题】:Hosting ASP.NET Core API in a Windows Forms Application 【发布时间】:2020-05-18 21:16:34 【问题描述】:

背景:我正在处理一个涉及 WinForms 应用程序的项目。客户端希望公开一个仅限本地的 HTTP 服务器,以允许其他应用程序通过 REST API(或类似方法)在 WinForms 应用程序的运行实例上触发功能。首选是使用 ASP.NET Core 实现上述 API。

因此,我的问题是:如何构建一个项目以在同一进程中同时拥有 ASP.NET Core API 和 WinForms GUI?有什么我需要提防的陷阱吗?

【问题讨论】:

为什么要在同一个进程中运行这两个程序? @citronas 允许其他应用程序通过 REST API 在 WinForms 应用程序的运行实例上触发功能,基本上是进程间通信。 @Matthew 以“最好的方法是什么...”开头的问题通常是题外话,因为它们是基于意见的。您对特定问题有任何具体问题吗? @RezaAghaei 抱歉,用“我该怎么做”替换“什么是最好的方法”......虽然,鉴于绝大多数编程问题都有不止一个解决方案,我认为几乎每个问题都有一个隐含的“什么是最好的方法”组件:-) @citronas 就像 Reza Aghaei 回答的那样 - IPC。与其说是“两个程序”,不如说是同一个程序的两个不同接口。 【参考方案1】:

在 Windows 窗体应用程序中托管 ASP.NET CORE API 并与窗体交互

这是一个关于如何创建项目以在 Windows 窗体应用程序中托管 ASP.NET CORE API 并与窗体执行一些交互的基本分步示例。

为此,请按以下步骤操作:

    创建一个 Windows 窗体应用程序,将其命名为 MyWinFormsApp

    在设计模式下打开Form1,然后在上面放一个TextBox

    将设计器中textBox1Modifiers属性更改为Public并保存。

    安装Microsoft.AspNetCore.Mvc

    安装Microsoft.AspNetCore

    在项目根目录下创建Startup.cs文件,复制如下代码:

     using Microsoft.AspNetCore.Builder;
     using Microsoft.AspNetCore.Hosting;
     using Microsoft.AspNetCore.Mvc;
     using Microsoft.Extensions.Configuration;
     using Microsoft.Extensions.DependencyInjection;
     namespace MyWinFormsApp
     
         public class Startup
         
             public Startup(IConfiguration configuration)
             
                 Configuration = configuration;
             
             public IConfiguration Configuration  get; 
             public void ConfigureServices(IServiceCollection services)
             
                 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
             
             public void Configure(IApplicationBuilder app, IHostingEnvironment env)
             
                 if (env.IsDevelopment())
                 
                     app.UseDeveloperExceptionPage();
                 
                 app.UseMvc();
             
         
     
    

    将以下代码复制到Program.cs

     using System;
     using System.Threading;
     using System.Windows.Forms;
     using Microsoft.AspNetCore;
     using Microsoft.AspNetCore.Hosting;
    
     namespace MyWinFormsApp
     
         public class Program
         
             public static Form1 MainForm  get; private set; 
    
             [STAThread]
             public static void Main(string[] args)
             
                 CreateWebHostBuilder(args).Build().RunAsync();
    
                 Application.EnableVisualStyles();
                 Application.SetCompatibleTextRenderingDefault(false);
                 MainForm = new Form1();
                 Application.Run(MainForm);
             
    
             public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                 WebHost.CreateDefaultBuilder(args)
                     .UseStartup<Startup>();
         
     
    

    在项目的根目录中创建一个名为Controllers 的文件夹。

    Controllers文件夹中创建ValuesController.cs,并将以下代码复制到文件中:

     using System;
     using Microsoft.AspNetCore.Mvc;
    
     namespace MyWinFormsApp.Controllers
     
         [Route("api/[controller]")]
         [ApiController]
         public class ValuesController : ControllerBase
         
             [HttpGet]
             public ActionResult<string> Get()
             
                 string text = "";
                 Program.MainForm.Invoke(new Action(() =>
                 
                     text = Program.MainForm.textBox1.Text;
                 ));
                 return text;
             
    
             [HttpGet("id")]
             public ActionResult Get(string id)
             
                 Program.MainForm.Invoke(new Action(() =>
                 
                     Program.MainForm.textBox1.Text = id;
                 ));
                 return Ok();
             
         
     
    

    运行应用程序。

    textBox1中输入“hi”

    打开浏览器并浏览 http://localhost:5000/api/values → 您将看到 hi 作为响应。

    http://localhost:5000/api/values/bye → 你会在textBox1看到bye

进一步阅读

您可能也对How to use Dependency Injection (DI) in Windows Forms (WinForms)感兴趣

【讨论】:

该示例使用 GET 方法只是为了简化浏览器中的测试。您可能希望根据自己的要求使用不同的动词。 这不是关于最佳实践,而是关于快速入门和一个简单的 PoC 展示您可以做什么。 谢谢礼萨。您知道这种方法是否会导致线程模型出现任何问题吗? 正如我在 cmets 中提到的,答案不是关于最佳实践,它更像是一个 PoC,但是关于这个解决方案有一些要点:(1)总的来说,这个想法是可以的,它是跨-进程通信。 (2)我在生产环境中的WinForms应用程序之间使用了类似的方法使用WCF进行IPC,没有任何问题。 (3) 我在测试环境中为此目的使用了 ASP.NET WEB API,但我还没有为此目的使用 ASP.NET CORE。 (4)只要使用Invoke访问UI线程,尝试访问UI线程是没有问题的。 另一个要考虑的选项,您可以考虑使用 MSMQ 或任何其他消息总线在基于事件/消息的解决方案中的应用程序之间进行通信。 (这超出了本文的范围)

以上是关于在 Windows 窗体应用程序中托管 ASP.NET Core API的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows 窗体应用程序中托管 ASP.NET Core API

非托管代码中的 Windows 窗体?

C# Windows 窗体无法在 Windows10 上加载非托管 C++ DLL

Windows 窗体中的 WCF 数据服务托管

在退出之前跟踪 - 并正确结束 - C# - C++/CLI - C++ Windows 窗体应用程序中的本机和托管线程

捕获托管在 mfc 对话框上的 windows 窗体事件(c#)