89

System.Timers.Timer在我的 Asp.Net 应用程序中使用了 a ,我需要使用HttpServerUtility.MapPath似乎只能通过HttpContext.Current.Server.MapPath. 问题在于HttpContext.Current事件null何时Timer.Elapsed触发。

还有另一种方法来获取对 HttpServerUtility 对象的引用吗?我可以将它注入我的类的构造函数中。安全吗?我怎么能确定它不会在当前请求结束时被垃圾收集?

谢谢!

4

6 回答 6

143

可以使用HostingEnvironment.MapPath()而不是HttpContext.Current.Server.MapPath()

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


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

  • 我关心的唯一方法HttpServerUtilityMapPath. 因此,作为替代方案,我可以使用AppDomain.CurrentDomain.BaseDirectory并以此构建我的路径。但是,如果您的应用程序使用虚拟目录(我的),这将失败。

  • 另一种方法:将我需要的所有路径添加到Global类中。解决这些路径Application_Start

于 2008-09-21T21:19:40.347 回答
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('/', '\\');
}
于 2009-01-27T23:31:21.050 回答
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 的问题

于 2012-07-09T21:52:06.237 回答
2

能不能在启动定时器之前不调用 MapPath 函数,只缓存结果?在滴答事件中调用 MapPath 是绝对必要的吗?

于 2008-09-21T20:23:50.247 回答
2

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

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

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

于 2008-09-21T20:48:56.613 回答
0

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

于 2008-09-21T20:23:41.167 回答