Reputation: 1012
I need to read a json file from a class in Asp.net Core 1.1. The file is in the "wwwroot" of my mvc project. I know I can take a dependency injection of IHostingEnvironment in controller, pass it down to my class, and access to WebRootPath, but I want to be able to instantiate my class outside a controller, e.g., inside another class. How can I read a file which is in wwwroot folder inside my class? Destination folder example:
wwwroot/keywords/keywords.json.
If I try to inject IHostingEnvironment in constructor of my class, I will need to pass a HostingEnvironment instance when I instantiate my class.
public class AppTweet
{
private readonly IHostingEnvironment _hostingEnvironment;
public AppTweet(ITweet tweet, ICollection<string> keyWords, IHostingEnvironment hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
}
}
I call my class in a controller that passes down the hostingEnvironment
, but I want to decouple this behaviour, because I need to instantiate this class outside a controller. E.g.:
public class Article()
{
public Article()
{
var appTweet = new AppTweet(new Tweet(), new List<string>, new HostingEnvironment());
}
}
If I do this way, HostingEnvironment.WebRootPath is null
EDIT
Maybe I don't need Dependency Injection. I just want to read a file inside the wwwroot folder, but I don't know how to access this path both in development and in server When I try
`var file = System.IO.File.ReadAllText(@"..\wwwroot\keywords\keywords.json")`;
the file var does not read the project folder in my development machine. The path I want to read form is something like E:\SOLUTION_FOLDER\PROJECT_FOLDER\wwwroot\keywords, but it reads from E:\SOLUTION_FOLDER\wwwroot\keywords, and does not include the project folder.
EDIT 2
I think DI is not suitable in this case. This is a personal project of my own. What I'm trying to do is populate some properties in this class. E.g.: summary of my class:
public class AppTweet
{
public AppTweet (ITweet tweet, ICollection<string> keyWords)
{
//Read a json file from wwwroot and populate NotDesiredKeyWords property
}
[NotMapped]
public IEnumerable<string> NotDesiredKeyWords { get; set; }
}
This class AppTweet
must have access to this json file, that is like a configuration file, because it will always have to read these values. I know I can hard-code the values in the class (it will be faster), but I prefer to do it in a json file, so I don't have to compile the project if I add some value.
From what I could read here , Dependency Injection takes care of instantiate your class, and you can't have params in your constructor with no default values.
I need (not need but it's the more reasonable way to me) instantiate this class myself. And maybe instantiate this class inside another class, outside the controller. So, the only thing I want is to have access to the web root folder wwwroot
(or some other folder) where I can put this json file, and it must work both in my machine and in the server. Which path
I can pass to System.IO.File.ReadAllText(path)
in order to read this file?
Upvotes: 1
Views: 2208
Reputation: 49779
ASP.NET Core provides File Provider for such cases. In your scenario you need the instance of PhysicalFileProvider
class (it is used to access the actual or physical file of the system). It could be created directly as
IFileProvider provider = new PhysicalFileProvider("root path");
or as your need to access files in wwwroot
, the IHostingEnvironment.WebRootFileProvider
extension property may be used:
//
// Summary:
// /// Gets or sets an Microsoft.Extensions.FileProviders.IFileProvider pointing
// at Microsoft.AspNetCore.Hosting.IHostingEnvironment.WebRootPath. ///
IFileProvider WebRootFileProvider { get; set; }
The possible way how to read your file:
// using System.IO;
// using Microsoft.AspNetCore.Hosting;
// IHostingEnvironment env
...
var fileProvider = env.WebRootFileProvider;
// here you define only subpath
var fileInfo = fileProvider.GetFileInfo("keywords\keywords.json");
var fileStream = fileInfo.CreateReadStream();
using (var reader = new StreamReader(fileStream))
{
string data = reader.ReadToEnd();
}
Also, note that you need to add Microsoft.Extensions.FileProviders.Physical
package as a dependency.
If you want to create instances manually, then you need to pass dependency in cascading way... (and the instance of YourService
should be created in the same manner or passed into another class as the dependency via constructor using DI...)
public class YourService
{
private IHostingEnvironment _env;
public YourService(IHostingEnvironment env)
{
_env = env;
}
public Article CreateArticle()
{
return new Article(_env);
}
}
public class AppTweet
{
public AppTweet(ITweet tweet, ICollection<string> keyWords, IHostingEnvironment hostingEnvironment)
{
// read file here for example
}
}
public class Article()
{
public Article(IHostingEnvironment hostingEnvironment)
{
var appTweet = new AppTweet(new Tweet(), new List<string>, hostingEnvironment);
}
}
Upvotes: 1