Search code examples
c#.net-6.0

The ConfigureServices method must either be parameterless Program.cs in .NET 6


I am trying to put Startup class back to .NET 6 project Web API.

So I just altered Program.cs to:

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

    public static IWebHost BuildWebHost(string[] args)
    {
        return WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
    }
}

and I extracted all service registrations and stuff into my Startup class:

    public class Startup
    {
        public WebApplication InitializeApp()
        {
            var builder = WebApplication.CreateBuilder();
            IServiceCollection servicesservices = builder.Services;
            ConfigureServices(servicesservices, builder);
            var app = builder.Build();
            Configure(app);
            return app;
        }

        public void ConfigureServices(IServiceCollection services, WebApplicationBuilder builder)
        {
            ConfigurationManager configuration = builder.Configuration;
            services.AddApplicationLayer();
            services.AddPersistanceLayer(builder.Configuration);
            services.AddControllers();
            services.AddEndpointsApiExplorer();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "VehicleReservation", Version = "v1" });
            });
        }

        public void Configure(WebApplication app)
        {
            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseHttpsRedirection();
            app.UseErrorHandlingMiddleware();
            app.UseAuthorization();

            app.MapControllers();

            SeedDatabase(app);
        }

        private void SeedDatabase(WebApplication app)
        {
            using (var scope = app.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                var vehicleReservationContext = services.GetRequiredService<VehicleReservationContext>();
                VehicleReservationContextSeed.SeedAsync(vehicleReservationContext);
            }
        }
    }

but I have an error: `The ConfigureServices method must either be parameterless or take only one parameter of type IServiceCollection.'

I see that I have 2 params for my ConfigureServices, but Im not sure, how to make it to have 1 or non parameters?

APPROACH #1: Is to have _builder globally defined within Startup class

    public class Startup
    {
        private WebApplicationBuilder _builder;
        public Startup(WebApplicationBuilder builder)
        {
            _builder = builder;
        }

        public WebApplication InitializeApp()
        {
            var _builder = WebApplication.CreateBuilder();
            IServiceCollection servicesservices = _builder.Services;
            ConfigureServices(servicesservices);
            var app = _builder.Build();
            Configure(app);
            return app;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            ConfigurationManager configuration = _builder.Configuration;
            services.AddApplicationLayer();
            services.AddPersistanceLayer(_builder.Configuration);
            services.AddControllers();
            services.AddEndpointsApiExplorer();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "VehicleReservation", Version = "v1" });
            });
        }

        public void Configure(WebApplication app)
        {
            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseHttpsRedirection();
            app.UseErrorHandlingMiddleware();
            app.UseAuthorization();

            app.MapControllers();

            SeedDatabase(app);
        }

        private void SeedDatabase(WebApplication app)
        {
            using (var scope = app.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                var vehicleReservationContext = services.GetRequiredService<VehicleReservationContext>();
                VehicleReservationContextSeed.SeedAsync(vehicleReservationContext);
            }
        }
    }

Solution

  • Startup classes support configuration injection via ctor, so since you are you only using Configuration from WebApplicationBuilder just inject it:

    public IConfiguration Configuration { get; }
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    
    // ...
    
    // to clarify configure method
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI();
        }
        // ...
    }
    

    And then you can use Configuration property in ConfigureServices.

    See the docs on the Startup class.