I use a System.Timers.Timer
in my Asp.Net application and I need to use the HttpServerUtility.MapPath
method which seems to be only available via <
It's possible to use HostingEnvironment.MapPath()
instead of HttpContext.Current.Server.MapPath()
I haven't tried it yet in a thread or timer event though.
Some (non viable) solutions I considered;
The only method I care about on HttpServerUtility
is MapPath
. So as an alternative I could use AppDomain.CurrentDomain.BaseDirectory
and build my paths from this. But this will fail if your app uses virtual directories (Mine does).
Another approach:
Add all the paths I need to the the Global
class. Resolve these paths in Application_Start
.
Can you not call the MapPath function before starting the timer, and simply cache the result? Is it absolutely neccessary to have the MapPath call inside the tick event?
I think the reason for why it is null at that time (if you think about it), is that the timer elapsed event doesn't occur as part of a HTTP request (hence there is no context). It is caused by something on your server.
When the timer elapse, there is no current HTTP context. This is because the timer events are not related to a specific HTTP request.
What you should do is use HttpServerUtility.MapPath where HTTP context is available. You can do it in one of the request pipeline events (such as Page_Load) or in a Global.asax event such as Application_Start.
Assign the MapPath result to a variable accessible from the Timer.Elapsed event, where you could use Path.Combine to get the location of a specific file you need.
I don't know if this will solve your virtual directories issue, but I use this for 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('/', '\\');
}
HostingEnvironment isn't the perfect solution because it's a very difficult class to mock (see How to unit test code that uses HostingEnvironment.MapPath).
For those who need testability, a better way might be to create your own path-mapper interface as proposed by https://stackoverflow.com/a/1231962/85196, except implement it as
public class ServerPathMapper : IPathMapper {
public string MapPath(string relativePath) {
return HostingEnvironment.MapPath(relativePath);
}
}
The result is easily mockable, uses HostingEnvironment internally, and could even potentially address ase69s's concern at the same time.