{"id":22725661,"url":"https://github.com/maremare/winformswithkestrel","last_synced_at":"2026-04-18T15:37:43.563Z","repository":{"id":220260904,"uuid":"751160188","full_name":"MareMare/WinFormsWithKestrel","owner":"MareMare","description":"🧪📝Self-hosting WebAPI with WinForms (with DI)","archived":false,"fork":false,"pushed_at":"2024-02-01T03:32:05.000Z","size":10,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-23T12:34:05.096Z","etag":null,"topics":["csharp","dotnet","example","kestrel","net8","self-hosted","winforms"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MareMare.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2024-02-01T03:32:00.000Z","updated_at":"2024-02-01T06:53:37.000Z","dependencies_parsed_at":"2024-02-01T05:38:43.657Z","dependency_job_id":"a13a93a2-51b6-4e5d-b0c0-147358c13497","html_url":"https://github.com/MareMare/WinFormsWithKestrel","commit_stats":null,"previous_names":["maremare/winformswithkestrel"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MareMare/WinFormsWithKestrel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MareMare%2FWinFormsWithKestrel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MareMare%2FWinFormsWithKestrel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MareMare%2FWinFormsWithKestrel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MareMare%2FWinFormsWithKestrel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MareMare","download_url":"https://codeload.github.com/MareMare/WinFormsWithKestrel/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MareMare%2FWinFormsWithKestrel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31974946,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dotnet","example","kestrel","net8","self-hosted","winforms"],"created_at":"2024-12-10T16:13:30.789Z","updated_at":"2026-04-18T15:37:38.552Z","avatar_url":"https://github.com/MareMare.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hosting WebAPI in WinForms (with DI) \n\nDI を利用した `WinForms` アプリに、あとから `Kestrel` サーバを自己ホストし `Web API` を公開する方法をメモ\n\n## やってみた\n\n### NuGet パッケージ参照\n\n```xml\n\u003cProject Sdk=\"Microsoft.NET.Sdk\"\u003e\n\n  \u003cPropertyGroup\u003e\n    \u003cOutputType\u003eWinExe\u003c/OutputType\u003e\n    \u003cTargetFramework\u003enet8.0-windows\u003c/TargetFramework\u003e\n    \u003cNullable\u003eenable\u003c/Nullable\u003e\n    \u003cUseWindowsForms\u003etrue\u003c/UseWindowsForms\u003e\n    \u003cImplicitUsings\u003eenable\u003c/ImplicitUsings\u003e\n  \u003c/PropertyGroup\u003e\n\n  \u003cItemGroup\u003e\n    \u003cNone Remove=\"appsettings.Development.json\" /\u003e\n    \u003cNone Remove=\"appsettings.json\" /\u003e\n  \u003c/ItemGroup\u003e\n\n  \u003cItemGroup\u003e\n    \u003cContent Include=\"appsettings.Development.json\"\u003e\n      \u003cCopyToOutputDirectory\u003ePreserveNewest\u003c/CopyToOutputDirectory\u003e\n      \u003cExcludeFromSingleFile\u003etrue\u003c/ExcludeFromSingleFile\u003e\n      \u003cCopyToPublishDirectory\u003ePreserveNewest\u003c/CopyToPublishDirectory\u003e\n    \u003c/Content\u003e\n    \u003cContent Include=\"appsettings.json\"\u003e\n      \u003cCopyToOutputDirectory\u003ePreserveNewest\u003c/CopyToOutputDirectory\u003e\n      \u003cExcludeFromSingleFile\u003etrue\u003c/ExcludeFromSingleFile\u003e\n      \u003cCopyToPublishDirectory\u003ePreserveNewest\u003c/CopyToPublishDirectory\u003e\n    \u003c/Content\u003e\n  \u003c/ItemGroup\u003e\n\n  \u003cItemGroup\u003e\n    \u003cPackageReference Include=\"Microsoft.Extensions.Configuration.Json\" Version=\"8.0.0\" /\u003e\n    \u003cPackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"8.0.0\" /\u003e\n    \u003cPackageReference Include=\"Microsoft.Extensions.Hosting\" Version=\"8.0.0\" /\u003e\n    \u003cPackageReference Include=\"NLog\" Version=\"5.2.8\" /\u003e\n    \u003cPackageReference Include=\"NLog.Extensions.Logging\" Version=\"5.3.8\" /\u003e\n  \u003c/ItemGroup\u003e\n\n  \u003c!-- 👇 これ！ --\u003e\n  \u003cItemGroup\u003e\n    \u003cPackageReference Include=\"Microsoft.AspNetCore.OpenApi\" Version=\"8.0.1\" /\u003e\n    \u003cPackageReference Include=\"Swashbuckle.AspNetCore\" Version=\"6.4.0\" /\u003e\n  \u003c/ItemGroup\u003e\n\n\u003c/Project\u003e\n```\n\n### Kestrel ポート番号の設定 (`launchSettings.json`)\n\n```json\n{\n  \"profiles\": {\n    \"WinForms\": {\n      \"commandName\": \"Project\",\n      \"remoteDebugEnabled\": false,\n      \"applicationUrl\": \"http://localhost:5000\"\n    }\n  }\n}\n```\n\n### Kestrel ポート番号の設定 (`appsettings.json`)\n\n```json\n{\n  \"Kestrel\": {\n    \"Endpoints\": {\n      \"Http\": {\n        \"Url\": \"http://localhost:7000\"\n      }\n    }\n  },\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\"\n}\n```\n\n### Program.cs のみで実装する場合\n\n\u003cdetails\u003e\u003csummary\u003eProgram.cs：\u003c/summary\u003e\n\n```cs\n// Program.cs\nusing System.Reflection;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace WinForms;\n\nstatic class Program\n{\n    /// \u003csummary\u003e\n    ///  The main entry point for the application.\n    /// \u003c/summary\u003e\n    [STAThread]\n    static void Main(string[] args)\n    {\n        // To customize application configuration such as set high DPI settings or default font,\n        // see https://aka.ms/applicationconfiguration.\n        ApplicationConfiguration.Initialize();\n\n        using var host = Program.CreateHostBuilder(args)\n            .UseWebApi() // 👈 これ！\n            .Build();\n        using var serviceScope = host.Services.CreateScope();\n        var services = serviceScope.ServiceProvider;\n\n        // Run Self-Hosted Web API.\n        host.RunAsync();\n\n        var mainForm = services.GetRequiredService\u003cForm1\u003e();\n        Application.Run(mainForm);\n        if (!mainForm.IsDisposed)\n        {\n            mainForm.Dispose();\n        }\n    }\n\n    private static IHostBuilder CreateHostBuilder(string[] args) =\u003e\n        Host.CreateDefaultBuilder(args)\n            .ConfigureServices((_, services) =\u003e\n                // TODO: add services.\n                services\n                    .AddTransient\u003cForm1\u003e());\n\n    private static IHostBuilder UseWebApi(this IHostBuilder builder)\n    {\n        builder.ConfigureWebHostDefaults(\n            webBuilder =\u003e\n            {\n                webBuilder\n                    .UseKestrel()\n                    .ConfigureServices(\n                        services =\u003e\n                        {\n                            // Add services to the container.\n                            services.AddControllers();\n                            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle\n                            services.AddEndpointsApiExplorer();\n                            //services.AddSwaggerGen();\n                            services.AddSwaggerGen(\n                                options =\u003e\n                                {\n                                    var assembly = Assembly.GetExecutingAssembly();\n                                    var assemblyName = assembly.GetName();\n                                    options.SwaggerDoc(\n                                        \"v1\",\n                                        new()\n                                        {\n                                            Version = $\"v{assemblyName.Version}\",\n                                            Title = $\"{assemblyName.Name}\",\n                                        });\n                                    var xmlDocumentFilePath = Path.Combine(\n                                        new Uri(Path.GetDirectoryName(assembly.Location) ?? string.Empty).AbsolutePath,\n                                        $\"{assemblyName.Name}.xml\");\n                                    if (File.Exists(xmlDocumentFilePath))\n                                    {\n                                        options.IncludeXmlComments(xmlDocumentFilePath);\n                                    }\n                                });\n                        })\n                    .Configure(\n                        (hostContext, app) =\u003e\n                        {\n                            if (hostContext.HostingEnvironment.IsDevelopment())\n                            {\n                                app.UseDeveloperExceptionPage();\n                            }\n                            \n                            // Configure the HTTP request pipeline.\n                            app.UseRouting();\n                            app.UseAuthorization();\n                            app.UseEndpoints(endpoints =\u003e { endpoints.MapControllers(); });\n\n                            app.UseSwagger();\n                            app.UseSwaggerUI();\n                        })\n                    .ConfigureServices((hostContext, services) =\u003e\n                    {\n                        // TODO: add services if necessary.\n                    });\n            });\n        return builder;\n    }\n}\n```\n\n\u003c/details\u003e\n\n### `UseStartup\u003cUseStartup\u003e` を使用する場合\n\n\u003cdetails\u003e\u003csummary\u003eWebApiStartup.cs：\u003c/summary\u003e\n\n```cs\n// WebApiStartup.cs\nusing System.Reflection;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace WinForms;\n\npublic class WebApiStartup\n{\n    public void ConfigureServices(IServiceCollection services)\n    {\n        // Add services to the container.\n        services.AddControllers();\n        // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle\n        services.AddEndpointsApiExplorer();\n        services.AddSwaggerGen(\n            options =\u003e\n            {\n                var assembly = Assembly.GetExecutingAssembly();\n                var assemblyName = assembly.GetName();\n                options.SwaggerDoc(\n                    \"v1\",\n                    new()\n                    {\n                        Version = $\"v{assemblyName.Version}\",\n                        Title = $\"{assemblyName.Name}\",\n                    });\n                var xmlDocumentFilePath = Path.Combine(\n                    new Uri(Path.GetDirectoryName(assembly.Location) ?? string.Empty).AbsolutePath,\n                    $\"{assemblyName.Name}.xml\");\n                if (File.Exists(xmlDocumentFilePath))\n                {\n                    options.IncludeXmlComments(xmlDocumentFilePath);\n                }\n            });\n    }\n\n    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n    {\n        if (env.IsDevelopment())\n        {\n            app.UseDeveloperExceptionPage();\n        }\n\n        // Configure the HTTP request pipeline.\n        app.UseRouting();\n        app.UseAuthorization();\n        app.UseEndpoints(endpoints =\u003e { endpoints.MapControllers(); });\n\n        app.UseSwagger();\n        app.UseSwaggerUI();\n    }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\u003csummary\u003eProgram.cs：\u003c/summary\u003e\n\n```cs\n// Program.cs\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Hosting;\n\nnamespace WinForms;\n\nstatic class Program\n{\n    /// \u003csummary\u003e\n    ///  The main entry point for the application.\n    /// \u003c/summary\u003e\n    [STAThread]\n    static void Main(string[] args)\n    {\n        // To customize application configuration such as set high DPI settings or default font,\n        // see https://aka.ms/applicationconfiguration.\n        ApplicationConfiguration.Initialize();\n\n        using var host = Program.CreateHostBuilder(args)\n            .ConfigureWebHostDefaults(webBuilder =\u003e webBuilder.UseStartup\u003cWebApiStartup\u003e()) // 👈 これ！\n            .Build();\n        using var serviceScope = host.Services.CreateScope();\n        var services = serviceScope.ServiceProvider;\n\n        // Run Self-Hosted Web API.\n        host.RunAsync();\n\n        var mainForm = services.GetRequiredService\u003cForm1\u003e();\n        Application.Run(mainForm);\n        if (!mainForm.IsDisposed)\n        {\n            mainForm.Dispose();\n        }\n    }\n\n    private static IHostBuilder CreateHostBuilder(string[] args) =\u003e\n        Host.CreateDefaultBuilder(args)\n            .ConfigureServices((_, services) =\u003e\n                // TODO: add services.\n                services\n                    .AddTransient\u003cForm1\u003e());\n}\n```\n\n\u003c/details\u003e\n\n## 参考\n* [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)\n* [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)\n* [ASP\\.NET Core を使用した gRPC サービス \\| Microsoft Learn](https://learn.microsoft.com/ja-jp/aspnet/core/grpc/aspnetcore?view=aspnetcore-8.0\u0026tabs=visual-studio#host-grpc-in-non-aspnet-core-projects)\n* [tonysneed/Demo\\.DotNetSelfHost: Sample Windows Forms application hosting an ASP\\.NET Core service](https://github.com/tonysneed/Demo.DotNetSelfHost)\n* [ASP\\.NET Kestrel Web サーバーで外部からの接続を許可する \\| iPentec](https://www.ipentec.com/document/csharp-asp-net-core-allow-external-connections-in-kestrel-web-server)\n* [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)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaremare%2Fwinformswithkestrel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaremare%2Fwinformswithkestrel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaremare%2Fwinformswithkestrel/lists"}