49

I have an ASP.NET Core (1.0-rc1-final) MVC solution and I wish to store a simple text file within the project which contain a list of strings which I read into a string array in my controller.

Where should I store this file in my project and how do I read those files in my controllers?

In ASP.net 4.x I'd have used the app_data folder and done something like this

string path = Server.MapPath("~/App_Data/File.txt");
string[] lines = System.IO.File.ReadAllLines(path);

But Server.MapPath does not seem to be valid in ASP.Net Core 1 and I'm not sure that the app_data folder is either.

Maxime Rouiller
  • 13,614
  • 9
  • 57
  • 107
Martin Kearn
  • 2,313
  • 1
  • 21
  • 35

6 Answers6

34

I found a simple solution to this.

Firstly, you can create a folder anywhere in your solution, you do not have to stick to the conventions like 'app_data' from .net 4.x.

In my scenario, I created a folder called 'data' at the root of my project, I put my txt file in there and used this code to read the contents to a string array

var owners = System.IO.File.ReadAllLines(@"..\data\Owners.txt");

Martin Kearn
  • 2,313
  • 1
  • 21
  • 35
  • 2
    This is not working for me in my machine, since it skips project folder. I. e.: it needs to be "D:\SOLUTION_FOLDER\PROJECT_FOLDER\data\Owners.txt" and it tries to read from "D:\SOLUTION_FOLDER\data\Owners.txt" – Porkopek Jul 22 '17 at 10:49
  • 3
    Your best choice is to always use [IHostingEnvironment](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.hosting.ihostingenvironment?view=aspnetcore-2.1) – Black Frog Aug 18 '18 at 17:32
  • 5
    From .NET Core 3.0 IHostingEnvironment is obslolete and should be replaced by IWebHostEnvironment – Mateusz D Nov 04 '19 at 22:49
24

You can get the enviroment with Dependency Injection in your controller:

using Microsoft.AspNetCore.Hosting;
....

public class HomeController: Controller
{
   private IHostingEnvironment _env;

   public HomeController(IHostingEnvironment env)
   {
   _env = env;
   }   
...

Then you can get the wwwroot location in your actions: _env.WebRootPath

var owners =   System.IO.File.ReadAllLines(System.IO.Path.Combine(_env.WebRootPath,"File.txt"));
Pieter van Kampen
  • 1,957
  • 17
  • 21
14

in your controller you could take a dependency on IApplicationEnvironment and have it injected into the constructor then you can use it to establish the path to your file so your file can live in a folder within the project. In the example below "env" is the instance of IApplicationEnvironment

using Microsoft.Extensions.PlatformAbstractions;

var pathToFile = env.ApplicationBasePath 
   + Path.DirectorySeparatorChar.ToString() 
   + "yourfolder"
   + Path.DirectorySeparatorChar.ToString() 
   + "yourfilename.txt";

string fileContent;

using (StreamReader reader = File.OpenText(pathToFile))
{
    fileContent = reader.ReadToEnd();
}

ApplicationBasePath represents the applicationRootFolder

note that there also exists IHostingEnvironment which has the familiar .MapPath method, but it is for things stored below the wwwroot folder. You should only store things below the wwwroot folder that you want to serve with http requests so it is better to keep your list of strings in a different folder.

Joe Audette
  • 35,330
  • 11
  • 106
  • 99
  • Thank you for your response, but I found a simpler method which I've posted and will mark as the answer. Thanks though – Martin Kearn Mar 08 '16 at 09:16
  • 1
    I gave a correct answer, just because it is not the exact syntax you chose in the end is not a great reason to not accept my answer imho. Also your answer if I'm not mistaken will only be correct on windows file system. – Joe Audette Mar 08 '16 at 11:35
  • OK, I see your point that your solution will be cross platform and therefore better - have given you the answer, thanks – Martin Kearn Mar 08 '16 at 14:32
  • 2
    1. It looks like IApplicationEnvironment is now dead. IHostingEnvironment seems to have replaced it. 2. Path.Combine() will make this solution a lot more attractive: `var pathToFile = System.IO.Path.Combine(env.ContentRootPath, "yourfolder", "yourfilename.txt");` – Phil Jan 05 '17 at 03:43
12

This has always worked for me locally and on IIS.

AppDomain.CurrentDomain.BaseDirectory

To access your file, you could simply do the following:

import System.IO
...
var owners = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "File.txt"))
zdub
  • 671
  • 6
  • 10
10

IApplicationEnvironment and IRuntimeEnvironment have been removed as of an announcement on github on 2016/04/26.

I replaced @JoeAudette's code with this

private readonly string pathToFile;

public UsersController(IHostingEnvironment env)
{
    pathToFile = env.ContentRootPath
       + Path.DirectorySeparatorChar.ToString()
       + "Data"
       + Path.DirectorySeparatorChar.ToString()
       + "users.json";
}

Where my .json file is located at src/WebApplication/Data/users.json

I then read/parse this data like so

private async Task<IEnumerable<User>> GetDataSet()
{
    string source = "";

    using (StreamReader SourceReader = File.OpenText(pathToFile))
    {
        source = await SourceReader.ReadToEndAsync();
    }

    return await Task.FromResult(JsonConvert.DeserializeObject<IEnumerable<User>>(source)));
}
seangwright
  • 17,245
  • 6
  • 42
  • 54
6

This method worked for me locally and on Azure environment. It is taken from Joe's answer above

public static string ReadFile(string FileName)
    {
        try
        {
            using (StreamReader reader = File.OpenText(FileName))
            {
                string fileContent = reader.ReadToEnd();
                if (fileContent != null && fileContent != "")
                {
                    return fileContent;
                }
            }
        }
        catch (Exception ex)
        {
            //Log
            throw ex;
        }
        return null;
    }

And this is how invoked that method

string emailContent = ReadFile("./wwwroot/EmailTemplates/UpdateDetails.html");
Crennotech
  • 521
  • 5
  • 8