Como acessar o método HttpServerUtility.MapPath em um thread ou temporizador?
-
02-07-2019 - |
Pergunta
Eu uso um System.Timers.Timer
na minha aplicação Asp.Net e eu preciso usar o método HttpServerUtility.MapPath
que parece ser apenas disponível através HttpContext.Current.Server.MapPath
.
O problema é que HttpContext.Current
é null
quando o evento é acionado Timer.Elapsed
.
Existe outra maneira para obter uma referência a um objeto HttpServerUtility? Eu poderia injetá-lo na minha classe construtor. É seguro ? Como posso estar certo de que não vai ser lixo coletado no final da solicitação atual?
Obrigado!
Solução
É possível usar HostingEnvironment.MapPath()
vez de HttpContext.Current.Server.MapPath()
Eu não tentei ainda em um evento de thread ou temporizador embora.
Algumas soluções (não viáveis) Eu considerei;
-
O único método que me interessa em
HttpServerUtility
éMapPath
. Assim como uma alternativa que eu poderia usarAppDomain.CurrentDomain.BaseDirectory
e construir meus caminhos deste. Mas isso vai falhar se o seu aplicativo usa diretórios virtuais (Minas faz). -
Outra abordagem: Adicione todos os caminhos que eu preciso para a classe do
Global
. Resolver esses caminhos emApplication_Start
.
Outras dicas
Eu não sei se isso vai resolver o seu problema diretórios virtual, mas eu uso isso para 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 não é a solução perfeita, porque é uma classe muito difícil de simulação (veja Como código de teste de unidade que usos HostingEnvironment.MapPath ).
Para aqueles que precisam a capacidade de teste, uma maneira melhor poderia ser a de criar sua própria interface caminho-mapeador como proposto por https: // stackoverflow .com / a / 1231962/85196 , exceto implementá-lo como
public class ServerPathMapper : IPathMapper {
public string MapPath(string relativePath) {
return HostingEnvironment.MapPath(relativePath);
}
}
O resultado é facilmente mockable, usa HostingEnvironment internamente, e até poderia potencialmente endereço das ase69s preocupação ao mesmo tempo.
Você não pode chamar a função MapPath antes de iniciar o temporizador, e simplesmente armazenar em cache o resultado? É absolutamente neccessary para ter a chamada MapPath dentro do evento tick?
Quando o decorrer timer, não há contexto HTTP atual. Isso ocorre porque os eventos timer não estão relacionados a uma solicitação HTTP específica.
O que você deve fazer é usar HttpServerUtility.MapPath onde HTTP contexto está disponível. Você pode fazê-lo em um dos eventos de pedido de pipeline (como Page_Load) ou em um evento Global.asax como Application_Start.
Atribuir o resultado MapPath a uma variável acessível a partir do evento Timer.Elapsed, onde você poderia usar Path.Combine para obter a localização de um arquivo específico que você precisa.
Eu acho que a razão pela qual ele é nulo nesse momento (se você pensar sobre isso), é que o temporizador decorrido evento não ocorre como parte de uma solicitação HTTP (portanto, não há contexto). É causada por algo em seu servidor.