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")
});
Related
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.
In .Net 5 and previous, we used to have a startup.cs file, with ConfigureServices and Configure Method inside. In below function I have added ILoggerManager as parameter of the function and then passed it to app.ConfigureExceptionHandler function.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerManager logger)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.ConfigureExceptionHandler(logger);
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
But with .Net 6 there is no startup.cs file and only program.cs file. There is no ConfigureService or Configure methods inside program.cs and all methods or functions are being called in a procedural way without any class or methods declaration like below:
var builder = WebApplication.CreateBuilder(args);
var logger = new LoggerManager();
builder.Services.AddControllers();
builder.Services.AddDbContext<DocumentDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DocumentStore")));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<ILoggerManager, LoggerManager>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.ConfigureExceptionHandler(<how to pass dependency here>);
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
My question is how can I pass a dependency to app.ConfigureExceptionHandler() function in .Net 6. I could not find any documentation on it.
Since you are creating LoggerManager yourself (var logger = new LoggerManager();) you can simply do:
app.ConfigureExceptionHandler(logger);
If you prefer to use the DI you can utilize IServiceProvider exposed via WebApplication.Services property:
var resolvedLoggerManager = app.Services.GetRequiredService<ILoggerManager>();
app.ConfigureExceptionHandler(resolvedLoggerManager);
For anyone trying obtain dependencies prior to calling builder.Build() (e.g. for use in services set-up), you can use an intermediate WebApplicationBuilder to build an additional WebApplication instance as below (Note that you cannot call builder.Build() twice, hence the need for the intermediate builder).
var builder = WebApplication.CreateBuilder(args);
// Use intermediate builder to obtain configuration etc
var intermediateBuilder = WebApplication.CreateBuilder(args);
var intermediateApp = intermediateBuilder.Build();
// Add services to the container.
var webHostEnvironment = intermediateApp.Services.GetRequiredService<IWebHostEnvironment>();
var configuration = new ConfigurationBuilder()
.AddJsonFile($"appsettings.{webHostEnvironment.EnvironmentName}.json", optional: false, reloadOnChange: false)
.Build();
...
I want to incorporate SignalR on my project but I can't I have an error when I add the line app.MapSignalR() in the Startup class. Here is the StartUp class:
public class Startup
{
public Startup(IConfiguration 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)
{...}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.MapSignalR(); // ERROR - IApplicaionBuilder dos not contain a definition MapSignalR() and the best extension method overload ' OwinExtensios.MapSignalR(IAppBuilder)' requires a receiver of type 'IAppBuilder'
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
I already added 'using Owin;' and it still doesn't work. What should I do?
Use like this. This is for .net core 3.0+
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
}
// 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("/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.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chatHub");
});
}
Read more : https://learn.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-3.1&tabs=visual-studio
Use below if .net core 2.2
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chatHub");
});
instead of
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chatHub");
});
I'm trying to figure out how to properly replace app.UseMvc() code that use to be part .net core 2.2. The examples go so far as to tell me what are all the codes I can call but I'm not yet understanding which should I call. For example for my MVC Web Application I have the following:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStatusCodePagesWithReExecute("/Error/Index");
app.UseMiddleware<ExceptionHandler>();
app.UseStaticFiles(new StaticFileOptions()
{
OnPrepareResponse = (context) =>
{
context.Context.Response.GetTypedHeaders()
.CacheControl = new CacheControlHeaderValue
{
MaxAge = TimeSpan.FromDays(30)
};
}
});
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
}
Before I would provide my routing inside the UseMvc() options. However now it seems I have to provide it inside MapControllerRoute But the examples always seem to also call MapRazorPages(). Do I need to call both or am I suppose to call just one? What is the actual difference between the two and how do I setup a default controller and a default action?
This is documented in the Migrate from ASP.NET Core 2.2 to 3.0 article. Assuming you want an MVC application.
The following example adds support for controllers, API-related
features, and views, but not pages.
services
// more specific than AddMvc()
.AddControllersWithViews()
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
And in Configure:
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
app.UseRouting();
// The equivalent of 'app.UseMvcWithDefaultRoute()'
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
// Which is the same as the template
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
}
For the order of use statemtents check the documentation.
The easiest way to fix it...
Build a new project targeting the .NET Core that you need and just copy the new Configure method and paste into your project that you are migrating to...
In this example...
Here are the old code lines:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
And here are the new code lines:
// 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();
});
}
i have a problem running my Asp.net core site on Debian 8 using netcore 1.1.1 with version 1.0.3
So i made a site using Asp.net core on my windows 10 platform using VS2017 and published it by dotnet publish -c release
Then i uploaded my project using FTP to Debian 8 and then i wrote
dotnet Altram.Web.Donate.dll
Unhandled Exception: System.InvalidOperationException: AddIdentity must be called on the service collection.
at Microsoft.AspNetCore.Builder.BuilderExtensions.UseIdentity(IApplicationBuilder app)
at Altram.Web.Donate.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) in /mnt/d/Development/C#/Visual Studio/Altram System/Altram.Web.Donate/Startup.cs:line 104
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
at Altram.Web.Donate.Program.Main(String[] args) in /mnt/d/Development/C#/Visual Studio/Altram System/Altram.Web.Donate/Program.cs:line 10
Aborted
in Startup.cs at ConfigureServices method i have
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
if (Environment.IsDevelopment())
{
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Info());
options.IncludeXmlComments(Path.Combine(PlatformServices.Default.Application.ApplicationBasePath,
"Altram.Web.Donate.xml"));
});
services.AddDbContext<DatabaseContext>(builder =>
{
builder.UseNpgsql(Configuration["Data:AltramDatabase"],
options => options.MigrationsAssembly("Altram.Web.Donate"));
});
services.AddDbContext<DatabaseContextCache>(builder =>
builder.UseInMemoryDatabase());
services.AddIdentity<User, IdentityRole>()
.AddEntityFrameworkStores<DatabaseContext>()
.AddErrorDescriber<ErrorDescriber>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
options.Password.RequiredLength = 46;
});
services.AddMvc();
services.AddDataInitializer();
services.DomainInitializer();
services.Initialize(links =>
{
links.Login = Configuration["Robokassa:RobokassaLogin"];
links.Mode = Configuration["Robokassa:RobokassaMode"];
links.Pass1 = Configuration["Robokassa:RobokassaPass1"];
links.Pass2 = Configuration["Robokassa:RobokassaPass2"];
});
services.AddLogging();
}
}
and Configure Method
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
So it give me that error at app.UseIdentity(); Line
and it's working very good without any problems on Windows 10.
I use PostgresSql with my project.
How can i fix this problem?
I have fixed my error by removing and put it outside of the if brackets
services.AddIdentity<User, IdentityRole>()
.AddEntityFrameworkStores<DatabaseContext>()
.AddErrorDescriber<ErrorDescriber>()
.AddDefaultTokenProviders();
From the if(Enviroment.IsDevelopment()) code because when i start dotnet from the terminal it starts at production Enviroment mode, so addIdentity won't work.