Accessing the IHostingEnvironment in ConfigureServices method - asp.net-core

I need to check in ConfigureServices method whether the current hosting environment name is 'Development'.
So using IHostingEnvironment.IsDevelopment() method may be ok for me, but unlike in Configure method, I do not have IHostingEnvironment env.

just create a property in the Startup class to persist the IHostingEnvironment. Set the property in the Startup constructor where you already have access, then you can access the property from ConfigureServices

Copied here from question marked as duplicate of this one and deleted. Credit to a-ctor.
If you want to access IHostingEnvironment in ConfigureServices you will have to inject it via the constructor and store it for later access in ConfigureServices:
public class Startup
{
public Startup(IConfiguration configuration, IHostingEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IHostingEnvironment Environment { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
System.Console.WriteLine($"app: {Environment.ApplicationName}");
}
// rest omitted
}

IHostingEnvironment is deprecated in Core 3.1
private readonly IWebHostEnvironment _env;
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
_env = env;
Configuration = configuration;
}
should do the trick...
Then reference anywhere with _env.IsDevelopment() etc...

If you aren't using a Startup class and are calling .Configure() directly, you can access the IHostingEnvironment or IWebHostEnvironment using GetService:
ASP.NET Core 2.2:
.Configure(app => {
var hostingEnvironment = app.ApplicationServices.GetService<IHostingEnvironment>();
if (hostingEnvironment?.IsDevelopment() == true)
{
app.UseDeveloperExceptionPage();
}
// .. Other stuff
});
ASP.NET Core 3.x:
.Configure(app => {
var hostingEnvironment = app.ApplicationServices.GetService<IWebHostEnvironment>();
if (hostingEnvironment?.IsDevelopment() == true)
{
app.UseDeveloperExceptionPage();
}
// .. Other stuff
});

If you don't have a Startup class (you may be creating a service) you can get the environment from the hostContext in ConfigureServices like so:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
IConfiguration config = hostContext.Configuration;
Configuration = config;
var env = hostContext.HostingEnvironment;
EnvironmentName = env?.EnvironmentName;
...

There are some examples here but none of them seem accurate to the newest release of dotnet, so here we go.
First, in your Startup.cs you should have a reference in your initial constructor like this:
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
this.Configuration = configuration;
this.Environment = env;
}
We can take the Env and tack it onto ServiceCollection like so:
services.AddSingleton(sp => this.Environment);
Then we can access it in any extension method or other place like so:
var hostEnvironment = services.BuildServiceProvider().GetRequiredService<IHostEnvironment>();
if (hostEnvironment.IsDevelopment())
{
//do something if in dev
}

Related

Logging in ASP.NET Core 5

