如何在线程或计时器中访问HttpServerUtility.MapPath方法?

时间:2008-09-21 20:04:51

标签: .net asp.net timer httpcontext

我在我的Asp.Net应用程序中使用System.Timers.Timer,我需要使用HttpServerUtility.MapPath方法,该方法似乎只能通过HttpContext.Current.Server.MapPath获得。 问题是当HttpContext.Current事件触发时nullTimer.Elapsed

是否有另一种方法来获取对HttpServerUtility对象的引用? 我可以在我的类'构造函数中注入它。安全吗?如何确保在当前请求结束时不会收集垃圾?

谢谢!

6 个答案:

答案 0 :(得分:140)

可以使用HostingEnvironment.MapPath()代替HttpContext.Current.Server.MapPath()

我还没有在线程或计时器事件中尝试过它。


我考虑过的一些(不可行的)解决方案;

  • HttpServerUtility关注的唯一方法是MapPath。因此,作为替代方案,我可以使用AppDomain.CurrentDomain.BaseDirectory并从中构建我的路径。 但如果您的应用使用虚拟目录(我的确如此),则会失败。

  • 另一种方法: 将我需要的所有路径添加到Global类。在Application_Start

  • 中解析这些路径

答案 1 :(得分: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('/', '\\');
}

答案 2 :(得分:13)

HostingEnvironment不是一个完美的解决方案,因为它是一个非常难以模拟的类(参见How to unit test code that uses HostingEnvironment.MapPath)。

对于那些需要可测试性的人来说,更好的方法可能是按照https://stackoverflow.com/a/1231962/85196的建议创建自己的路径映射器接口,除非将其实现为

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

结果很容易模拟,在内部使用HostingEnvironment,甚至可能同时解决ase69s's concern

答案 3 :(得分:2)

在启动计时器之前,你不能调用MapPath函数,只是缓存结果吗?在tick事件中进行MapPath调用是否绝对必要?

答案 4 :(得分:2)

当计时器过去时,没有当前的HTTP上下文。这是因为计时器事件与特定的HTTP请求无关。

你应该做的是使用HTTP上下文可用的HttpServerUtility.MapPath。您可以在其中一个请求管道事件(例如Page_Load)或Global.asax事件(例如Application_Start)中执行此操作。

将MapPath结果分配给可从Timer.Elapsed事件访问的变量,您可以使用Path.Combine获取所需特定文件的位置。

答案 5 :(得分:0)

我认为当时为什么它为空(如果你考虑的话)的原因是计时器经过的事件不会作为HTTP请求的一部分发生(因此没有上下文)。它是由您服务器上的某些内容引起的。