ASP.NET MVC: trova il percorso assoluto della cartella App_Data dal controller


283

Qual è il modo corretto per trovare il percorso assoluto della cartella App_Data da un controller in un progetto ASP.NET MVC? Mi piacerebbe poter lavorare temporaneamente con un file .xml e non voglio codificare il percorso.

Questo non funziona:

[HandleError]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        string path = VirtualPathUtility.ToAbsolute("~/App_Data/somedata.xml");

        //.... do whatever 

        return View();
    }

}

Penso che al di fuori del contesto Web VirtualPathUtility.ToAbsolute () non funzioni. il percorso della stringa torna come "C: \ App_Data \ somedata.xml"

Dove devo determinare il percorso del file .xml in un'app MVC? global.asax e incollare una variabile a livello di applicazione?


Immagino in un senso di Separazione delle preoccupazioni e della testabilità: VirtualPathUtility.ToAbsolute () non dovrebbe funzionare. Ma allora qual è il modo giusto per farlo?
BuddyJoe,

Risposte:


400

ASP.NET MVC1 -> MVC3

string path = HttpContext.Current.Server.MapPath("~/App_Data/somedata.xml");

ASP.NET MVC4

string path = Server.MapPath("~/App_Data/somedata.xml");


Riferimento MSDN:

Metodo HttpServerUtility.MapPath


6
@Cleiton Tranne che Url.Content fornisce un URL, non un percorso del server.
Andrew Dunkman,

8
per mvc4 è solo Server.MapPath ()
SeriousM

6
Il modo MVC4 non ha funzionato, o ho dovuto usare Currento Server.MapPath(...)come menzionato SeriousM.
Gligoran,

27
UsaSystem.Web.Hosting.HostingEnvironment.MapPath()
Vince Panuccio il

1
Chiamate a HttpContext. La corrente non funziona in alcune situazioni in cui non esiste un HttpContext (application_start ecc.)
mcintyre321,

274
string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();

Questo è probabilmente un modo più "corretto" di ottenerlo.


25
Perché non è hardcoding la stringa "App_Data". Ciò può cambiare nelle versioni future o essere diverso in Mono, ecc. Ecc.
Alex,

19
La cosa bella di questa risposta è che posso usarla nel mio progetto Model senza fare riferimento a system.web, contribuendo così a mantenere una separazione netta. Ben fatto!
Frans,

10
Il post sul blog a cui Pete fa riferimento parla anche del perché l'utilizzo di questo potrebbe non essere una grande idea.
Andy,

13
Non documentato in MSDN , pertanto non deve essere utilizzato.
Alexander Abramov,

10
La codifica hard di un'altra stringa anziché "App_Data" non è un modo "corretto". Inoltre, non ci sono più domini di app in .NET Core.
UserControl

139

Cerco di prendere l'abitudine di usare HostingEnvironmentinvece di Servercome funziona anche nel contesto dei servizi WCF.

 HostingEnvironment.MapPath(@"~/App_Data/PriceModels.xml");

6
Server.MapPath () alla fine chiama HostingEnvironment.MapPath (), vedi stackoverflow.com/questions/944219/…
Todd

3
Questo è il mio preferito poiché posso usarlo al di fuori dei miei controller. Questo è nello System.Web.Hostingspazio dei nomi nel caso in cui qualcuno debba conoscere il relativo using. Rif: docs.microsoft.com/en-us/dotnet/api/…
MDMower

7

Il modo più corretto è usare HttpContext.Current.Server.MapPath("~/App_Data");. Ciò significa che è possibile recuperare il percorso solo da un metodo in cui HttpContextè disponibile. Ha senso: la directory App_Data è una struttura di cartelle del progetto Web [1].

Se hai bisogno del percorso di ~ / App_Data da una classe a cui non hai accesso HttpContextpuoi sempre iniettare un'interfaccia del provider usando il tuo contenitore IoC:

public interface IAppDataPathProvider
{
    string GetAppDataPath();
}

Implementalo usando il tuo HttpApplication:

public class AppDataPathProvider : IAppDataPathProvider
{
    public string GetAppDataPath()
    {
        return MyHttpApplication.GetAppDataPath();
    }
}

Dove MyHttpApplication.GetAppDataPathappare:

public class MyHttpApplication : HttpApplication
{
    // of course you can fetch&store the value at Application_Start
    public static string GetAppDataPath()
    {
        return HttpContext.Current.Server.MapPath("~/App_Data");
    }
}

[1] http://msdn.microsoft.com/en-us/library/ex526337%28v=vs.100%29.aspx


In che modo statico non potrebbe HttpContext.Currentmai essere disponibile in un posto se lo si utilizza, tramite un contenitore IoC, in un altro posto? Dove la proprietà statica non sarebbe disponibile?
M. Mimpen,

Sarà disponibile solo nel progetto Web. Questo risponde alla tua domanda? Non sono sicuro di aver capito appieno. Oggi penso che avrei potuto risolvere questo problema (certamente semplice) un po 'diverso. Probabilmente avrei usato la stessa interfaccia del provider ma l'ho impostato in Application_Start con il percorso radice dell'applicazione.
Daniel Lidström,

No, HttpContext.Current non è disponibile solo nel progetto Web ... Se fai riferimento a un progetto che ha GetAppDataPath (), dovrà sempre fare riferimento anche a HttpContext.Current. Vale a dire se si utilizza la libreria A che utilizza la libreria B, l'applicazione avrà bisogno di riferimenti alle librerie A e B.
M. Mimpen

A volte è conveniente non accedere direttamente a HttpContext, passando invece attraverso un livello di riferimento indiretto. Pensa ad esempio ai test unitari. La testabilità di solito è il motivo per cui faccio le cose in questo modo. Ma penso che tu sia inesatto riguardo alla tua affermazione. Solo l'interfaccia deve essere condivisa tra gli assiemi. Questo è il motivo per cui puoi deriderlo per i test, cioè non hai bisogno di HttpContext.Current per i test. Scusa se ti sto confondendo le cose ...
Daniel Lidström,

6

Phil Haak ha un esempio che penso sia un po 'più stabile quando si tratta di percorsi con pazzi separatori di directory in stile "\". Gestisce in modo sicuro la concatenazione del percorso. Viene fornito gratuitamente in System.IO

var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);

Tuttavia, è possibile provare anche "AppDomain.CurrentDomain.BaseDirector" anziché "Server.MapPath".


4
string filePath = HttpContext.Current.Server.MapPath("~/folderName/filename.extension");

O

string filePath = HttpContext.Server.MapPath("~/folderName/filename.extension");

1
Sebbene questo codice possa aiutare a risolvere il problema, fornire un contesto aggiuntivo per quanto riguarda il perché e / o il modo in cui risponde alla domanda migliorerebbe significativamente il suo valore a lungo termine. Modifica la tua risposta per aggiungere alcune spiegazioni.
oɔɯǝɹ

1
string Index = i;
            string FileName = "Mutton" + Index + ".xml";
            XmlDocument xmlDoc = new XmlDocument();

            var path = Path.Combine(Server.MapPath("~/Content/FilesXML"), FileName);
            xmlDoc.Load(path); // Can use xmlDoc.LoadXml(YourString);

questa è la soluzione migliore per ottenere il percorso che è esattamente necessario per ora

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.