aleksander_si
aleksander_si

Reputation: 1377

Mapping a specific controller to a specific Kestrel endpoint

Is it possible to map a specific controller to a specific Kestrel endpoint? Assuming the following endpoints:

  "Kestrel": {
    "EndpointDefaults": {
      "Protocols_comment": "Host does not support newer protocols",
      "Protocols": "Http1"
    },
    "Endpoints": {
    "localhostHttp": {
        "Url": "http://localhost:5180"
     },
    "localhostHttps": {
        "Url": "https://localhost:5181",
        "Certificate": {
          "Subject": "<certsubject string>",
          "Location": "LocalMachine",
          "AllowInvalid": "false"
        }
      }
    }
  }

And controller:

[Route("api/[controller]")]
    [ApiController]
    public class PushBackWsController : Controller
{
// ...
}

Is it possible to map the PushBackWsController controller to the localhostHttps endpoint relying only on configuration in appsettings.json or Startup.cs / Program.cs?

Upvotes: 0

Views: 820

Answers (2)

Shenron
Shenron

Reputation: 453

Sticking to Kestrel, i used the following logic:

The csproj must reference the "Microsoft.NET.Sdk.Web" sdk

In Program.cs in implement the logic needed to run 2 workers for 2 entrypoints

    public static void Main(string[] args)
    {
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) => {
                services
                    .AddHostedService<Workers.ForecastWorker>()
                    .AddHostedService<Workers.WeatherWorker>();
            })
            .Build()
            .Run();
    }

I found a SO question which has been answered

https://stackoverflow.com/a/68551696

providing a link to a gist to map specific controllers instead of all controllers

Then i create 2 workers implementations, each with its own WebHostBuilder instance and a different Startup class

In the Startup class, i reference only the controller related to the entrypoint/worker

    public override void ConfigureServices(IServiceCollection services)
    {
        //services.AddControllers();//removed to avoid referencing all controllers
        // use the extensions from Damian Hickey to reference needed controller only
        services.AddMvcCore().UseSpecificControllers(typeof(ForecastController));
    }

This way, i have 1 worker per entrypoint, each with its own controller

And you can have as many workers as needed

Upvotes: 0

u1986237
u1986237

Reputation: 78

According to the official definition, it cannot specify a certain controller. But you can determine the protocol through middleware, and then determine which routing template to map.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        //...
        app.Use(async (context,next)=>
        {
            var schema=context.Request.Scheme;
            if (schema == "https")
            {
                app.Map("/map",
                    (IApplicationBuilder app2) =>
                    {
                        app2.Run(async context =>
                        {
                             context.Response.Redirect("/home/get");
                        });
                    }
                );
            }
            await next();
        });
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }

Upvotes: 1

Related Questions