I working on an ASP.NET Core 2.2 web application. I have some issues when upgrade my application to .NET 6.
My issue is that there's no startup class in .NET 6.0 and I found program.cs file only.
I add startup class on my web application but I don't know how to use it inside Program.cs.
How to add or use startup class inside my program.cs?
This is the startup.cs file in .NET Core 2.2:
public class Startup
{
private readonly IConfigurationRoot configRoot;
private AppSettings AppSettings { get; set; }
public Startup(IConfiguration configuration)
{
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
Configuration = configuration;
IConfigurationBuilder builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
configRoot = builder.Build();
AppSettings = new AppSettings();
Configuration.Bind(AppSettings);
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddController();
services.AddDbContext(Configuration, configRoot);
services.AddIdentityService(Configuration);
services.AddAutoMapper();
services.AddScopedServices();
services.AddTransientServices();
services.AddSwaggerOpenAPI();
services.AddMailSetting(Configuration);
services.AddServiceLayer();
services.AddVersion();
services.AddHealthCheck(AppSettings, Configuration);
services.AddFeatureManagement();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory log)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(options =>
options.WithOrigins("http://localhost:3000")
.AllowAnyHeader()
.AllowAnyMethod());
app.ConfigureCustomExceptionMiddleware();
log.AddSerilog();
//app.ConfigureHealthCheck();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.ConfigureSwagger();
app.UseHealthChecks("/healthz", new HealthCheckOptions
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse,
ResultStatusCodes =
{
[HealthStatus.Healthy] = StatusCodes.Status200OK,
[HealthStatus.Degraded] = StatusCodes.Status500InternalServerError,
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable,
},
}).UseHealthChecksUI(setup =>
{
setup.ApiPath = "/healthcheck";
setup.UIPath = "/healthcheck-ui";
//setup.AddCustomStylesheet("Customization/custom.css");
});
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
And this is my .NET 6 program.cs:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
How to use the startup class inside program.cs class ?
Updated Post
every thing is working but configure service not working
because i don't know how to implement ILoggerFactory
on startup
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory log)
{
}
on program.cs
startup.Configure(app, app.Environment,???);
How to add logger factory as third paramter on program.cs
ILoggerFactory is buit in class
Updated it solved using
var app = builder.Build();
startup.Configure(
app,
builder.Environment,
app.Services.GetRequiredService<FooService>(),
app.Services.GetRequiredService<ILoggerFactory>()
);
can you please tell me how to apply swagger ui to check my api
New templates use the so called minimal hosting model but nobody prevents from switching back to the generic hosting one used previously (or via WebHost).
If you want to work with top-level statements you can copy contents of Main method to the Program.cs file and then copy all other methods declared in the old Program class. New Program.cs potentially can look something like this:
await CreateHostBuilder(args)
.Build()
.RunAsync();
// do not forget to copy the rest of the setup if any
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Or just remove the Startup class completely and move configure methods to corresponding parts of new file (maybe extracting some to concise extension methods).
You can manually instantiate the Startup and manually call the method ConfigureServices and Configure :
var builder = WebApplication.CreateBuilder(args);
var startup = new Startup(builder.Configuration);
startup.ConfigureServices(builder.Services);
var app = builder.Build();
startup.Configure(app, builder.Environment);
In ASP.NET Core 2.*, Startup.Configure accepted injected service :
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSingleton<IFooService, FooService>();
}
public void Configure(WebApplication app, IWebHostEnvironment env, IFooService fooService, ILoggerFactory loggerFactory)
{
fooService.Init();
...
}
}
Then you can :
var app = builder.Build();
startup.Configure(
app,
builder.Environment,
app.Services.GetRequiredService<FooService>(),
app.Services.GetRequiredService<ILoggerFactory>()
);
When I migrated my APIs, first I consider to reuse the Startup class... but finally I moved the configuration in extension methods.
Related
I am using a Blazor WASM Application with .NET6
Whenever I try to use my service class it gives me this error 'Unable to resolve service for type 'Persistence.Data.DataContext' while attempting to activate 'Services.Customers.CustomerService'.'
Heres my classes (simplified):
Persistence.Data.DataContext:
public class DataContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
// Add configurations
base.OnModelCreating(builder);
builder.ApplyConfiguration(new CustomerConfiguration());
}
}
Services.Customers.CustomerService:
public class CustomerService : ICustomerService
{
private readonly DataContext _dbContext;
public CustomerService(DataContext dbContext)
{
this._dbContext = dbContext;
}
//...
}
Client.Program.cs:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddMudServices();
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<ICustomerService, CustomerService>();
await builder.Build().RunAsync();
Server.Startup.cs:
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
[Obsolete]
public void ConfigureServices(IServiceCollection services)
{
var builder = new SqlConnectionStringBuilder(Configuration.GetConnectionString("DataContext"));
services.AddDbContext<DataContext>(options =>
options.UseSqlServer(builder.ConnectionString)
.EnableSensitiveDataLogging(Configuration.GetValue<bool>("Logging:EnableSqlParameterLogging")));
services.AddControllersWithViews();
services.AddScoped<DataInitializer>();
services.AddRazorPages();
services.AddScoped<ICustomerService, CustomerService>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataInitializer dataInitializer)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Vic API"));
dataInitializer.InitializeData();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
}
Thanks in advance
WebAssemblyHostBuilder projects don't use Startup.cs (and its Configure and ConfigureServices).
Blazor WebAssembly 3.2.0 Preview 1 release now available says:
Move the root component registrations in the Blazor WebAssembly client project from Startup.Configure to Program.cs by calling builder.RootComponents.Add(string selector).
Move the configured services in the Blazor WebAssembly client project from Startup.ConfigureServices to Program.cs by adding services to the builder.Services collection.
Remove Startup.cs from the Blazor WebAssembly client project.
ASP.NET Core Blazor Server with Entity Framework Core (EF Core) says:
The recommended approach to create a new DbContext with dependencies is to use a factory. EF Core 5.0 or later provides a built-in factory for creating new contexts.
and the example app at https://github.com/dotnet/blazor-samples/blob/main/6.0/BlazorServerEFCoreSample/BlazorServerDbContextExample/Program.cs does the registration direcly in main:
builder.Services.AddDbContextFactory<ContactContext>(opt => ...
In .NET 5 Startup.cs class there is Configure method which it's inside ILoggerFactory interface is injected. See below:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
loggerFactory.AddFile("Logs/mylog-{Date}.txt");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
..........
}
In .NET 6 how can I get the ILoggerFactory after the var app = builder.Build(); and call its AddFile() method to write logs like .NET 5 above.
You can do this like that:
using (var scope = app.Services.CreateScope())
{
var loggerFactory = scope.ServiceProvider.GetRequiredService(typeof(ILoggerFactory));
loggerFactory.AddFile("Logs/mylog-{Date}.txt");
}
In your Program.cs file, add the following code:
var builder = WebApplication.CreateBuilder(args);
// some initialization.
// example:
builder.Services.AddControllers().AddNewtonsoftJson();
// add logging
builder.Services.AddLogging(logging =>
{
logging.ClearProviders(); // optional (clear providers already added)
logging.AddFile("Logs/mylog-{Date}.txt")
});
I have been working on project for some time now and I was able to add migrations without problem but week or two ago i transitioned from using onconfiguring optionsbuilder.useSqlServer to connect to sql server from my context class to using services from Startup class to connect to database
When I try to run add-migration i get this error
Unable to create an object of type 'mojDbContext'. For the different patterns supported at design time
Program class
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 class
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<mojDbContext>(options=> options.UseSqlServer(Configuration.GetConnectionString("ererer")));
services.AddControllersWithViews();
services.AddMvc();
services.AddDistributedMemoryCache();
services.AddSession();
}
// 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();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
my context class with removed dbset properties to keep code smaller
public class mojDbContext : DbContext
{
public mojDbContext(DbContextOptions<mojDbContext> options)
: base(options)
{
}
}
when i run add-migration -verbose i get this
https://i.stack.imgur.com/Rn7Op.png
I work on an Web Application made with Asp Net Core and I try to use TestServer for integration testing.
I followed this blog post to setup my
test enviroment.
The Startup.cs of the application look like this :
public class Startup
{
public Startup(IHostingEnvironment env)
{
applicationPath = env.WebRootPath;
contentRootPath = env.ContentRootPath;
// Setup configuration sources.
var builder = new ConfigurationBuilder()
.SetBasePath(contentRootPath)
.AddJsonFile("appsettings.json")
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
// Many services are called here
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifetime)
{
// Many config are made here
loggerFactory.AddSerilog();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=auth}/{action=login}/{id?}");
});
}
}
For the integration test I use this code for create WebHostBuilder
var builder = new WebHostBuilder()
.UseContentRoot(appRootPath)
.UseStartup<TStartup>()
.UseEnvironment("test")
.ConfigureServices(x =>
{
.AddWebEncoders();
});
If I run a simple test that will check if home page is accessible it works.
For some raison I have to change some configuration in the Startup. So I add a call at Configure on WebHostBuilder :
var builder = new WebHostBuilder()
.UseContentRoot(appRootPath)
.UseStartup<TStartup>()
.UseEnvironment("test")
.ConfigureServices(x =>
{
.AddWebEncoders();
})
.Configure(x => {
// Some specific configuration
});
And, I don't know why (that's why I need your help), when I debug the same simple test like before,
the ConfigureServices and Configure method of the startup class are never called...
Even when I just let the Configure method blank.
Is this behavoir normal?
How can I set up specific configuration without adding it directly in the Startup.cs ?
WebHostBuilder.Configure replaces UseStartup, they can't be used together. Instead you can register an IStartupFilter inside ConfigureServices. Look here.
I'm trying to setup a new web application and I would to load the index.html (wwwroot folder) at startup.
In ASP.NET 5 Beta 6 this can be simply done only with app.UseStaticFiles() call inside Configure method even if MVC is configured.
Now, in Beta 7 (with Web Tools 2015 Beta7 installed), this doesn't work anymore :(
I found on many articles that I'm supposed to add this call too:
app.UseDefaultFiles(new DefaultFilesOptions
{
DefaultFileNames = new [] { "index.html" }
});
But even with that the index.html is not served by the framework.
Here is my Startup.cs:
public class Startup
{
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
.AddJsonFile("config.json")
.AddJsonFile($"config.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment())
{
builder.AddUserSecrets();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
// Add MVC services to the services container.
services.AddMvc();
}
public async void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Add static files to the request pipeline.
app.UseStaticFiles();
// Add default files to the request pipeline
app.UseDefaultFiles(new DefaultFilesOptions
{
DefaultFileNames = new [] { "index.html" }
});
// Add MVC to the request pipeline.
app.UseMvc();
}
}
Someone knows how to solve this problem?
It worked before because IIS fall through was opted in by default, but now you have to opt in explicitly as mentioned in the breaking changes in the announcements repo