【问题标题】:ASP.NET MVC - Find Absolute Path to the App_Data folder from ControllerASP.NET MVC - 从控制器中查找 App_Data 文件夹的绝对路径
【发布时间】:2010-11-19 02:49:32
【问题描述】:

从 ASP.NET MVC 项目的控制器中找到 App_Data 文件夹的绝对路径的正确方法是什么?我希望能够临时使用 .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() 不应该工作。但是,这样做的正确方法是什么?

标签: .net asp.net-mvc absolute-path


【解决方案1】:

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 Method

【讨论】:

  • @Cleiton 除了 Url.Content 提供的是 URL,而不是服务器路径。
  • 对于 mvc4 它只有 Server.MapPath()
  • MVC4 方式不起作用,我不得不使用CurrentServer.MapPath(...),正如 SeriousM 提到的那样。
  • 使用System.Web.Hosting.HostingEnvironment.MapPath()
  • 对 HttpContext.Current 的调用在某些没有 HttpContext(application_start 等)的情况下不起作用
【解决方案2】:
string path = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();

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

【讨论】:

  • 因为它没有硬编码“App_Data”字符串。这可能会在未来的版本中发生变化,或者在 Mono 等中有所不同。
  • 这个答案的好处是我可以在我的模型项目中使用它而不引用system.web,从而有助于保持干净的分离。不错!
  • Pete 引用的博文还谈到了为什么使用它可能不是一个好主意。
  • MSDN 中未记录,因此不应使用。
  • 硬编码另一个字符串而不是“App_Data”不是“正确”的方式。此外,.NET Core 中没有更多的应用程序域。
【解决方案3】:

我尝试养成使用 HostingEnvironment 而不是 Server 的习惯,因为它也适用于 WCF 服务的上下文。

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

【讨论】:

【解决方案4】:

最正确的方法是使用HttpContext.Current.Server.MapPath("~/App_Data");。这意味着您只能从HttpContext 可用的方法中检索路径。有道理:App_Data 目录是一个 Web 项目文件夹结构 [1]。

如果您需要从无权访问 HttpContext 的类到 ~/App_Data 的路径,您始终可以使用您的 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 容器 - 在另一个地方?静态属性在哪里不可用?
  • 它只在 web 项目中可用。这回答了你的问题了吗?我不确定我是否完全理解。今天我想我可能已经解决了这个(诚然简单的)问题有点不同。我可能会使用相同的提供程序接口,但在 Application_Start 中使用应用程序根路径进行设置。
  • 不,HttpContext.Current 不仅在 Web 项目中可用...如果您引用具有 GetAppDataPath() 的项目,它也总是需要引用 HttpContext.Current。 IE。如果您使用使用库 B 的库 A,您的应用程序将需要对库 A B的引用。
  • 有时不直接访问 HttpContext 会很方便,而是通过一个间接级别。以单元测试为例。可测试性通常是我以这种方式做事的原因。但我认为你的说法是不正确的。只有接口需要在程序集之间共享。这就是您可以模拟它进行测试的原因,即您不需要 HttpContext.Current 进行测试。对不起,如果我让你感到困惑......
【解决方案5】:

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”。

【讨论】:

    【解决方案6】:
    string filePath = HttpContext.Current.Server.MapPath("~/folderName/filename.extension");
    

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

    【讨论】:

    • 虽然此代码可能有助于解决问题,但提供有关它为什么和/或如何回答问题的额外上下文将显着提高其长期价值。请编辑您的答案以添加一些解释。
    【解决方案7】:
    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);
    

    这是获得现在真正需要的路径的最佳解决方案

    【讨论】:

      【解决方案8】:

      这样我就得到了托管路径。

      using Microsoft.AspNetCore.Hosting;
      using Microsoft.AspNetCore.Mvc;
      
      namespace IHostingEnvironmentExample.Controllers
      {
          public class HomeController : Controller
          {
              private IHostingEnvironment _env;
              public HomeController(IHostingEnvironment env)
              {
                  _env = env;
              }
              public IActionResult Index()
              {
                  var webRoot = _env.WebRootPath;
                  var file = System.IO.Path.Combine(webRoot, "test.txt");
                  System.IO.File.WriteAllText(file, "Hello World!");
                  return View();
              }
          }
      }
      

      https://forums.asp.net/t/1696005.aspx?How+to+get+Local+Server+path+in+mvc

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多