ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

我想从关注点和可测试性的角度来看 - VirtualPathUtility.ToAbsolute() 不应该工作。但是,这样做的正确方法是什么?

L
Loudenvier

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

HttpServerUtility.MapPath Method


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

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


因为它不是硬编码“App_Data”字符串。这可能会在未来的版本中改变,或者在 Mono 等中有所不同。
这个答案的好处是我可以在我的模型项目中使用它而无需引用 system.web,从而有助于保持干净的分离。好东西!
Pete 提到的博客文章还谈到了为什么使用它可能不是一个好主意。
MSDN 中未记录,因此不应使用。
硬编码另一个字符串而不是“App_Data”不是“正确”的方式。此外,.NET Core 中不再有应用程序域。
S
Simon_Weaver

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

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

Server.MapPath() 最终调用 HostingEnvironment.MapPath(),参见 stackoverflow.com/questions/944219/…
这是我最喜欢的,因为我可以在我的控制器之外使用它。这是在 System.Web.Hosting 命名空间中,以防任何人需要知道相关的 using。参考:docs.microsoft.com/en-us/dotnet/api/…
D
Daniel Lidström

最正确的方法是使用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


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

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


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

或者

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

尽管此代码可能有助于解决问题,但提供有关它为什么和/或如何回答问题的额外上下文将显着提高其长期价值。请编辑您的答案以添加一些解释。
佚名

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

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


S
Shahbaz Pirzada
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);

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