ASP.NET MVC - ค้นหาพา ธ ที่สมบูรณ์ไปยังโฟลเดอร์ App_Data จากคอนโทรลเลอร์


283

วิธีที่ถูกต้องในการค้นหาเส้นทางที่แน่นอนไปยังโฟลเดอร์ App_Data จากคอนโทรลเลอร์ในโครงการ ASP.NET MVC คืออะไร ฉันต้องการทำงานกับไฟล์. xml ชั่วคราวและฉันไม่ต้องการฮาร์ดโค้ดพา ธ

สิ่งนี้ไม่ทำงาน:

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

        //.... do whatever 

        return View();
    }

}

ฉันคิดว่านอกบริบทเว็บ VirtualPathUtility.ToAbsolute () ไม่ทำงาน เส้นทางสตริงกลับมาเป็น "C: \ App_Data \ somedata.xml"

ฉันควรกำหนดเส้นทางของไฟล์. xml ในแอป MVC ได้อย่างไร global.asax และติดมันเป็นตัวแปรระดับแอปพลิเคชัน?


ฉันเดาจากความกังวลและความรู้สึกทดสอบได้ - VirtualPathUtility.ToAbsolute () ไม่ควรทำงาน แต่แล้ววิธีที่ถูกต้องในการทำเช่นนี้คืออะไร?
BuddyJoe

คำตอบ:


399

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


ข้อมูลอ้างอิง MSDN:

วิธี HttpServerUtility.MapPath


6
@Cleiton ยกเว้นว่า Url.Content จะให้ URL ไม่ใช่เส้นทางของเซิร์ฟเวอร์
Andrew Dunkman

8
สำหรับ mvc4 เป็นเพียง Server.MapPath ()
SeriousM

6
วิธี MVC4 ใช้งานไม่ได้ฉันต้องใช้CurrentหรือServer.MapPath(...)ตามที่ระบุไว้ใน SeriousM
gligoran

27
ใช้System.Web.Hosting.HostingEnvironment.MapPath()
วินซ์ Panuccio

1
โทรไปที่ HttpContext.Current ไม่ทำงานในบางสถานการณ์ที่ไม่มี HttpContext (application_start ฯลฯ )
mcintyre321

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

นี่อาจเป็นวิธีที่ "ถูกต้อง" มากกว่าในการรับมัน


25
เพราะมันไม่ได้เข้ารหัสรหัส "App_Data" ที่สามารถเปลี่ยนแปลงได้ในรุ่นในอนาคตหรือจะแตกต่างกันใน Mono และอื่น ๆ
อเล็กซ์

19
สิ่งที่ดีเกี่ยวกับคำตอบนี้คือฉันสามารถใช้มันในโครงการ Model โดยไม่มีการอ้างอิง system.web ดังนั้นช่วยให้แยกจากกันอย่างสะอาด ทำได้ดีนี่!
ฟรานส์

10
โพสต์บล็อก Pete หมายถึงพูดถึงว่าทำไมการใช้สิ่งนี้อาจไม่ใช่ความคิดที่ดี
Andy

13
ไม่ได้บันทึกไว้ในMSDNดังนั้นจึงไม่ควรใช้
Alexander Abramov

10
การเข้ารหัสฮาร์ดสตริงอื่นแทน "App_Data" ไม่ใช่วิธีที่ "ถูกต้อง" นอกจากนี้ยังไม่มีโดเมนแอปใน. NET Core อีก
UserControl

139

ฉันพยายามใช้ให้เป็นนิสัยHostingEnvironmentแทนการใช้Serverงานตามบริบทของบริการ WCF เช่นกัน

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

6
Server.MapPath () ในที่สุดเรียก HostingEnvironment.MapPath () ดูstackoverflow.com/questions/944219/…
Todd

3
นี่คือสิ่งที่ฉันชอบเนื่องจากฉันสามารถใช้มันนอกตัวควบคุมของฉัน นี้อยู่ในSystem.Web.Hostingnamespace usingในกรณีที่ทุกคนต้องการที่จะรู้ที่เกี่ยวข้อง Ref: docs.microsoft.com/en-us/dotnet/api/…
MDMower

7

