Startup
static void Main
Asp.Net Core is a true console application, with a public static void Main(string[] args)
In Core 3.1 there were separate Program.cs and Startup.cs. In .net 6, everything is in Program.cs (but old projects aren't upgraded, and Startup.cs still works).
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
var app = builder.Build();
//trimmed app.Use stuff
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name:"default"
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
- WebApplication.CreateBuilder is the new WebHost.CreateDefaultBuilder
- UseStartup<Startup>();> will error. Startup doesn't exist anymore. But you can extract out the configuration.
Nuget packages
You will probably need:
- Dependency Injection - Autofac.Extensions.DependencyInjection See example
- Logging - NLog.Web.AspNetCore. See example
- Some sort of authentication. For webAPI, probably Microsoft.AspNetCore.Authentication.JwtBearer See example
- For webAPI, you probably want MediatR
<PackageReference Include="MediatR" Version="12.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.22" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.4" />
Older versions of Core
.Net Core 3.1
In .net core 3.1 for asp use WebHost (in .net6 you can use WebApplication, which removes the need for Startup.cs)
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();>
});
}
Startup.cs
In classic Asp.net, you configured things in Global.asax. In Core 1-5, you use Startup.cs. In .net 6 it's gone again.
There is no base class or interface. The name and standard methods are conventions. You can have multiple "Startup" classes, but only one is used... either the project namespace, or it uses namespace alphabetical order(!).
Net6 - if you use WebApplication.CreateBuilder(args), you can't use Startup in the same way. But you can new it up and use it explicitly.
//using the new WebApplication instead of WebHost
var builder = WebApplication.CreateBuilder(args);
//just new up startup with the configuration
var startup = new Startup(builder.Configuration);
//then add the services (AddControllersWithViews)
startup.ConfigureServices(builder.Services);
//as before
var app = builder.Build();
//then do the configuration
startup.Configure(app, app.Environment);
//as before
app.Run();
Structure
The minimum:
public class Startup
{
//REQUIRED: configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello :)");
});
}
}
Method | Notes | Arguments |
Startup.Configure(IApplicationBuilder app, ...) | Required. Normally app.UseMvc() | IApplicationBuilder (required), IWebHostEnvironment |
Startup.ConfigureServices | (optional) build dependency injection | IServiceCollection (required, only input) |
Constructor | Initial configuration, initialize "application" variables such as configuration | IConfiguration, IWebHostEnvironment |
IApplicationBuilder must only be used for Configure, and IServiceCollection must only be used for ConfigureServices
- IWebHostEnvironment or IHostEnvironment (in .net core 1/2 this was IHostingEnvironment) - EnvironmentName, WebRootPath, ContentRootPath
- In .net core 1/2 you could inject a ILoggerFactory but that's not possible in .net core 3 (initialize the logger in Program.cs)
- A less commonly used Startup method is ConfigureContainer(ContainerBuilder), which is called after ConfigureServices.
- The startup loader checks and calls environment-named variations of the methods, eg ConfigureProductionServices() if your environment is production. This is so weird, avoid.
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace CoreWeb
{
public class Startup
{
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
- app.UseMvc() is obsolete (.net IRouting). For .net 3+, app.UseEndpoints(e => { e.MapControllers();});
- Order is important- app.UseRouting(); then .UseAuthorization() then .UseEndpoints()
- .Net 6 minimal Apis hides UseRouting and UseEndpoints, calling them implicitly in the correct order
Type | ConfigureServices(IServiceCollection services) | Configure(IApplicationBuilder app, ... |
---|---|---|
API | services.AddControllers(); Includes CORS/Authorization etc |
app.UseEndpoints(endpoints => Hooks up controllers with attributes ([Route("[controller]")] or [HttpPost] |
MVC | services.AddControllersWithViews(); Same as API, but with views! |
app.UseEndpoints(endpoints => You have one or more routing patterns to match controller and action names. NB: if it has attributes it is ignored. MapDefaultControllerRoute does what the more explicit template code does, and is probably all you need. |
Razor Pages | services.AddRazorPages(); |
app.UseEndpoints(endpoints => |
.Net Core 1
In RC1 it was in Startup.cs; from RC2 it is in Program.cs
public static void Main(string[] args)
{
var host = new WebHostBuilder(args)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
For Windows/IIS, you don't need to change this.