Pergunta

eu tenho um HttpModule que cria um objeto CommunityPrincipal (implementa a interface IPrincipal) em cada solicitação. Eu quero armazenar alguma forma o objeto para cada pedido soo i pode obtê-lo sempre que eu precisar dele sem ter que fazer um elenco ou criá-la novamente.

Basicamente eu quero imitar a forma como o FormsAuthenticationModule funciona. Ele atribui a propriedade HttpContext.User um objeto que implementa a interface IPrincipal, em cada solicitação.

De alguma maneira eu quero ser capaz de chamar etc. HttpContext.MySpecialUser (ou MySpecialContext.MySpecialUser - poderia criar classe estática). Que retornará meu objeto (o tipo específico)

Eu poderia usar um método de extensão, mas não sei como armazenar o objeto para que ele possa ser acessado durante o pedido.

Como isso pode ser alcançado?

Por favor note que eu quero armazená-lo como o tipo específico (CommunityPrincipal - não apenas como um objeto). É, naturalmente, só deve estar disponível para o pedido está sendo processado e não compartilhados com todos os outros segmentos / pedidos.

Agora eu atribuir meu objeto CommunityPrincipal ao HttpContext.User na HttpModule, mas me obriga a fazer uma vez de elenco eu preciso para usar propriedades no objeto CommunityPrincipal que não está definido na interface IPrincipal.

Foi útil?

Solução

A atribuição de seu principal personalizado para Context.User está correto. Esperamos que você está fazendo isso em Application_AuthenticateRequest.

Chegando à sua pergunta, não só acessar o objeto usuário de páginas ASPX? Se assim você poderia implementar uma página base personalizado que contém o elenco para você.

public class CommunityBasePage : Page
{
    new CommunityPrincipal User
    {
        get { return base.User as CommunityPrincipal; }
    }
}

Em seguida, fazer suas páginas herdam CommunityBasePage e você será capaz de chegar a todas as suas propriedades de this.User.

Outras dicas

Eu recomendo que você fique longe de acoplamento seus dados para o próprio fio. Você não tem nenhum controle sobre como asp.net usa segmentos agora ou no futuro.

Os dados são muito ligados ao contexto de solicitação por isso deve ser definido, ao vivo, e morrer junto com o contexto. Isso é apenas o lugar certo para colocá-lo, e instanciar o objeto em um HttpModule também é apropriado.

O elenco realmente não deve ser um grande problema, mas se você quiser ficar longe de que eu recomendo um método de extensão para HttpContext para este ... este é exatamente o tipo de situação que os métodos de extensão são projetado para lidar com.

Aqui está como eu iria implementá-lo:

Criar uma classe estática para colocar o método de extensão:

public static class ContextExtensions
{
    public static CommunityPrinciple GetCommunityPrinciple(this HttpContext context)
    {
        if(HttpContext.Current.Items["CommunityPrinciple"] != null)
        {
            return HttpContext.Current.Items["CommunityPrinciple"] as CommunityPrinciple;
        }
    }
}

Em seu HttpModule basta colocar o principal para a colecção itens de contexto como:

HttpContext.Current.Items.Add("CommunityPrincipal", MyCommunityPrincipal); 

Isso mantém propriedade do usuário do contexto regular no estado natural para que o código do 3o partido, código do framework, e qualquer outra coisa que você escreve não está em risco de você ter adulterado o IPrincipal normais stroed lá. A instância existe apenas durante a solicitação do usuário para o qual é válido. E o melhor de tudo, o método está disponível para o código como se fosse apenas um membro qualquer HttpContext normal .... e nenhum elenco necessário.

Uma vez que você já armazenar o objeto na propriedade HttpContext.User tudo o que você realmente precisa para conseguir seu objetivo é um método estático que acheives seu objetivo: -

  public static class MySpecialContext
  {
    public static CommunityPrinciple Community
    {
        get
        {
           return (CommunityPrinciple)HttpContext.Current.User;
        }
    }
  }

Agora você pode obter o CommunityPrinciple como: -

  var x = MySpecialContext.Community;

No entanto, parece um grande esforço para consegui evitar: -

  var x = (CommunityPrinciple)Context.User;

Uma alternativa seria um método de extensão em HttpContext: -

  public static class HttpContextExtensions
  {
    public static CommunityPrinciple GetCommunity(this HttpContext o)
    {
      return (CommunityPrinciple)o.User;
    }
  }

O uso ele: -

  var x = Context.GetCommunity();

Isso é muito arrumado, mas vai exigir que você lembre-se de incluir o namespace onde a classe extensões está definido na lista usando em cada arquivo as necessidades de TI.

Editar :

Vamos assumir por um momento que você tem alguma boa razão por que mesmo um elenco realizada dentro chamado código como acima ainda é inaceitável (BTW, eu estaria realmente interessado em compreender o que leva circunstância a esta conclusão).

No entanto, outra alternativa é um campo ThreadStatic: -

  public class MyModule : IHttpModule
  {
    [ThreadStatic]
    private static CommunityPrinciple _threadCommunity;

    public static CommunityPrinciple Community
    {
        get
        {
           return _threadCommunity;
        }
    }
    // Place here your original module code but instead of (or as well as) assigning
    // the Context.User store in _threadCommunity.
    // Also at the appropriate point in the request lifecyle null the _threadCommunity

  }

Um campo decorado com [ThreadStatic] terá uma instância de armazenamento por thread. Daí vários segmentos pode modificar e ler _threadCommunity mas cada um vai operar em sua instância específica do campo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top