user13755987
user13755987

Reputation:

Use Kestrel in a .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 set up Kestrel.

As far as I know, 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.

How can I 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:

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

Upvotes: 6

Views: 26528

Answers (2)

MtiHector
MtiHector

Reputation: 71

For .NET 5.0 as follows.

  1. Add a Framework reference to ASP.NET:

    <Project Sdk="Microsoft.NET.Sdk.Worker">
        <ItemGroup>
            <FrameworkReference Include="Microsoft.AspNetCore.App" />
        </ItemGroup>
    </Project>
    
  2. Add a web configuration to file program.cs:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false);
                config.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true);
    
                Configuration = config.Build();
             })
    
             // Worker
             .ConfigureServices((hostContext, services) =>
             {
                 services.AddHostedService<ServiceDemo>();
             })
    
             // Web site
             .ConfigureWebHostDefaults(webBuilder =>
             {
                 webBuilder.UseStartup<Startup>();
                 webBuilder.UseKestrel(options =>
                 {
                     // HTTP 5000
                     options.ListenLocalhost(58370);
    
                     // HTTPS 5001
                     options.ListenLocalhost(44360, builder =>
                     {
                         builder.UseHttps();
                     });
                 });
             });
    
  3. Configure class Startup

    public class Startup
    {
        public IConfiguration Configuration { get; }
    
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public void ConfigureServices(IServiceCollection services)
        {
        }
    
        public void Configure(IApplicationBuilder app)
        {
            var serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();
    
            app.UseStaticFiles();
            app.Run(async (context) =>
            {
                context.Response.ContentType = "text/html";
                await context.Response
                    .WriteAsync("<!DOCTYPE html><html lang=\"en\"><head>" +
                                "<title></title></head><body><p>Hosted by Kestrel</p>");
    
                if (serverAddressesFeature != null)
                {
                    await context.Response
                        .WriteAsync("<p>Listening on the following addresses: " +
                                    string.Join(", ", serverAddressesFeature.Addresses) +
                                    "</p>");
                }
    
                await context.Response.WriteAsync("<p>Request URL: " +
                                                  $"{context.Request.GetDisplayUrl()}<p>");
            });
        }
    }
    

Upvotes: 6

Purushothaman
Purushothaman

Reputation: 579

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:

Upvotes: 7

Related Questions