C# 在Windows窗体应用程序中托管ASP.NET核心API
背景:我正在从事一个涉及WinForms应用程序的项目。客户端希望公开仅本地HTTP服务器,以允许其他应用程序通过REST API(或类似应用程序)在WinForms应用程序的运行实例上触发功能。首选使用ASP.NET核心实现上述APIC# 在Windows窗体应用程序中托管ASP.NET核心API,c#,.net,winforms,asp.net-core,asp.net-core-webapi,C#,.net,Winforms,Asp.net Core,Asp.net Core Webapi,背景:我正在从事一个涉及WinForms应用程序的项目。客户端希望公开仅本地HTTP服务器,以允许其他应用程序通过REST API(或类似应用程序)在WinForms应用程序的运行实例上触发功能。首选使用ASP.NET核心实现上述API 因此,我的问题是:如何构造一个项目,使ASP.NET核心API和WinForms GUI都在同一个过程中?是否有任何我必须警惕的陷阱?在Windows窗体应用程序中托管ASP.NET核心API并与窗体交互 下面是一个基本的分步示例,介绍如何创建一个项目,在Win
因此,我的问题是:如何构造一个项目,使ASP.NET核心API和WinForms GUI都在同一个过程中?是否有任何我必须警惕的陷阱?在Windows窗体应用程序中托管ASP.NET核心API并与窗体交互 下面是一个基本的分步示例,介绍如何创建一个项目,在Windows窗体应用程序中托管ASP.NET核心API,并与窗体执行一些交互 为此,请执行以下步骤:
MyWinFormsApp
Form1
,并在其上放置一个TextBox
textBox1
的Modifiers
属性更改为Public
,然后保存它Microsoft.AspNetCore.Mvc
packageStartup.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>();
}
}
文本框1中键入“hi”
hi
作为响应textBox1
为什么要在同一进程中运行这两个程序?@citronas允许其他应用程序通过REST API(基本上是进程间通信)在WinForms应用程序的运行实例上触发功能。@Matthew以“最佳方式是什么…”开头的问题通常是离题的,因为它们是基于意见的。你对某个问题有什么具体的问题吗?@RezaAghaei抱歉,用“我该怎么做”替换“什么是最好的方法”。。。尽管如此,考虑到绝大多数编程问题都有不止一个解决方案,我认为几乎每个问题都有一个隐含的“最好的方法是什么”组件:-)citronas,这与Reza Aghaei回答的完全一样-IPC。与其说它是“两个程序”,不如说它是同一个程序的两个不同接口。该示例使用GET方法只是为了让在浏览器中测试时保持简单。您可能需要根据自己的需求使用不同的动词。这不是关于最佳实践,而是关于快速入门和一个简单的PoC,展示您可以做什么。谢谢Reza。您知道这种方法是否会导致线程模型出现任何问题吗?正如我在评论中提到的,答案不是关于最佳实践,而是PoC,但是这种解决方案有一些要点:(1)一般来说,这个想法是好的,它是进程间通信。(2) 我在生产环境中的WinForms应用程序之间使用WCF for IPC使用了类似的方法,没有任何问题。(3) 为此,我在测试环境中使用了ASP.NETWebAPI,但还没有使用ASP.NETCore。(4)只要使用调用来访问UI线程,就可以尝试访问UI线程。另一个要考虑的选项,您可以考虑使用MSMQ或任何其他消息总线在基于事件/消息的解决方案之间进行应用程序之间的通信。(不在本岗位范围内)
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();
}
}
}