How to access the HttpServerUtility.MapPath method in a Thread or Timer?

Viewed 40628

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 HttpContext.Current.Server.MapPath. The problem is that HttpContext.Current is null when the Timer.Elapsed event fires.

Is there another way to get a reference to a HttpServerUtility object ? I could inject it in my class' constructor. Is it safe ? How can I be sure it won't be Garbage Collected at the end of the current request?

Thanks!

6 Answers

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.

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('/', '\\');
}

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?

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 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.

Related