스레드 또는 타이머에서 HttpServerUtility.MapPath 메서드에 액세스하는 방법은 무엇입니까?


88

System.Timers.Timer내 Asp.Net 응용 프로그램에서를 사용하고 .NET HttpServerUtility.MapPath을 통해서만 사용할 수 있는 방법 을 사용해야합니다 HttpContext.Current.Server.MapPath. 문제는 즉 HttpContext.Currentnull경우 Timer.Elapsed이벤트가 발생합니다.

HttpServerUtility 개체에 대한 참조를 얻는 다른 방법이 있습니까? 내 클래스의 생성자에 삽입 할 수 있습니다. 안전 해요 ? 현재 요청이 끝날 때 가비지 수집이되지 않는지 어떻게 확인할 수 있습니까?

감사!

답변:


142

HostingEnvironment.MapPath()대신 사용할 수 있습니다.HttpContext.Current.Server.MapPath()

그래도 스레드 또는 타이머 이벤트에서 아직 시도하지 않았습니다.


내가 고려한 일부 (실행 불가능한) 솔루션;

  • 내가 신경 쓰는 유일한 방법 HttpServerUtilityMapPath. 그래서 대안 AppDomain.CurrentDomain.BaseDirectory으로 이것에서 내 경로를 사용 하고 만들 수 있습니다 . 그러나 앱이 가상 디렉터리를 사용하는 경우에는 실패합니다 (내가 사용함 ).

  • 또 다른 방법 : 필요한 모든 경로를 Global클래스에 추가합니다 . 에서 이러한 경로를 해결하십시오 Application_Start.


1
그러나 위의 내용은 이후 버전의 IIS에서 작동하지 않습니다. IIS7에서 응용 프로그램 시작은 http 요청 외부에서 호출 될 수 있습니다. 즉, 코드 예제입니다. HostingEnvironment.MapPath ()가 이전처럼 계속 작동 할 것이라고 확신합니다.
Robba

그러나 HostingEnvironment.MapPath ()를 전달하면 오류가 발생하고 폴더 경로를 직접 가져 오기 위해 빈 문자열이 발생합니다 ... HttpContext.Current.Server.MapPath ( ""); -> HostingEnvironment.MapPath ( ""); -> 오류 발생
VSP

14

이것이 가상 디렉터리 문제를 해결할 수 있을지는 모르겠지만 MapPath에 이것을 사용합니다.

public static string MapPath(string path)
{
    if (HttpContext.Current != null)
        return HttpContext.Current.Server.MapPath(path);

    return HttpRuntime.AppDomainAppPath + path.Replace("~", string.Empty).Replace('/', '\\');
}

path.Replace ( "~", string.Empty)는 path.Replace ( '~', '.') 여야합니다.
Slava

13

HostingEnvironment는 모의하기가 매우 어려운 클래스이기 때문에 완벽한 솔루션이 아닙니다 ( HostingEnvironment.MapPath를 사용하는 코드를 단위 테스트하는 방법 참조 ).

테스트 가능성이 필요한 사람들을 위해 더 나은 방법은 https://stackoverflow.com/a/1231962/85196 에서 제안한대로 자신의 경로 매퍼 인터페이스를 만드는 것입니다.

public class ServerPathMapper : IPathMapper { 
 public string MapPath(string relativePath) { 
      return HostingEnvironment.MapPath(relativePath); 
 } 
} 

결과는 쉽게 모의 할 수 있고 내부적으로 HostingEnvironment를 사용 하며 동시에 ase69s의 문제 를 잠재적으로 해결할 수 있습니다.


이를 통해 참조하는 라이브러리의 System.Web 또는 System.Net에 대한 종속성없이 Web API 프로젝트의 경로 확인을위한 구현을 제공 할 수있었습니다. +1
David Peterson

DI 및이 방법의 테스트 용이성을위한 엄지 손가락
Dilhan Jayathilake

2

타이머를 시작하기 전에 MapPath 함수를 호출 할 수없고 단순히 결과를 캐시 할 수 있습니까? 틱 이벤트 내에서 MapPath 호출이 절대적으로 필요합니까?


2

타이머가 경과하면 현재 HTTP 컨텍스트가 없습니다. 이는 타이머 이벤트가 특정 HTTP 요청과 관련이 없기 때문입니다.

해야 할 일은 HTTP 컨텍스트를 사용할 수있는 HttpServerUtility.MapPath를 사용하는 것입니다. 요청 파이프 라인 이벤트 (예 : Page_Load) 또는 Global.asax 이벤트 (예 : Application_Start)에서 수행 할 수 있습니다.

Timer.Elapsed 이벤트에서 액세스 할 수있는 변수에 MapPath 결과를 할당합니다. 여기서 Path.Combine을 사용하여 필요한 특정 파일의 위치를 ​​가져올 수 있습니다.


0

그 당시에 null 인 이유는 (생각하면) 타이머 경과 이벤트가 HTTP 요청의 일부로 발생하지 않기 때문이라고 생각합니다 (따라서 컨텍스트가 없음). 서버의 무언가로 인해 발생합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.