Resolved How to use webRootPath inside my controller?

destro

Well-known member
Joined
Mar 28, 2020
Messages
46
Programming Experience
1-3
I am trying to upload image to wwwroot path using my homecontroller but my IhostingEnvironment interface has no such property named WebRootPath, infact it has no properties at all when I peeked the definition. How do I access this path in my HomeController?

Startup.cs:
public class Startup
    {
        private IConfiguration _config;
        public Startup(IConfiguration config)
        {
            _config = config;
        }
      
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<IAstrologerRepository, SQLAstrologerRepository>();

            services.AddMvc();
            services.AddDbContextPool<ApplicationDbContext>(options =>
     options.UseSqlServer(_config.GetConnectionString("DefaultConnection")));
         
        }

        // 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();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseAuthentication();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

                routes.MapRoute(name: "login",
                    template: "{controller=Home}/{action=Login}");
              
            });

        }
    }


HomeController.cs:
[CODE lang="csharp" title="Startup.cs"]
public class HomeController : Controller
    {
        private readonly IAstrologerRepository _astrologerRepository;
        private readonly IHostingEnviroment _hostingEnviroment;

        public HomeController(IAstrologerRepository astrologerRepository, IHostingEnviroment hostingEnviroment)
        {

            _astrologerRepository = astrologerRepository;
            _hostingEnviroment = hostingEnviroment;
        }


        // GET: /<controller>/
        public ViewResult Index()
        {
            var model = _astrologerRepository.GetAllAstrologers();
            return View(model);
        }

    
        [HttpGet]
        public ViewResult SignUp()
        {
          
            return View();
        }
        [HttpPost]
        public IActionResult SignUp(AstrologerCreateViewModel model)
        {
            if (ModelState.IsValid)
            {
             //   string fileName = null;
                if(model.profilephoto!=null)
                {
                  
                
                }
               // Astrologer newastrologer = _astrologerRepository.Add(astrologer);
                return RedirectToAction("Index");
            }
            return View();
        }
    }
 
Warning - This API is now obsolete.

This type is obsolete and will be removed in a future version. The recommended alternative is Microsoft.AspNetCore.Hosting.IWebHostEnvironment.
IWebHostEnvironment also has a WebRootPath property.
 
Also as a quick aside, on most IIS enviroments, there is only read permissions enabled on the web root directory, but read-write permission is given to the App_Data directory with IIS and ASP.NET providing additional security to prevent J. Random Web User from browsing directly into the App_Data to harvest any data or files that they shouldn't have access to. Obviously this can be overridden, but in general you should respect this convention and not write your files to your web root. Imagine what would happen if the user could upload a file to your web root and they can control the file name: Here came Mr. Hacker who uploads a default.htm to your web root and now your site has been hijacked; or a login.aspx to start harvesting usernames and passwords; or a web.config to override your setting; etc. Yes, I know that you are using Kestrel and not bound by what IIS does, but do consider the implications of having access to the web root.
 

IWebHostEnvironment also has a WebRootPath property.

I am using asp.net core 2.1 in VS community 2017 should I still use IWebHostEnvironment injection in my controller instead of IHostingEnvironment injection??
 
Last edited:
Also as a quick aside, on most IIS enviroments, there is only read permissions enabled on the web root directory, but read-write permission is given to the App_Data directory with IIS and ASP.NET providing additional security to prevent J. Random Web User from browsing directly into the App_Data to harvest any data or files that they shouldn't have access to. Obviously this can be overridden, but in general you should respect this convention and not write your files to your web root. Imagine what would happen if the user could upload a file to your web root and they can control the file name: Here came Mr. Hacker who uploads a default.htm to your web root and now your site has been hijacked; or a login.aspx to start harvesting usernames and passwords; or a web.config to override your setting; etc. Yes, I know that you are using Kestrel and not bound by what IIS does, but do consider the implications of having access to the web root.
That was really enlightening @Skydiver but
I am simply using it on custom-file-input control for saving uploaded profile pic of the user. Should I place it somewhere else? I am gonna use authentication for users to allow them to change their profile pic. Should I go with some other approach otherwise?

It will be hosted online in future for sure, I am not even sure how to access webrootpath in this project. @JohnH suggested using IWebHostEnvironment. Should I clear out the IHostingEnviroment from startup.cs and homecontroller.cs to place IWebHostEnvironment instead?
 
Last edited:
I only recommend saving to a local file system if you know that your application will only ever live on a single machine from now until the end of time. For web applications, there is a choice to either scale up (by adding more CPU, RAM, disk space, etc.) or scale out (by adding more machines behind a load balancer). Scaling out is often cheaper than scaling up. Now imaging if your user uploaded their picture to machine 1, and the next web request from the same user is sent to machine 2. Where is their picture now?

Yes, you can use the local filesystem for something that you know is transient like a picture upload on which you want to do some post-processing before putting the image is something more durable and agnostic of which machine is accessing it (ex. a file share or a database).

If you are still on the learning curve and this is a toy application or a simple prototype, then go ahead and save l locally. Just make sure to remind your management team that the prototype is not production ready.
 
Out of curiosity, why do you even need the web root path. If this is a Kestrel based application, then the default running environment has the current directory set to the same directory that contains web application executable. Just use relative paths. Or is there some unwritten constraint or requirement that forces you to need the full path?
 
I am using asp.net core 2.1
End of life for .NET Core 2.1 is August 21, 2021. Might as well plan ahead and go to .NET Core 3.1 which has a longer window of life: December 3, 2022.
 
Out of curiosity, why do you even need the web root path. If this is a Kestrel based application, then the default running environment has the current directory set to the same directory that contains web application executable. Just use relative paths. Or is there some unwritten constraint or requirement that forces you to need the full path?
Actually I am still on learning curve, I am following a video which used the constructor injection of IHostingEnvironment and using its webrootpath property to save the profile image uploaded by user inside the create action of type IActionResult. I did the same but my IHostingEnvironment interface is empty with no properties at all.
 
Ahaa... I fixed it. I was using the wrong Interface of Hosting Environment. I had to implement the one that comes with Microsoft.AspNetCore.Hosting, there were two in the list. One was from constructor and other was using namespace. I changed the type to interface with using namespace and all the properties were there. Thanks for great advise everyone. @Skydiver @JohnH. I will update to 3.1 within a month once I have the hang of all CRUD operations.
 
I've got the same error I was using "using Microsoft.Extensions.Hosting.Internal;" with "IWebHostEnvironment". When you're using Core 3.1 you need to use: "using Microsoft.AspNetCore.Hosting; " and "IWebHostEnvironment" That will solve all your problems. Thank you @destro @Skydiver and @JohnH
 
Back
Top Bottom