Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/maremare/winformswithkestrel
🧪📝Self-hosting WebAPI with WinForms (with DI)
https://github.com/maremare/winformswithkestrel
csharp dotnet example kestrel net8 self-hosted winforms
Last synced: about 5 hours ago
JSON representation
🧪📝Self-hosting WebAPI with WinForms (with DI)
- Host: GitHub
- URL: https://github.com/maremare/winformswithkestrel
- Owner: MareMare
- Created: 2024-02-01T03:32:00.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-02-01T03:32:05.000Z (about 1 year ago)
- Last Synced: 2024-12-10T16:13:25.842Z (about 2 months ago)
- Topics: csharp, dotnet, example, kestrel, net8, self-hosted, winforms
- Language: C#
- Homepage:
- Size: 9.77 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Hosting WebAPI in WinForms (with DI)
DI を利用した `WinForms` アプリに、あとから `Kestrel` サーバを自己ホストし `Web API` を公開する方法をメモ
## やってみた
### NuGet パッケージ参照
```xml
WinExe
net8.0-windows
enable
true
enable
PreserveNewest
true
PreserveNewest
PreserveNewest
true
PreserveNewest
```
### Kestrel ポート番号の設定 (`launchSettings.json`)
```json
{
"profiles": {
"WinForms": {
"commandName": "Project",
"remoteDebugEnabled": false,
"applicationUrl": "http://localhost:5000"
}
}
}
```### Kestrel ポート番号の設定 (`appsettings.json`)
```json
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://localhost:7000"
}
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
```### Program.cs のみで実装する場合
Program.cs:
```cs
// Program.cs
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;namespace WinForms;
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();using var host = Program.CreateHostBuilder(args)
.UseWebApi() // 👈 これ!
.Build();
using var serviceScope = host.Services.CreateScope();
var services = serviceScope.ServiceProvider;// Run Self-Hosted Web API.
host.RunAsync();var mainForm = services.GetRequiredService();
Application.Run(mainForm);
if (!mainForm.IsDisposed)
{
mainForm.Dispose();
}
}private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
// TODO: add services.
services
.AddTransient());private static IHostBuilder UseWebApi(this IHostBuilder builder)
{
builder.ConfigureWebHostDefaults(
webBuilder =>
{
webBuilder
.UseKestrel()
.ConfigureServices(
services =>
{
// Add services to the container.
services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
//services.AddSwaggerGen();
services.AddSwaggerGen(
options =>
{
var assembly = Assembly.GetExecutingAssembly();
var assemblyName = assembly.GetName();
options.SwaggerDoc(
"v1",
new()
{
Version = $"v{assemblyName.Version}",
Title = $"{assemblyName.Name}",
});
var xmlDocumentFilePath = Path.Combine(
new Uri(Path.GetDirectoryName(assembly.Location) ?? string.Empty).AbsolutePath,
$"{assemblyName.Name}.xml");
if (File.Exists(xmlDocumentFilePath))
{
options.IncludeXmlComments(xmlDocumentFilePath);
}
});
})
.Configure(
(hostContext, app) =>
{
if (hostContext.HostingEnvironment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Configure the HTTP request pipeline.
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });app.UseSwagger();
app.UseSwaggerUI();
})
.ConfigureServices((hostContext, services) =>
{
// TODO: add services if necessary.
});
});
return builder;
}
}
```### `UseStartup` を使用する場合
WebApiStartup.cs:
```cs
// WebApiStartup.cs
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;namespace WinForms;
public class WebApiStartup
{
public void ConfigureServices(IServiceCollection services)
{
// Add services to the container.
services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
services.AddSwaggerGen(
options =>
{
var assembly = Assembly.GetExecutingAssembly();
var assemblyName = assembly.GetName();
options.SwaggerDoc(
"v1",
new()
{
Version = $"v{assemblyName.Version}",
Title = $"{assemblyName.Name}",
});
var xmlDocumentFilePath = Path.Combine(
new Uri(Path.GetDirectoryName(assembly.Location) ?? string.Empty).AbsolutePath,
$"{assemblyName.Name}.xml");
if (File.Exists(xmlDocumentFilePath))
{
options.IncludeXmlComments(xmlDocumentFilePath);
}
});
}public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}// Configure the HTTP request pipeline.
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });app.UseSwagger();
app.UseSwaggerUI();
}
}
```Program.cs:
```cs
// Program.cs
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;namespace WinForms;
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();using var host = Program.CreateHostBuilder(args)
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()) // 👈 これ!
.Build();
using var serviceScope = host.Services.CreateScope();
var services = serviceScope.ServiceProvider;// Run Self-Hosted Web API.
host.RunAsync();var mainForm = services.GetRequiredService();
Application.Run(mainForm);
if (!mainForm.IsDisposed)
{
mainForm.Dispose();
}
}private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
// TODO: add services.
services
.AddTransient());
}
```## 参考
* [Host Kestrel Web Server in \.NET 6 Windows Form Application \| by Jason Ge \| Medium](https://jason-ge.medium.com/host-kestrel-web-server-in-net-6-windows-form-application-8b0fd70b4288)
* [c\# \- Hosting ASP\.NET Core API in a Windows Forms Application \- Stack Overflow](https://stackoverflow.com/questions/60033762/hosting-asp-net-core-api-in-a-windows-forms-application/60046440#60046440)
* [ASP\.NET Core を使用した gRPC サービス \| Microsoft Learn](https://learn.microsoft.com/ja-jp/aspnet/core/grpc/aspnetcore?view=aspnetcore-8.0&tabs=visual-studio#host-grpc-in-non-aspnet-core-projects)
* [tonysneed/Demo\.DotNetSelfHost: Sample Windows Forms application hosting an ASP\.NET Core service](https://github.com/tonysneed/Demo.DotNetSelfHost)
* [ASP\.NET Kestrel Web サーバーで外部からの接続を許可する \| iPentec](https://www.ipentec.com/document/csharp-asp-net-core-allow-external-connections-in-kestrel-web-server)
* [ASP\.NET Core Kestrel Web サーバーのエンドポイントを構成する \| Microsoft Learn](https://learn.microsoft.com/ja-jp/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-8.0#configure-https-in-appsettingsjson)