Kenci
Kenci

Reputation: 4882

Where to place files when File.Exists is executed in a class library but called from a MVC project?

I have a solution which has two presentation layers. One is using ASP.NET MVC, the other WinForms. Both projects depend on a third projecs which does some business logic and is a class library. The third project has the following method which works fine in WinForms, but doesnt work in MVC:

    public static string[] Dictionary()
    {
        if (_dictionary == null)
        {
            if (File.Exists("dict.txt"))
                _dictionary = File.ReadAllLines("dict.txt");
        }

        return _dictionary;
    }

So when I am using the WinForms GUI the file is found, but when I am using the MVC website, the project can't find it.

When building the solution dict.txt is placed in bin/debug of the WinForms project.

It is placed in /bin in the MVC project.

Where should I place the file in the MVC proejct?

Upvotes: 0

Views: 326

Answers (3)

justin.lovell
justin.lovell

Reputation: 675

So when I am using the WinForms GUI the file is found, but when I am using the MVC website, the project can't find it.

To answer the reason why you are observing the difference is called the current working directory. By default, when VS.NET launches Windows apps or consoles, the working directory is to the relevant bin directory.

All relative file operations, such as File.ReadAllLines("the.file"), will concatenate to an absolute file path as per below.

Path.Combine(Directory.GetCurrentDirectory(), "the.file");

ASP.NET's working directory would not correlate to the root of your web application.

Where should I place the file in the MVC proejct?

As suggested by @dariogriffo, it should be placed in the ~/App_Data/* directory.

I have a solution which has two presentation layers. One is using ASP.NET MVC, the other WinForms. Both projects depend on a third projecs which does some business logic and is a class library.

So now you are in a little bit of a pickle over here with your current implementation and the way the current working directory is implemented. Without delving into too much detail, I suggest that the code figures out how to load the file indirectly such as passing in an interface with a contract such as the following.

public interface IDictionaryRepository {
    IEnumerable<string> LoadAllWords();
}

With the above, you can change your business logic to the following

public static string[] Dictionary()
{
    if (_dictionary == null)
    {
        _dictionary = _dictionaryRepository.LoadAllWords().ToArray();
    }

    return _dictionary;
}

The benefit of the above abstraction is that you may then easily substitute the file finding logic as per the other suggestions easily, and maybe migrate your dictionary to be hosted in a database somewhere.

Upvotes: 1

WholeLifeLearner
WholeLifeLearner

Reputation: 455

server applications can have 2 paths - virtual and logical. You can reference to one or another using MapPath() method.

Server.MapPath("."), Server.MapPath("~"), Server.MapPath(@"\"), Server.MapPath("/"). What is the difference?

I thinki you need to provide full path to this file in MVC, check this out:

Server.MapPath("~\\bin\\dict.txt")

Upvotes: 0

Dario Griffo
Dario Griffo

Reputation: 4274

You can place them in the App_Data Forlder, and then reference them like this

 var fileName = Path.Combine(System.Web.HttpContext.Current.Server.MapPath(@"~/App_Data"),"dict.txt");

Upvotes: 2

Related Questions