ASP.NET MVC - Temukan Absolute Path ke folder App_Data dari Controller

283

Apa cara yang benar untuk menemukan jalur absolut ke folder App_Data dari Pengendali dalam proyek ASP.NET MVC? Saya ingin dapat bekerja sementara dengan file .xml dan saya tidak ingin hardcode path.

Ini tidak bekerja:

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

        //.... do whatever 

        return View();
    }

}

Saya pikir di luar konteks web VirtualPathUtility.ToAbsolute () tidak berfungsi. string path kembali sebagai "C: \ App_Data \ somedata.xml"

Di mana saya harus menentukan jalur file .xml di aplikasi MVC? global.asax dan tempelkan variabel level aplikasi?

BuddyJoe
sumber
Saya kira dalam Separation of Concerns & Testability sense - VirtualPathUtility.ToAbsolute () seharusnya tidak berfungsi. Tapi lalu apa cara yang benar untuk melakukan ini?
BuddyJoe

Jawaban:

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");


Referensi MSDN:

Metode HttpServerUtility.MapPath

eu-ge-ne
sumber
6
@Cleiton Kecuali bahwa Url.Content memberikan URL, bukan jalur server.
Andrew Dunkman
8
untuk mvc4 hanya Server.MapPath ()
SeriousM
6
Cara MVC4 tidak berhasil, saya harus menggunakan Currentatau Server.MapPath(...)seperti yang disebutkan SeriousM.
gligoran
27
GunakanSystem.Web.Hosting.HostingEnvironment.MapPath()
Vince Panuccio
1
Panggilan ke HttpContext.Current tidak berfungsi dalam beberapa situasi di mana tidak ada HttpContext (application_start dll)
mcintyre321
274
string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();

Ini mungkin cara yang lebih "benar" untuk mendapatkannya.

Alex
sumber
25
Karena itu bukan hardcoding string "App_Data". Itu bisa berubah di versi mendatang, atau berbeda di Mono dll.
Alex
19
Yang menyenangkan tentang jawaban ini adalah bahwa saya dapat menggunakannya dalam proyek Model saya tanpa merujuk system.web, sehingga membantu menjaga pemisahan yang bersih. Yang bagus!
Frans
10
Posting blog yang merujuk Pete juga berbicara tentang mengapa menggunakan ini mungkin bukan ide bagus.
Andy
13
Tidak didokumentasikan dalam MSDN , oleh karena itu tidak boleh digunakan.
Alexander Abramov
10
Hard-coding string lain bukannya "App_Data" bukan cara yang "benar". Selain itu, tidak ada lagi domain aplikasi di .NET Core.
UserControl
139

Saya mencoba untuk membiasakan menggunakan HostingEnvironmentdaripada Serverberfungsi dalam konteks layanan WCF juga.

 HostingEnvironment.MapPath(@"~/App_Data/PriceModels.xml");
Simon_Weaver
sumber
6
Server.MapPath () akhirnya memanggil HostingEnvironment.MapPath (), lihat stackoverflow.com/questions/944219/…
Todd
3
Ini adalah favorit saya karena saya dapat menggunakannya di luar pengontrol saya. Ini ada dalam System.Web.Hostingnamespace kalau-kalau ada yang perlu tahu yang relevan using. Ref: docs.microsoft.com/en-us/dotnet/api/…
MDMower
7

Cara yang paling benar adalah menggunakan HttpContext.Current.Server.MapPath("~/App_Data");. Ini berarti Anda hanya dapat mengambil jalur dari metode di mana HttpContexttersedia. Masuk akal: direktori App_Data adalah struktur folder proyek web [1].

Jika Anda memerlukan path ke ~ / App_Data dari kelas di mana Anda tidak memiliki akses ke, HttpContextAnda selalu dapat menyuntikkan antarmuka penyedia menggunakan wadah IoC Anda:

public interface IAppDataPathProvider
{
    string GetAppDataPath();
}

Terapkan dengan menggunakan HttpApplication:

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

Di mana MyHttpApplication.GetAppDataPathterlihat seperti:

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

Daniel Lidström
sumber
Bagaimana mungkin statis tidakHttpContext.Current pernah tersedia di satu tempat jika Anda menggunakannya - melalui wadah IOC - di tempat lain? Di mana properti statis tidak tersedia?
M. Mimpen
Ini hanya akan tersedia di proyek web. Apakah ini menjawab pertanyaan Anda? Saya tidak yakin saya mengerti sepenuhnya. Hari ini saya pikir saya mungkin telah memecahkan masalah ini (memang sederhana) sedikit berbeda. Saya mungkin akan menggunakan antarmuka penyedia yang sama tetapi mengaturnya di Application_Start dengan jalur root aplikasi.
Daniel Lidström
Tidak, HttpContext.Current tidak hanya tersedia di proyek web ... Jika Anda mereferensikan proyek yang memiliki GetAppDataPath (), itu akan selalu perlu merujuk HttpContext.Current juga. Yaitu jika Anda menggunakan perpustakaan A yang menggunakan perpustakaan B, aplikasi Anda akan memerlukan referensi ke perpustakaan A dan B.
M. Mimpen
Terkadang nyaman untuk tidak mengakses HttpContext secara langsung, alih-alih melalui tingkat tipuan. Pikirkan tes unit misalnya. Testabilitas biasanya mengapa saya melakukan hal-hal dengan cara ini. Tapi saya pikir Anda salah tentang pernyataan Anda. Hanya antarmuka yang perlu dibagikan di antara majelis. Itulah alasan Anda dapat mengejeknya untuk tes, yaitu Anda tidak perlu HttpContext. Saat ini untuk tes. Maaf jika saya membingungkan hal-hal untuk Anda ...
Daniel Lidström
6

Phil Haak memiliki contoh yang saya pikir sedikit lebih stabil ketika berhadapan dengan jalur dengan pemisah direktori gaya "\" gila. Itu juga aman menangani rangkaian jalan. Itu datang secara gratis di System.IO

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

Namun, Anda juga bisa mencoba "AppDomain.CurrentDomain.BaseDirector" alih-alih "Server.MapPath".

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

ATAU

string filePath = HttpContext.Server.MapPath("~/folderName/filename.extension");
Dipak Delvadiya
sumber
1
Meskipun kode ini dapat membantu menyelesaikan masalah, memberikan konteks tambahan tentang mengapa dan / atau bagaimana ia menjawab pertanyaan akan secara signifikan meningkatkan nilai jangka panjangnya. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan.
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);

ini adalah Solusi terbaik untuk mendapatkan jalan yang sebenarnya dibutuhkan untuk saat ini

Shahbaz Pirzada
sumber