HttpContext.Current.Server.MapPath("~/App_Data");วิธีที่ถูกต้องที่สุดคือการใช้งาน ซึ่งหมายความว่าคุณสามารถดึงข้อมูลเส้นทางจากวิธีการที่HttpContextมีอยู่ เหมาะสมแล้ว: ไดเรกทอรี App_Data เป็นโครงสร้างโฟลเดอร์โครงการเว็บ [1]

หากคุณต้องการเส้นทางไปที่ ~ / App_Data จากคลาสที่คุณไม่มีสิทธิ์เข้าถึงHttpContextคุณสามารถฉีดส่วนต่อประสานผู้ให้บริการโดยใช้คอนเทนเนอร์ IoC ของคุณ:

public interface IAppDataPathProvider
{
    string GetAppDataPath();
}

ติดตั้งโดยใช้HttpApplication:

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

ไหนMyHttpApplication.GetAppDataPathดูเหมือนว่า:

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


คงไม่HttpContext.Currentเคยมีวิธีคงที่ในสถานที่หนึ่งถ้าคุณใช้มัน - ผ่านภาชนะ IoC - ในสถานที่อื่น? คุณสมบัติคงที่จะไม่สามารถใช้ได้ที่ไหน
M. Mimpen

มันจะใช้ได้เฉพาะในโครงการเว็บ นี่ตอบคำถามของคุณหรือไม่? ฉันไม่แน่ใจว่าฉันเข้าใจอย่างถ่องแท้ วันนี้ฉันคิดว่าฉันอาจจะแก้ปัญหานี้ได้ (เป็นที่ยอมรับง่าย) แตกต่างกันเล็กน้อย ฉันอาจจะใช้อินเทอร์เฟซผู้ให้บริการเดียวกัน แต่ตั้งค่าใน Application_Start ด้วยแอปพลิเคชันรูทพา ธ
Daniel Lidström

ไม่ HttpContext.Current ไม่สามารถใช้ได้เฉพาะในโครงการเว็บ ... หากคุณอ้างอิงโครงการที่มี GetAppDataPath () ก็จะต้องอ้างอิง HttpContext.Current เช่นกันเสมอ คือถ้าคุณใช้
ไลบรารี่ A ที่ใช้ไลบรารี่

บางครั้งจะสะดวกในการไม่เข้าถึง HttpContext โดยตรงแทนที่จะผ่านระดับการเปลี่ยนทิศทาง คิดว่าการทดสอบหน่วยเป็นตัวอย่าง ความสามารถในการทดสอบมักเป็นสาเหตุที่ฉันทำสิ่งนี้ แต่ฉันคิดว่าคุณไม่ถูกต้องเกี่ยวกับคำสั่งของคุณ เฉพาะอินเตอร์เฟสที่ต้องใช้ร่วมกันระหว่างชุดประกอบ นั่นคือเหตุผลที่คุณสามารถเยาะเย้ยมันสำหรับการทดสอบนั่นคือคุณไม่จำเป็นต้อง HttpContext.Current สำหรับการทดสอบ ขออภัยถ้าฉันสับสนในสิ่งที่คุณ ...
Daniel Lidström

6

Phil Haak มีตัวอย่างที่ฉันคิดว่าค่อนข้างเสถียรกว่าเมื่อจัดการกับเส้นทางที่มีตัวคั่นไดเรกทอรีสไตล์ "\" บ้า นอกจากนี้ยังจัดการการเรียงต่อเส้นทางได้อย่างปลอดภัย มันมาฟรีใน System.IO

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

อย่างไรก็ตามคุณสามารถลอง "AppDomain.CurrentDomain.BaseDirector" แทน "Server.MapPath"


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

หรือ

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

1
แม้ว่ารหัสนี้อาจช่วยแก้ปัญหาได้ แต่การให้บริบทเพิ่มเติมเกี่ยวกับสาเหตุและ / หรือวิธีการตอบคำถามจะช่วยปรับปรุงมูลค่าระยะยาวอย่างมีนัยสำคัญ โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบาย
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);

นี่คือทางออกที่ดีที่สุดเพื่อให้ได้เส้นทางที่ต้องการในตอนนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.