Domanda

ho un HttpModule che crea un CommunityPrincipal (implementa l'interfaccia IPrincipal) oggetto su ogni richiesta. Voglio conservare in qualche modo l'oggetto per ogni richiesta soo posso farlo ogni volta che ho bisogno, senza dover fare un cast o crearne di nuovo.

Fondamentalmente voglio imitare il modo in cui il FormsAuthenticationModule funziona. Si assegna la proprietà HttpContext.User un oggetto che implementa l'interfaccia IPrincipal, su ogni richiesta.

In qualche modo voglio essere in grado di chiamare, ecc HttpContext.MySpecialUser (o MySpecialContext.MySpecialUser - potrebbe creare classe statica). Che restituirà il mio oggetto (il tipo specifico)

ho potuto utilizzare un metodo di estensione ma non so come memorizzare l'oggetto in modo che possa essere letta durante la richiesta.

Come può essere raggiunto?

Si prega di notare che voglio conservarlo come il tipo specifico (CommunityPrincipal - non solo come un oggetto). Dovrebbe essere disponibile ovviamente solo per la richiesta corrente in corso di elaborazione e non condiviso con tutti gli altri thread / richieste.

In questo momento mi assegna il mio oggetto CommunityPrincipal alla HttpContext.User nel HttpModule, ma mi obbliga a fare un ogni getto ho bisogno di utilizzare le proprietà sull'oggetto CommunityPrincipal che costerà definito nell'interfaccia IPrincipal.

È stato utile?

Soluzione

L'assegnazione vostro principale personalizzato per Context.User è corretta. Speriamo che si sta facendo in Application_AuthenticateRequest.

Venendo alla tua domanda, si accede solo l'oggetto utente da pagine ASPX? Se è così si potrebbe implementare una pagina personalizzata di base che contiene il cast per voi.

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

quindi apportare le pagine ereditano da CommunityBasePage e sarete in grado di ottenere a tutti i vostri oggetti di this.User.

Altri suggerimenti

mi consiglia di stare lontano da accoppiare i dati al thread stesso. Tu non hai il controllo su come asp.net utilizza i thread ora o in futuro.

I dati sono molto legato al contesto richiesta quindi dovrebbe essere definito, vivo, e muore insieme con il contesto. Questo è il posto giusto per metterla, e istanziare l'oggetto in un HttpModule è anche opportuno.

Il cast in realtà non dovrebbe essere un gran problema, ma se si vuole uscire da quel consiglio caldamente un metodo di estensione per HttpContext per questo ... questo è esattamente il tipo di situazione che i metodi di estensione sono progettato per gestire.

Ecco come mi piacerebbe implementare è:

Creare una classe statica per mettere il metodo di estensione:

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

Nel vostro HttpModule appena messo il preside nella collezione elementi di contesto come:

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

Ciò mantiene proprietà utente del contesto regolare allo stato naturale in modo che il codice 3a parte, codice del framework, e qualsiasi altra cosa che si scrive non è a rischio da voi dopo aver manomesso il normale IPrincipal stroed lì. esiste l'istanza solo durante la richiesta dell'utente per il quale è valido. E meglio di tutti, il metodo è disponibile a codice come se si trattasse di un qualsiasi membro HttpContext regolare .... e non getto necessario.

Dal momento che già memorizzare l'oggetto nella proprietà HttpContext.User tutto quello che ha realmente bisogno di acheive si obiettivo è un metodo statico che acheives il vostro obiettivo: -

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

Ora è possibile ottenere il CommunityPrinciple come: -

  var x = MySpecialContext.Community;

Tuttavia sembra un grande sforzo per ottenuto da evitare: -

  var x = (CommunityPrinciple)Context.User;

Un'alternativa sarebbe un metodo di estensione su HttpContext: -

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

L'uso che: -

  var x = Context.GetCommunity();

Questo è abbastanza ordinata ma richiedono di ricordare di includere il namespace in cui la classe estensioni è definito nella lista utilizzando in ogni file le esigenze di esso.

Modifica :

Consente di assumere per il momento che hai qualche buona ragione per cui anche un cast eseguita all'interno chiamato il codice di cui sopra è ancora inaccettabile (a proposito, sarei veramente interessato a capire che cosa circostanza vi porta a questa conclusione).

Ancora un'altra alternativa è un 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

  }

Un campo decorato con [ThreadStatic] avrà un'istanza di archiviazione per thread. Quindi più thread possono modificare e leggere _threadCommunity ma ogni opereranno sul loro caso specifico del campo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top