与传统的ASP.NET框架不同,ASP.NET Core彻底打破了对IIS的强绑定依赖,为开发者提供了灵活多样的运行模式选择。
不同的运行模式在资源占用、部署成本、运维复杂度、适用场景上存在显著差异,开发者需要根据项目的业务属性、部署环境、SLA要求等维度,选择最适配的运行方案。
本文将系统梳理ASP.NET Core的六大类主流运行模式,帮助开发者在不同业务场景下做出最优的技术选型。
一、自宿主
自宿主(Self-Hosting)是ASP.NET Core基础的运行模式,指应用程序完全独立运行,不依赖任何外部服务器软件,通过内置的Kestrel Web服务器直接监听端口、处理HTTP请求。这种模式将宿主环境与应用程序打包为统一的整体,开发者无需提前在服务器上安装IIS、Nginx等外部Web服务器,即可直接启动应用对外提供服务。
详细步骤:
1.环境校验
打开命令行执行 dotnet --version,确认已安装对应版本的.NET SDK,版本号需与项目目标框架匹配:
2.创建项目
执行命令 dotnet new webapi -n SelfHostDemo,自动生成基础ASP.NET Core WebAPI项目。
3.配置监听端口
打开项目根目录的 appsettings.json,添加Kestrel配置节点,指定监听所有网卡的5000端口:
"Kestrel": { "Endpoints": { "Http": { "Url": "http://0.0.0.0:5000" } } },4.验证代码逻辑
打开默认生成的 Program.cs,确认没有额外的IIS托管相关配置,保留基础的WebApplication构建逻辑即可。
5.还原依赖
在项目目录执行 dotnet restore,自动下载所有NuGet依赖包,确保无依赖缺失报错。
6.本地调试运行
执行 dotnet run,控制台输出“Now listening on:http://0.0.0.0:5000”即代表启动成功,浏览器访问 http://localhost:5000/weatherforecast 验证接口正常返回数据。
7.发布独立包
执行 dotnet publish -c Release -r win-x64 --self-contained true,生成完全独立的可执行文件,无需目标服务器安装.NET运行时即可运行。
8.目标服务器部署
将publish目录下所有文件拷贝到目标服务器,直接双击生成的 SelfHostDemo.exe 启动应用,或在命令行执行 ./SelfHostDemo 运行。
9.端口放行
在服务器防火墙中添加5000端口的入站规则,允许外部设备访问该端口,验证跨设备访问接口正常。
注意:自宿主模式下Kestrel的原生HTTP处理能力虽然优秀,但在生产环境直接对外暴露公网时,缺少反向代理提供的端口隔离、请求限流、静态文件缓存等能力,因此不建议直接将自宿主应用暴露在公网环境中。同时,默认的控制台窗口关闭后应用进程会直接退出,生产环境使用时需要结合进程守护工具保证应用的持续运行。
二、IIS服务承载
IIS(Internet Information Services)是Windows平台下经典的Web服务器,ASP.NET Core可以通过ASP.NET Core Module(ANCM)模块实现与IIS的集成,将应用托管在IIS进程中运行。
这种模式充分复用了IIS成熟的Web管理能力,为ASP.NET Core应用提供进程管理、反向代理、安全认证等一系列生产级特性。
传统Windows企业环境部署:大量已经深度使用IIS的传统企业IT环境,运维团队已经熟练掌握IIS的配置与运维方法,将ASP.NET Core应用托管在IIS中可以完全复用现有的运维体系,降低团队的学习成本。
1.服务器环境准备
在Windows服务器上安装IIS服务,确保Web服务器角色中勾选了“应用程序开发”下的“ASP.NET Core 3.0”组件。
如果服务器系统版本较低,需要手动下载安装ASP.NET Core Hosting Bundle,该组件会自动安装ANCM模块与对应的.NET运行时环境。
下载 .NET 9.0 (Linux、macOS 和 Windows) | .NET
2.配置应用池
在IIS管理器中新建独立的应用池,将“.NET CLR版本”设置为“无托管代码”,因为ASP.NET Core应用的运行时已经独立于IIS的托管环境,设置为无托管代码可以避免旧的.NET框架组件对应用运行产生干扰。
3.发布应用程序
在Visual Studio中右键点击项目选择“发布”。
发布模式选择“文件夹”。
部署模式推荐选择“独立部署”,目标运行时选择对应的Windows平台版本,将发布后的所有文件拷贝到服务器的指定目录中。
4.部署站点
在IIS管理器中新建网站,指定网站的物理路径为刚才拷贝的应用文件目录,设置网站绑定的端口与域名,选择之前创建好的独立应用池,完成站点创建。
访问:
5.验证运行状态
在IIS中点击站点对应的“浏览”按钮,访问配置的域名地址,确认应用可以正常响应请求。同时可以在IIS的“日志”目录中查看请求访问记录,确认所有请求都经过IIS的代理转发。
注意添加文件夹权限:
三、WebAPI 嵌入桌面应用程序中
WebAPI嵌入桌面应用程序是一种将ASP.NET Core Web服务与Windows Forms、WPF等桌面客户端深度集成的运行模式。
在同一个进程中同时运行桌面UI界面与内置的WebAPI服务,桌面应用可以直接通过本地HTTP调用WebAPI接口。
外部设备也可以通过局域网访问这个内置的Web服务,实现桌面端与Web端的能力打通。
创建解决方案
在Visual Studio中新建“Windows Forms App(.NET)”项目,命名为EmbedDesktopDemo,解决方案中再新增一个“ASP.NET Core Web API”类库项目,命名为InnerWebApi。
添加项目引用
在Windows Forms项目中右键“依赖项”,添加项目引用,选中InnerWebApi项目,实现桌面项目与WebAPI项目的关联。
安装核心依赖
在Windows Forms项目的NuGet包管理器中,搜索安装 Microsoft.AspNetCore.App 元包,自动引入ASP.NET Core运行所需的所有组件。
编写后台启动代码
打开主窗体的构造函数,添加后台线程启动Web宿主的逻辑,避免阻塞UI线程:
private IHost _webHost; public Form1() { InitializeComponent(); // 后台启动内置Web服务 Task.Run(async () => { _webHost = Host.CreateDefaultBuilder() .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<InnerWebApi.Startup>(); webBuilder.UseUrls("http://localhost:7200"); }) .Build(); await _webHost.RunAsync(); }); }实现本地调用逻辑
在窗体中添加一个按钮,点击事件中注入HttpClient,调用本地内置的WebAPI接口,将返回结果显示在文本框中。
处理窗口关闭事件
重写FormClosing事件,在窗体关闭时先停止Web宿主,避免进程残留:
private async void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (_webHost != null) await _webHost.StopAsync(); }配置局域网访问
如需允许同网络其他设备访问,将监听地址修改为http://0.0.0.0:7200,在Windows防火墙中添加7200端口的入站规则。
打包发布
将Windows Forms项目发布为独立可执行文件,双击运行后,既可以操作桌面界面,也可以通过浏览器访问内置的WebAPI接口。
四、服务承载
1.使用Worker Service 项目模版
服务承载是将ASP.NET Core应用作为系统后台服务运行的模式,应用会在系统开机时自动静默启动,无需用户登录系统即可在后台持续运行,这种模式是企业级后台服务最常用的部署方案,可以实现7×24小时不间断运行。
Worker Service是ASP.NET Core官方提供的专门用于开发长时间运行后台服务的项目模版,它为后台服务的开发提供了标准化的基础结构,大幅降低了长驻后台服务的开发门槛。
使用Worker Service项目模版
创建项目
在Visual Studio新建项目界面搜索“Worker Service”,选择对应.NET版本,命名为WorkerDemo,自动生成后台服务基础项目。
编写业务逻辑
打开默认的Worker.cs文件,修改ExecuteAsync方法,实现自定义定时任务逻辑:
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("当前时间:{0},执行定时数据同步", DateTime.Now); // 此处添加你的业务处理代码 await Task.Delay(60000, stoppingToken); // 间隔1分钟执行一次 } }注册服务
打开Program.cs,确认已通过services.AddHostedService<Worker>()将后台服务注册到依赖注入容器中。
本地调试
直接启动项目,控制台会持续输出日志,验证定时任务逻辑正常运行,按Ctrl+C触发优雅关闭,确认服务正常退出。
发布项目
执行dotnet publish -c Release,生成发布文件,后续可注册为系统服务。
2.Windows服务注册
安装依赖包
在Worker项目中NuGet安装Microsoft.Extensions.Hosting.WindowsServices包。
修改Program.cs
在主机构建链中添加UseWindowsService配置:
var host = Host.CreateDefaultBuilder(args) .UseWindowsService(options => { options.ServiceName = "MyWorkerService"; }) .ConfigureServices(s => s.AddHostedService<Worker>()) .Build(); host.Run();部署文件:将发布后的所有文件拷贝到服务器目录C:\Services\WorkerDemo。
注册服务:以管理员身份打开PowerShell,执行sc命令创建服务:
sc.exe create "MyWorkerService" binPath="C:\Services\WorkerDemo\WorkerDemo.exe" start=auto DisplayName="我的定时同步服务"
启动验证:执行sc start "MyWorkerService",打开Windows服务管理器,确认服务处于运行状态,重启服务器验证服务自动启动。
3.Linux服务注册
部署文件:将发布后的Linux-x64版本文件拷贝到Linux服务器的/var/www/worker-demo目录,执行chmod +x WorkerDemo.dll添加执行权限。
创建服务单元文件:执行vim /etc/systemd/system/my-worker.service,写入以下配置:
[Unit] Description=ASP.NET Core定时服务 After=network.target [Service] WorkingDirectory=/var/www/worker-demo ExecStart=/usr/bin/dotnet /var/www/worker-demo/WorkerDemo.dll Restart=always RestartSec=10 User=root Environment=ASPNETCORE_ENVIRONMENT=Production [Install] WantedBy=multi-user.target重载配置:执行`systemctl daemon-reload`,让Systemd识别新服务。
启动并设置自启
依次执行:
```bash systemctl start my-worker systemctl enable my-worker验证状态:执行systemctl status my-worker,确认服务处于active(running)状态,通过journalctl -u my-worker查看运行日志。
将WebApi托管为Windows服务
创建WebAPI项目:新建ASP.NET Core WebAPI项目,NuGet安装Microsoft.Extensions.Hosting.WindowsServices包。
修改Program.cs:添加Windows服务托管配置:
var builder = WebApplication.CreateBuilder(args); builder.Host.UseWindowsService(); builder.Services.AddControllers(); var app = builder.Build(); app.MapControllers(); app.Run("http://localhost:8888");发布项目:将项目发布为独立可执行文件,拷贝到服务器目录C:\Services\WebApiService。
注册服务:管理员PowerShell执行:
sc create "WebApiWinService" binPath="C:\Services\WebApiService\WebApiDemo.exe" start=auto
放行端口:在防火墙中添加8888端口入站规则,启动服务后访问接口地址验证正常响应。
4.将WebApi托管为Windows服务
除了纯后台Worker服务之外,ASP.NET Core WebAPI项目也可以直接托管为Windows服务,实现无需IIS依赖的Web服务后台运行,这种方案在很多对部署轻量化有要求的场景下被广泛使用。
WebAPI托管为Windows服务的本质是将WebAPI的宿主进程注册为Windows服务,通过UseWindowsService()`方法将宿主的生命周期与Windows服务控制管理器绑定,应用启动后内置的Kestrel服务器会在后台静默监听指定端口,处理外部的HTTP请求,整个过程无需IIS的参与。
引入Windows服务依赖包:在WebAPI项目中安装Microsoft.Extensions.Hosting.WindowsServices` NuGet包。
修改Program.cs代码:在Web应用的构建逻辑中添加UseWindowsService配置:
```csharp var builder = WebApplication.CreateBuilder(args); // 启用Windows服务托管模式 builder.Host.UseWindowsService(); builder.Services.AddControllers(); var app = builder.Build(); app.MapControllers(); app.Run();配置监听端口:在appsettings.json中配置Kestrel的监听地址,指定WebAPI的访问端口,避免端口冲突。
发布与注册服务:将项目发布为独立可执行文件,使用sc.exe命令将应用注册为Windows服务,设置服务开机自动启动。
开放防火墙端口:在Windows防火墙中添加对应端口的入站规则,允许其他设备通过局域网访问该WebAPI服务的接口地址。
五、WindowsFormsLifetime
WindowsFormsLifetime是ASP.NET Core提供的一种特殊宿主生命周期模式,专门用于将ASP.NET Core应用与Windows Forms桌面应用深度集成,让Web服务的生命周期完全由Windows Forms的消息循环控制,实现桌面窗口与Web服务的一体化运行。
配置项目属性:将项目的输出类型修改为Windows应用程序,添加对Windows Forms的框架引用,在项目文件中添加对应的配置节点。
安装必要NuGet包:安装Microsoft.AspNetCore.Server.Kestrel.Windows与Microsoft.Extensions.Hosting.WindowsFormsLifetime包,获取WindowsFormsLifetime的支持能力。
编写宿主构建代码:在Program.cs中配置使用WindowsFormsLifetime作为宿主的生命周期:
var builder = Host.CreateDefaultBuilder(args) .UseWindowsFormsLifetime(options => { // 指定主窗口的类型 options.MainFormType = typeof(MainForm); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); webBuilder.UseUrls("http://localhost:8080"); }); var host = builder.Build(); host.Run();开发主窗口界面:创建Windows Forms主窗口,在窗口中添加启动、停止Web服务、查看服务状态、打开浏览器访问Web页面等交互按钮,实现图形化的控制能力。
测试运行:启动应用后,Windows Forms主窗口会正常显示,同时内置的Web服务在后台自动启动,关闭主窗口时Web服务会自动优雅关闭,不会出现进程残留。
六、使用nginx部署
这种部署架构采用“Nginx反向代理+Kestrel内网服务”的两层架构,Nginx作为前置入口监听80/443公网端口,处理所有外部用户的HTTP/HTTPS请求,完成SSL证书解密、静态文件缓存、请求限流、负载均衡等操作后,将动态请求转发给后端运行在本地的ASP.NET Core Kestrel服务。
Kestrel仅监听127.0.0.1本地回环地址,不直接对外暴露,所有外部请求都经过Nginx的安全过滤,既充分利用了Nginx的高并发连接处理能力,又发挥了Kestrel在动态请求处理上的优势,整体架构的性能与安全性都远高于Kestrel直接对外提供服务的模式。
安装Nginx:在Ubuntu服务器上执行apt update && apt install nginx -y,安装完成后执行systemctl start nginx && systemctl enable nginx,启动并设置开机自启。
部署ASP.NET Core应用:将发布后的Linux版本WebAPI文件拷贝到/var/www/nginx-demo目录,注册为Systemd服务,设置Kestrel监听http://127.0.0.1:5000。
创建站点配置:执行vim /etc/nginx/sites-available/my-aspnet-site,写入反向代理配置:
server { listen 80; server_name yourdomain.com; location / { proxy_pass http://127.0.0.1:5000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off; proxy_max_temp_file_size 0; } }启用站点:执行ln -s /etc/nginx/sites-available/my-aspnet-site /etc/nginx/sites-enabled/,创建软链接启用站点。
验证配置:执行nginx -t,确认配置文件语法无报错,执行systemctl reload nginx重载配置。配置HTTPS:安装Certbot工具,执行certbot --nginx -d yourdomain.com,自动申请SSL证书并配置HTTPS规则。
最终验证:浏览器访问域名地址,确认ASP.NET Core应用正常响应,查看Nginx访问日志,确认所有请求都经过反向代理转发。