88 votes

Comment accéder à la méthode HttpServerUtility.MapPath dans un Thread ou un Timer ?

J'utilise un System.Timers.Timer dans mon application Asp.Net et j'ai besoin d'utiliser l'application HttpServerUtility.MapPath qui semble n'être disponible que via HttpContext.Current.Server.MapPath . Le problème est que HttpContext.Current es null lorsque le Timer.Elapsed se déclenche.

Existe-t-il un autre moyen d'obtenir une référence à un objet HttpServerUtility ? Je pourrais l'injecter dans le constructeur de ma classe. Est-ce sûr ? Comment puis-je être sûr qu'il ne sera pas collecté à la fin de la requête en cours ?

Merci !

142voto

Costo Points 2187

Il est possible d'utiliser HostingEnvironment.MapPath() au lieu de HttpContext.Current.Server.MapPath()

Je ne l'ai pas encore essayé dans un fil de discussion ou un événement de minuterie.


Quelques solutions (non viables) que j'ai envisagées ;

  • La seule méthode qui m'intéresse sur HttpServerUtility es MapPath . Donc, comme alternative, je pourrais utiliser AppDomain.CurrentDomain.BaseDirectory et construire mes chemins à partir de ça. Mais cela échouera si votre application utilise des répertoires virtuels. (Le mien le fait).

  • Une autre approche : Ajouter tous les chemins dont j'ai besoin à la Global classe. Résolvez ces chemins dans Application_Start .

14voto

Je ne sais pas si cela résoudra votre problème de répertoires virtuels, mais je l'utilise pour 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('/', '\\');
}

13voto

Mike Points 1832

HostingEnvironment n'est pas la solution parfaite, car il s'agit d'une classe très difficile à simuler (cf. Comment tester un code unitaire qui utilise HostingEnvironment.MapPath ? ).

Pour ceux qui ont besoin de testabilité, une meilleure façon de procéder pourrait être de créer votre propre interface de mappage de chemin comme proposé par https://stackoverflow.com/a/1231962/85196 à l'exception de l'implémentation en tant que

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

Le résultat est facilement mockable, utilise HostingEnvironment en interne, et pourrait même potentiellement répondre à la question suivante L'inquiétude de ase69s en même temps.

2voto

Mark S. Rasmussen Points 13313

Ne pouvez-vous pas appeler la fonction MapPath avant de lancer la minuterie, et simplement mettre le résultat en cache ? Est-il absolument nécessaire d'appeler la fonction MapPath dans l'événement tick ?

2voto

zvikara Points 1263

Lorsque le délai est écoulé, il n'y a pas de contexte HTTP en cours. Cela est dû au fait que les événements de la minuterie ne sont pas liés à une demande HTTP spécifique.

Ce que vous devez faire, c'est utiliser HttpServerUtility.MapPath lorsque le contexte HTTP est disponible. Vous pouvez le faire dans l'un des événements du pipeline de requête (comme Page_Load) ou dans un événement Global.asax comme Application_Start.

Affectez le résultat de MapPath à une variable accessible depuis l'événement Timer.Elapsed, où vous pourriez utiliser Path.Combine pour obtenir l'emplacement d'un fichier spécifique dont vous avez besoin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X