ASP.NET MVC-컨트롤러에서 App_Data 폴더의 절대 경로 찾기


283

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 ()가 작동하지 않아야한다고 생각합니다. 그러나 이것을하는 올바른 방법은 무엇입니까?
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()
빈스 파누치

1
HttpContext (application_start 등)가없는 일부 상황에서는 HttpContext.Current 호출이 작동하지 않습니다.
mcintyre321

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

이것은 아마도 "올바른"방법입니다.


25
"App_Data"문자열을 하드 코딩하지 않기 때문입니다. 향후 버전에서 변경되거나 Mono 등에서 다를 수 있습니다.
Alex

19
이 답변의 좋은 점은 system.web 참조 하지 않고 모델 프로젝트에서 사용할 수 있으므로 깨끗하게 분리하는 데 도움이된다는 것입니다. 좋은 것!
Frans

10
블로그 게시물 Pete는 왜 이것을 사용하는 것이 좋은 아이디어가 아닌지에 대한 이야기를 말합니다.
Andy

13
MSDN에 문서화되어 있지 않으므로 사용해서는 안됩니다.
Alexander Abramov

10
"App_Data"대신 다른 문자열을 하드 코딩하는 것은 "올바른"방법이 아닙니다. 또한 .NET Core에는 더 이상 앱 도메인이 없습니다.
UserControl

139

WCF 서비스의 맥락에서도 작동하기 때문에 HostingEnvironment대신 사용 습관을 얻으려고합니다 Server.

 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 디렉토리는 웹 프로젝트 폴더 구조입니다 [1].

액세스 할 수없는 클래스에서 ~ / App_Data에 대한 경로가 필요한 경우 HttpContextIoC 컨테이너를 사용하여 항상 공급자 인터페이스를 주입 할 수 있습니다.

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도 참조해야합니다. 즉, 라이브러리 B를 사용하는 라이브러리 A를 사용하는 경우 응용 프로그램은 라이브러리 A B에 대한 참조가 필요합니다 .
M. Mimpen

때로는 간접적 인 수준을 거치는 대신 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);

그러나 "Server.MapPath"대신 "AppDomain.CurrentDomain.BaseDirector"를 시도 할 수도 있습니다.


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.