Search code examples
c#.net-corekestrel

use Kestrel in .NET Core worker project


I created a new .NET Core worker project with the template provided by Visual Studio. I want to listen for incoming TCP messages and HTTP requests. I'm following David Fowler's "Multi-protocol Server with ASP.NET Core and Kestrel" repository on how to setup Kestrel.

AFAIK all I have to do is to install the Microsoft.AspNetCore.Hosting package to get access to the UseKestrel method.

In the Program.cs file I'm currently doing this

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });
}

Unfortunately I can't append UseKestrel to the ConfigureServices method. I think this is because I'm working with the IHostBuilder interface instead of the IWebHostBuilder interface.

This project should not be a Web API project, it should remain as a Worker project.

Any ideas how to configure Kestrel for this?


I tried to change the code to the code from the sample repository

using System.Net;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;

namespace Service
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureServices(services =>
                {
                    // ...
                })
                .UseKestrel(options =>
                {
                    // ...
                });
    }
}

When doing so it is still not able to resolve WebHost and comes up with these errors

  • There is no argument given that corresponds to the required formal parameter 'middleware' of 'ConnectionBuilderExtensions.Run(IConnectionBuilder, Func<ConnectionContext, Task>)'

  • The name 'WebHost' does not exist in the current context

I think this happens because the worker project does not use a Web SDK.


Solution

  • You enable the HTTP workload using IHostbuilder you need to add .ConfigureWebHostDefaults in your Host.CreateDefaultBuilder. Since Kestrel is web server you can only configure it from a webhost.

    In your program.cs file

    public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                       webBuilder.UseStartup<Startup>();
                        webBuilder.UseKestrel(options =>
                        {
                            // TCP 8007
                            options.ListenLocalhost(8007, builder =>
                            {
                                builder.UseConnectionHandler<MyEchoConnectionHandler>();
                            });
    
                            // HTTP 5000
                            options.ListenLocalhost(5000);
    
                            // HTTPS 5001
                            options.ListenLocalhost(5001, builder =>
                            {
                                builder.UseHttps();
                            });
                        });
                    });
    
    

    Or

    public static IHostBuilder CreateHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .UseKestrel(options =>
                {
                    // TCP 8007
                    options.ListenLocalhost(8007, builder =>
                    {
                        builder.UseConnectionHandler<MyEchoConnectionHandler>();
                    });
    
                    // HTTP 5000
                    options.ListenLocalhost(5000);
    
                    // HTTPS 5001
                    options.ListenLocalhost(5001, builder =>
                    {
                        builder.UseHttps();
                    });
                });
    

    Since you are enabling HTTP workloads using a web server then you project must be of type web. WebHost will be enabled only if the project is of type web. So you need to change your SDK to use web in your csproj file.

    <Project Sdk="Microsoft.NET.Sdk.Web">
    

    Reference: