Get value of Web root - asp.net-core

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"));
}

Related

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.

I can't access index.html in wwwroot when I use windows service to run my site

I can't access my static files in wwwroot when I use the windows service to run my site, but it works when I use IIS Express or IIS.
I build The project using Asp.Net Core 2.2.
The actions in the controllers are ok, just the static files cannot be accessed.
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().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// 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();
}
var df = new DefaultFilesOptions();
df.DefaultFileNames.Add("Index.html");
app.UseDefaultFiles(df);
app.UseStaticFiles();
app.UseMvc();
}
}
public class Program
{
public static void Main(string[] args)
{
var isService = !(Debugger.IsAttached || args.Contains("--console"));
if (isService)
{
var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
Directory.SetCurrentDirectory(pathToContentRoot);
var host = CreateWebHostBuilder(args.Where(arg => arg != "--console").ToArray()).Build();
host.RunAsService();
}
else
{
WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build().Run();
}
}
static int Port = 9099;
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options => { options.Listen(IPAddress.Any, Port); })
.UseStartup<Startup>();
}
It is because you are setting the directory when running the application as a windows-service.
Instead of doing this
var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
Directory.SetCurrentDirectory(pathToContentRoot);
Adjust your Webhost-Build definition
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options => { options.Listen(IPAddress.Any, Port); })
.UseStartup<Startup>()
.UseContentRoot(AppContext.BaseDirectory); // add this line
And then in the Startup class add static-file options
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
var df = new DefaultFilesOptions();
// these options are not necessary index.html is added by default
df.DefaultFileNames.Add("Index.html");
app.UseDefaultFiles(df);
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = env.WebRootFileProvider
});
app.UseMvc();
}
Also make sure that your index.html is always copied to the output directory.
Either add this to your csproj-file
<Content Update="wwwroot\index.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
or in visual-studio right click on it > properties > Copy to Output Directory > Copy always

Accessing the IHostingEnvironment in ConfigureServices method

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
}