Create HostingEnvironment instance with WebRootPath - c#

I'm migrating from netcore2.1 to netcore3.1. I have a service where I need to create an IServiceProvider and inject IWebHostEnvironment (I used to inject IHostingEnvironment in netcore2.1). The code used to just create a new Microsoft.Extensions.Hosting.Internal.HostingEnvironment instance but that class doesn't contain WebRootPath anymore. I fetched git repo and tried to look for implementations of IWebHostEnvironment but it seems that the only implementation is internal to aspnetcore which is of no use.
Is there a possibility to create an instance of IWebHostEnvironment somehow?
Daniel

Hi You can access WebRoot Path using in Core 3.1
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
public class HomeController : Controller
{
private readonly IWebHostEnvironment _hostingEnv;
public HomeController(IWebHostEnvironment hostingEnv)
{
_hostingEnv = hostingEnv;
}
private Void GetWebRoot()
{
var webRootPath = _hostingEnv.WebRootPath;
}
}
Can you try this, upvote if it helps

Related

Dependency Injection - Multiple projects

I'm creating a wep api and this is the current structure:
API - The Web API (.net core web api project)
DAL - DbContext and Entities (.net core class library)
DTO - Data Transfert Objects - The classes I send to the client without sensible data (.net core class library)
REPO - Contains de Interfaces and Repositories (.net core class library)
For information I had everything on the same project and decided to split into multiple class libraries.
What I've done until now:
Added the references beetween each project
Update usings
Changed namespaces names to the correct ones
Solution as 0 errors
I think that my problem is related to dependency injection because when I try to access a controller from postman or from the browser this error happens:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: FootballManager.REPO.ILeagueRepository Lifetime: Scoped ImplementationType: FootballManager.REPO.LeagueRepository': Unable to resolve service for type 'FootballManager.DAL.FootballManagerAPIContext' while attempting to activate 'FootballManager.REPO.LeagueRepository'.
My Startup.cs looks like this:
using FootballManager.REPO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace FootballManager.API
{
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.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
});
});
services.AddControllers().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
services.AddScoped<ILeagueRepository, LeagueRepository>();
services.AddScoped<IMatchRepository, MatchRepository>();
services.AddScoped<IPlayerRepository, PlayerRepository>();
services.AddScoped<IRefereeRepository, RefereeRepository>();
services.AddScoped<ITeamRepository, TeamRepository>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
This is my controller code where I do the injection:
public class LeaguesController : ControllerBase
{
private readonly ILeagueRepository _repo;
public LeaguesController(ILeagueRepository repo)
{
_repo = repo;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<LeagueDto>>> GetLeagues()
{
return await _repo.GetAll();
}
}
For my DbContext connection I did directly on the DAL project like this (I dont think that the problem is here):
public partial class FootballManagerAPIContext : DbContext
{
public FootballManagerAPIContext()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(#"Server =.\SQLEXPRESS; Database = FootballManagerAPI; Trusted_Connection = True;");
}
}
}
After hours on the web and stackoverflow I still can't find any working solution...
How can I solve this error and why I'm having this? Thank you.
You never instantiate your DbContext - the error is very explicit about that;
Unable to resolve service for type 'FootballManager.DAL.FootballManagerAPIContext'
You also need to register the DbContext you need in the startup including configuration
I cant add comments to you question so I leave this here:
Maybe its a stupid question but, maybe you forgot it:
Does LeagueRepository inherit from ILeagueRepository?
I think this will help you.
Check out this video in which i explain how to implement dependency injection using autofac.
https://studio.youtube.com/video/XvklkAj7qPg/edit
Also i sugest that you should use disposable database connection, connect and disconnect in every method. So do not use dependency injection for db context.
Check if you registered the db context.
services.AddDbContext(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
In the services configuration i can't see it.
Thanks,
Liviu

How do I access a directory path in asp.net core from server side code?

I'm trying to get the current directory path from server side code. In asp.net we used HttpContext.Current.Server.MapPath to get the path. But it's different with asp.net core we're supposed to use IHostingEnvironment to get the path. As far as I know it's only used in the StartUp class and in Controllers but what I'm trying to do is use it in a server side class. How do I do that?
I've tried to pass the IHostingEnvironment value to the constructor of a server side class but it sets it to null. Nothing else was added in the StartUp class.
I also tried to look for any help on the internet and couldn't believe there was nothing that can help me to set the value in a server side class.
Here's an example of my code:
public class PathHelper
{
private static IHostingEnvironment _hostingEnvironment;
public PathHelper(IHostingEnvironment environment)
{
_hostingEnvironment = environment;
}
public static string RootPath
{
get
{
return _hostingEnvironment.ContentRootPath;
}
}
The error I get is
null reference at the constructor level.
This is not the best option, but this is what I currently doing right now.
I pass the IHostingEnvironment to static class to be used globally and init on Configure method in Startup.cs.
public static class Context
{
public static IHostingEnvironment HostingEnvironment;
}
Assign on Configure method in Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
//.....
namespace.Context.HostingEnvironment = env;
}

Getting the Base URL in ASP.Net Core

I've just recently switched over from ASP.NET MVC to using .Core 2 and I can't figure out how to get the current URL in Core. I could get it easily enough using the Request in previous asp.net versions, but since that's no long valid in .Net Core I'm at a loss.
I haven't been able to find any way from my google searching as of now.
Any help is appreciated. Thanks!
In the ConfigureServices method of your Startup.cs file, add the line:
services.AddHttpContextAccessor();
and you will now have access to the IHttpContextAccessor interface throughout your code when using dependency injection.
Usage as follows:
public class CustomerRepository
{
private readonly IHttpContextAccessor _context;
public CustomerRepository(IHttpContextAccessor context)
{
_context = context;
}
public string BaseUrl()
{
var request = _context.HttpContext.Request;
// Now that you have the request you can select what you need from it.
return string.Empty;
}
}
Hope this answers your question :)
Try:
public class Startup {
public Startup(IConfiguration configuration, IHostingEnvironment env) {
Configuration = configuration;
HostingEnvironment = env;
var url = configuration[WebHostDefaults.ServerUrlsKey];
}
Please note that you can get more than one url.

Httpcontext Does not contain the definition of a server? [duplicate]

Sorry for a noob question, but it seems I can't get Server.MapPath from Controller. I need to output json file list from images folder at wwwroot. They are is at wwwroot/images. How can I get a reliable wwwroot path?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using www.Classes;
using System.Web;
namespace www.Controllers
{
[Route("api/[controller]")]
public class ProductsController : Controller
{
[HttpGet]
public IEnumerable<string> Get()
{
FolderScanner scanner = new FolderScanner(Server.MapPath("/"));
return scanner.scan();
}
}
}
Server.MapPath seems not available from System.Web namespace.
Project is using ASP.NET 5 and dotNET 4.6 Framework
You will need to inject IWebHostEnvironment into your class to have access to the ApplicationBasePath property value: Read about Dependency Injection. After successfully injecting the dependency, the wwwroot path should be available to you. For example:
private readonly IWebHostEnvironment _appEnvironment;
public ProductsController(IWebHostEnvironment appEnvironment)
{
_appEnvironment = appEnvironment;
}
Usage:
[HttpGet]
public IEnumerable<string> Get()
{
FolderScanner scanner = new FolderScanner(_appEnvironment.WebRootPath);
return scanner.scan();
}
Edit: IHostingEnvironment has been replaced by IWebHostEnvironment in later versions of asp.net.
I know this has already been answered, but it has given me different results depending on my hosting environment (IIS Express vs IIS). The following approach seems to work for all hosting environments nicely if you want to get your wwwroot path (see this GitHub issue).
For example
private readonly IHostingEnvironment _hostEnvironment;
public ProductsController(IHostingEnvironment hostEnvironment)
{
_hostEnvironment = hostEnvironment;
}
[HttpGet]
public IEnumerable<string> Get()
{
FolderScanner scanner = new FolderScanner(_hostEnvironment.WebRootPath);
return scanner.scan();
}
For those who deploy to Azure and come into this error. What I did was a work around for it, I haven't tried to figure out why environment of Azure is different than local IIS.
Here is my work around:
if (string.IsNullOrWhiteSpace(_environment.WebRootPath))
{
_environment.WebRootPath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
}
Of course you will need:
private IHostingEnvironment _environment;
public OnboardingController(IHostingEnvironment environment)
{
_environment = environment;
}
There is another way to implement this right from startup. It is not exact solution to this case per se, but I modified it to suit my need. We need a singleton for this. This is a startup class with environment injection.
namespace www
{
public class Startup
{
private IHostingEnvironment _env;
public Startup(IHostingEnvironment env)
{
_env = env;
Environment.rootPath = env.WebRootPath;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseMvc();
}
}
}
The environment variables I was looking for is there, IHOstingEnvironment. But for my purpose, I need to make Environment class like this to easily access all environment items from all project. This singleton will provide data to configuration, environment, and many other thing. But for this thread, I would just put one rootPath property.
namespace www.Utilities
{
public class Environment
{
private static Environment instance;
private static String _rootPath;
private Environment() { }
public static Environment Instance
{
get
{
if (instance == null)
{
instance = new Environment();
}
return instance;
}
}
public static string rootPath
{
set
{
_rootPath = value;
}
get
{
return _rootPath;
}
}
}
}
As I have accepted Oluwafemi's answers, I'll keep it that way, since he led me to this. But I think this is the better way to access environment variables throughout the project

Get wwwroot folder path from ASP.NET 5 controller VS 2015

Sorry for a noob question, but it seems I can't get Server.MapPath from Controller. I need to output json file list from images folder at wwwroot. They are is at wwwroot/images. How can I get a reliable wwwroot path?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using www.Classes;
using System.Web;
namespace www.Controllers
{
[Route("api/[controller]")]
public class ProductsController : Controller
{
[HttpGet]
public IEnumerable<string> Get()
{
FolderScanner scanner = new FolderScanner(Server.MapPath("/"));
return scanner.scan();
}
}
}
Server.MapPath seems not available from System.Web namespace.
Project is using ASP.NET 5 and dotNET 4.6 Framework
You will need to inject IWebHostEnvironment into your class to have access to the ApplicationBasePath property value: Read about Dependency Injection. After successfully injecting the dependency, the wwwroot path should be available to you. For example:
private readonly IWebHostEnvironment _appEnvironment;
public ProductsController(IWebHostEnvironment appEnvironment)
{
_appEnvironment = appEnvironment;
}
Usage:
[HttpGet]
public IEnumerable<string> Get()
{
FolderScanner scanner = new FolderScanner(_appEnvironment.WebRootPath);
return scanner.scan();
}
Edit: IHostingEnvironment has been replaced by IWebHostEnvironment in later versions of asp.net.
I know this has already been answered, but it has given me different results depending on my hosting environment (IIS Express vs IIS). The following approach seems to work for all hosting environments nicely if you want to get your wwwroot path (see this GitHub issue).
For example
private readonly IHostingEnvironment _hostEnvironment;
public ProductsController(IHostingEnvironment hostEnvironment)
{
_hostEnvironment = hostEnvironment;
}
[HttpGet]
public IEnumerable<string> Get()
{
FolderScanner scanner = new FolderScanner(_hostEnvironment.WebRootPath);
return scanner.scan();
}
For those who deploy to Azure and come into this error. What I did was a work around for it, I haven't tried to figure out why environment of Azure is different than local IIS.
Here is my work around:
if (string.IsNullOrWhiteSpace(_environment.WebRootPath))
{
_environment.WebRootPath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
}
Of course you will need:
private IHostingEnvironment _environment;
public OnboardingController(IHostingEnvironment environment)
{
_environment = environment;
}
There is another way to implement this right from startup. It is not exact solution to this case per se, but I modified it to suit my need. We need a singleton for this. This is a startup class with environment injection.
namespace www
{
public class Startup
{
private IHostingEnvironment _env;
public Startup(IHostingEnvironment env)
{
_env = env;
Environment.rootPath = env.WebRootPath;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseMvc();
}
}
}
The environment variables I was looking for is there, IHOstingEnvironment. But for my purpose, I need to make Environment class like this to easily access all environment items from all project. This singleton will provide data to configuration, environment, and many other thing. But for this thread, I would just put one rootPath property.
namespace www.Utilities
{
public class Environment
{
private static Environment instance;
private static String _rootPath;
private Environment() { }
public static Environment Instance
{
get
{
if (instance == null)
{
instance = new Environment();
}
return instance;
}
}
public static string rootPath
{
set
{
_rootPath = value;
}
get
{
return _rootPath;
}
}
}
}
As I have accepted Oluwafemi's answers, I'll keep it that way, since he led me to this. But I think this is the better way to access environment variables throughout the project

Categories