I have written a project with ASP.NET Core. When I publish the project to the server, my user can not log in for more than 30 minutes, and after 30 minutes, it needs to be re-authenticated and redirected to the login page.
This is my code in the ConfigureServices method:
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = false;
options.LoginPath = "/Login";
options.AccessDeniedPath = "/NotFound";
options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.LogoutPath = "/SignOut";
});
And this is in the Configure method:
app.UseAuthentication();
app.UseAuthorization();
This problem only occurs when the project is published
UPDATE
You can find machine key here. It will help you solve the issue.
Reason
Application generates new machine key every time when it has been restarted. So way to solve problem is to force application to use constant key.
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
_env = env;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment _env { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetApplicationName($"my-app-{_env.EnvironmentName}")
.PersistKeysToFileSystem(new DirectoryInfo($#"{_env.ContentRootPath}\keys"));
services.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
}
}
Change FromDays to FromMinutes will help you solve the issue.
options.ExpireTimeSpan = TimeSpan.FromMinutes(30); //TimeSpan.FromDays(30);

IwebHostEnvironment interface

i have used IwebHostEnvironment in my code but i have a question ..
IWebHostEnvironment is an interface used to provide info about hosting & can get data about path from it
why i take an instance from it and inject it like i was inject a _db without register it in
ConfigureServices method like i register Db context?!
public class ProductController : Controller
{
private readonly App_DbContext _db;
private readonly IWebHostEnvironment _webHostEnvironment;
public ProductController(App_DbContext db,IWebHostEnvironment webHostEnvironment)
{
_db = db;
_webHostEnvironment = webHostEnvironment;
}
public IActionResult Index()
{
IEnumerable<Product> products= _db.Product;
return View(products);
}
this is configure services Method
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<App_DbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllersWithViews();
}
Agree with #Nkosi, you can refer to this section, IWebHostEnvironment is one of the framework-registered services.

.NET Core Identity and Simple Injector. Crosswire not working

I am using simple injector (4.8.1) on a project that uses asp.net core identity. I tried to crosswise UserManager but I got an error saying
No service for type 'Microsoft.AspNetCore.Identity.UserManager`1[Tenancy.Core.Domain.AppUser]' has been registered."
the SimpleInjectorConfig class is:
public static class SimpleInjectorConfig
{
private static Container _container;
public static void ConfigureServices(IServiceCollection services, IConfiguration config,
IWebHostEnvironment env)
{
_container = new Container();
_container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
_container.ConfigureCore(config, env);
_container.RegisterInitializer<BaseApiController>(controller =>
{
controller.Mediator = _container.GetInstance<IMediator>();
});
services.AddSingleton(_container);
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddControllers();
services.AddLogging();
// Sets up the basic configuration that for integrating Simple Injector with
// ASP.NET Core by setting the DefaultScopedLifestyle, and setting up auto
// cross wiring.
services.AddSimpleInjector(_container, options =>
{
// AddAspNetCore() wraps web requests in a Simple Injector scope and
// allows request-scoped framework services to be resolved.
options
.AddAspNetCore()
.AddControllerActivation();
options.AddLogging();
options.CrossWire<UserManager<AppUser>>();
});
}
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSimpleInjector(_container);
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
IdentityModelEventSource.ShowPII = true;
}
//app.UseHttpsRedirection();
_container.Verify();
}
}
and I called it in my Startup.cs file
public class Startup
{
public IConfiguration _configuration { get; }
public IWebHostEnvironment _env { get; }
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
_configuration = configuration;
_env = env;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
SimpleInjectorConfig.ConfigureServices(services, _configuration, _env);
CorsConfig.ConfigureServices(services);
DatabaseConfig.ConfigureServices(services, _configuration);
MvcConfig.ConfigureServices(services);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
SimpleInjectorConfig.Configure(app, env);
CorsConfig.Configure(app, _configuration);
MvcConfig.Configure(app);
}
}
The configurations have their own class and called in the Startup called in the Startup class just to keep it clean, SimpleInjectorConfig is the config class for simple injector.

.net core not showing HTML static file changes

I made some changes to the static file index.html but running via .net-core and inspecting elements these changes do not apply however when I open the static file via live server extension of vscode I can see the changes.
I am very new to .net core, I looked up a few threads but couldn't find what the problem is or a similar one.
My Startup class looks as so:
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.AddControllers();
services.AddMvc().ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});
}
// 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.UseDefaultFiles();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
also, the project repository is here
Thanks to everyone who takes their time to help.

Get value of Web root

On an ASP.NET Core Startup file I have the following:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
services.AddPOLocalization(x => x.ResourcesPath = "wwwroot/assets");
}
How can get the value defined for web root instead of hard code it (wwwroot)?
There is an IHostingEnvironment.WebRootPath property:
Gets or sets the absolute path to the directory that contains the web-servable application content files.
You can get instance from DI container:
private IHostingEnvironment _env;
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
// use env.WebRootPath here or variable in private field for future using
// (like in ConfigureServices method)
_env = env;
...
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddPOLocalization(x =>
x.ResourcesPath = System.IO.Path.Combine(_env.WebRootPath, "assets"));
}