スレッドまたはタイマーでHttpServerUtility.MapPathメソッドにアクセスする方法


88

System.Timers.TimerはAsp.Netアプリケーションでを使用しており、HttpServerUtility.MapPath経由でのみ利用できるように見えるメソッドを使用する必要がありますHttpContext.Current.Server.MapPath。問題はそれでHttpContext.Currentあるnull時にTimer.Elapsedイベントが発生します。

HttpServerUtilityオブジェクトへの参照を取得する別の方法はありますか?クラスのコンストラクターに挿入できます。安全ですか?現在のリクエストの最後にガベージコレクションされないようにするにはどうすればよいですか?

ありがとう!

回答:


142

HostingEnvironment.MapPath()代わりに使用することが可能ですHttpContext.Current.Server.MapPath()

私はまだスレッドまたはタイマーイベントでそれを試していません。


私が検討したいくつかの(実行不可能な)ソリューション。

  • 私が気にする唯一の方法HttpServerUtilityMapPathです。したがって、代替手段として、これからAppDomain.CurrentDomain.BaseDirectory自分のパスを使用して構築することができました。しかし、アプリが仮想ディレクトリを使用している場合、これは失敗します(Mineはそうです)。

  • 別のアプローチ: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( '〜'、 '。')である必要があります
スラバ

13

HostingEnvironmentは、モックするのが非常に難しいクラスであるため、完全なソリューションではありません(HostingEnvironment.MapPathを使用するコードを単体テストする方法を参照)。

テスト容易性が必要な場合は、https://stackoverflow.com/a/1231962/85196で提案されている独自のパスマッパーインターフェースを作成することをお勧めします。

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

結果は簡単にモック可能で、HostingEnvironmentを内部で使用し、同時にase69の懸念に対処することさえできます。


これにより、参照しているライブラリのSystem.WebまたはSystem.Netへの依存関係を必要とせずに、Web APIプロジェクトのパス解決の実装を提供できました。+1
デビッドピーターソン、

このアプローチのDIとテスト容易
性の評価

2

タイマーを開始する前にMapPath関数を呼び出して、結果をキャッシュすることはできませんか?ティックイベント内でMapPathを呼び出すことは絶対に必要ですか?


2

タイマーが経過すると、現在のHTTPコンテキストはありません。これは、タイマーイベントが特定のHTTPリクエストに関連していないためです。

あなたがすべきことは、HTTPコンテキストが利用可能なHttpServerUtility.MapPathを使用することです。これは、リクエストパイプラインイベント(Page_Loadなど)の1つ、またはApplication_StartなどのGlobal.asaxイベントで実行できます。

MapPathの結果を、Timer.Elapsedイベントからアクセス可能な変数に割り当てます。Path.Combineを使用して、必要な特定のファイルの場所を取得できます。


0

その時点でnullである理由(考えれば)は、タイマーの経過イベントがHTTPリクエストの一部として発生しないため(コンテキストがないため)と思います。サーバー上の何かが原因です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.