ASP.NET MVC-从控制器查找App_Data文件夹的绝对路径


282

从ASP.NET MVC项目中的Controller查找App_Data文件夹的绝对路径的正确方法是什么?我希望能够临时使用.xml文件,但不想对路径进行硬编码。

这不起作用:

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

        //.... do whatever 

        return View();
    }

}

我认为在Web上下文之外,VirtualPathUtility.ToAbsolute()不起作用。字符串路径返回为“ C:\ App_Data \ somedata.xml”

我应该在哪里确定MVC应用程序中.xml文件的路径?global.asax并将其粘贴到应用程序级变量?


我想从“关注点与可测试性”的分离意义上来说,VirtualPathUtility.ToAbsolute()不起作用。但是,什么是正确的方法呢?
BuddyJoe

Answers:


398

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 2012年

8
对于mvc4,它仅是Server.MapPath()
SeriousM

6
该MVC4方式没有工作,我要么不得不使用CurrentServer.MapPath(...)作为SeriousM提及。
gligoran

26
使用System.Web.Hosting.HostingEnvironment.MapPath()
Vince Panuccio

1
调用HttpContext.Current在没有HttpContext的某些情况下不起作用(application_start等)
mcintyre321 2014年

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

这可能是一种更“正确”的获取方式。


25
因为它不是对“ App_Data”字符串进行硬编码。在将来的版本中可能会更改,或者在Mono等中可能会有所不同
Alex

19
关于这个答案的好处是,我可以在我的Model项目中使用它,而无需引用system.web,从而有助于保持清晰的分隔。好一个!
法兰斯,

10
皮特(Pete)提到的博客文章还讨论了为什么使用此方法可能不是一个好主意。
安迪

13
没有在MSDN中记录,因此不应使用。
Alexander Abramov '04

10
硬编码另一个字符串而不是“ App_Data”不是一种“正确”的方法。此外,.NET Core中没有其他应用程序域。
UserControl 2015年

139

我尝试养成使用HostingEnvironment代替的习惯,Server因为它也在WCF服务的上下文中起作用。

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

6
Server.MapPath()最终调用HostingEnvironment.MapPath(),请参阅stackoverflow.com/questions/944219/…–
托德(Todd)

3
这是我的最爱,因为我可以在控制器之外使用它。这是在System.Web.Hosting名称空间中的,以防任何人需要了解相关的using。参考:docs.microsoft.com/en-us/dotnet/api/…–
MDMower

7

最正确的方法是使用HttpContext.Current.Server.MapPath("~/App_Data");。这意味着您只能从HttpContext可用的方法中检索路径。这很有意义:App_Data目录是一个Web项目文件夹结构[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 2015年

它仅在Web项目中可用。这回答了你的问题了吗?我不确定我是否完全理解。今天,我想我可能已经解决了这个(公认简单)的问题。我可能会使用相同的提供程序接口,但使用应用程序根路径在Application_Start中进行设置。
DanielLidström2015年

不,HttpContext.Current不仅在Web项目中可用...如果您引用一个具有GetAppDataPath()的项目,则它将始终也需要引用HttpContext.Current。也就是说,如果你使用了一个文库B库中,你的应用程序需要库中的引用 B.
M. Mimpen

有时不直接访问HttpContext而是通过间接访问级别是很方便的。以单元测试为例。可测试性通常是我以这种方式做事的原因。但是我认为您的说法不正确。程序集之间仅需要共享接口。这就是您可以模拟它进行测试的原因,即您不需要HttpContext.Current进行测试。抱歉,如果我让您感到困惑...
DanielLidström2015年

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

这是获得当前所需的最佳解决方案

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.