c# - asp.net mvc formulaire




Ce client personnalisé dans le contrôleur de base ASP.NET MVC 3 est-il terriblement inefficace? (2)

Malgré le fait que je sois ici depuis un moment, c'est ma toute première question sur SO, alors soyez gentils avec moi.

J'utilise ASP.NET MVC 3 et je veux créer un Principal personnalisé afin que je puisse stocker un peu plus d'informations sur l'utilisateur actuel que ce qui est standard, donc pas besoin d'aller trop souvent à la base de données. C'est assez standard que je suis après. Disons simplement l'adresse e-mail et l'identifiant de l'utilisateur dans un premier temps.

J'ai décidé de stocker l'objet dans le cache car je suis conscient qu'il n'est pas conseillé de le stocker dans la session.

Je ne veux pas non plus devoir continuer à lancer l'objet User , donc je voulais surcharger l'objet User dans le contrôleur. Je peux donc aller User.UserId et être User.UserId de quelque chose.

J'ai donc créé un principal personnalisé comme celui-ci:

public class MyPrincipal : IPrincipal
{
    public MyPrincipal(IIdentity ident, List<string> roles, string email, Guid userId)
    {
        this._identity = ident;
        this._roles = roles;
        this._email = email;
        this._userId = userId;
    }

    IIdentity _identity;

    public IIdentity Identity
    {
        get { return _identity; }
    }

    private List<string> _roles;

    public bool IsInRole(string role)
    {
        return _roles.Contains(role);
    }

    private string _email;

    public string Email
    {
        get { return _email; }
    }

    private Guid _userId;

    public Guid UserId
    {
        get { return _userId; }
    }
}

Et j'ai un contrôleur de base comme celui-ci:

public class BaseController : Controller
    {
        protected virtual new MyPrincipal User
        {
            get
            {
                if (base.User is MyPrincipal)
                {
                    return base.User as MyPrincipal;
                }
                else
                {
                    return new MyPrincipal(base.User.Identity, new List<string>(0), "", Guid.Empty );
                }
            }
        }

        protected override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (User != null)
            {
                if (User.Identity.IsAuthenticated)
                {
                    if (User.Identity is FormsIdentity)
                    {
                        FormsIdentity id = base.User.Identity as FormsIdentity;
                        MyPrincipal principal = (MyPrincipal)filterContext.HttpContext.Cache.Get(id.Name);
                        if (principal == null)
                        {
                            MembershipUser user = Membership.GetUser();

                            // Create and populate your Principal object with the needed data and Roles.
                            principal = new MyPrincipal(id, Roles.GetRolesForUser(id.Name).ToList(), user.Email, (Guid)user.ProviderUserKey);
                            filterContext.HttpContext.Cache.Add(
                            id.Name,
                            principal,
                            null,
                            System.Web.Caching.Cache.NoAbsoluteExpiration,
                            new System.TimeSpan(0, 30, 0),
                            System.Web.Caching.CacheItemPriority.Default,
                            null);
                        }
                        filterContext.HttpContext.User = principal;
                        System.Threading.Thread.CurrentPrincipal = principal;
                        base.OnAuthorization(filterContext);
                    }
                }
            }
        }
    }

Si vous jetez un coup d'oeil, vous vous rendrez compte rapidement que si l'utilisateur ne s'est pas connecté, tout appel à l'objet User devra passer par ce bit de code:

return new MyPrincipal(base.User.Identity, new List<string>(0), "", Guid.Empty );

et cela me semble terriblement inefficace, même s'il ne s'agit que de créer des objets vides pour les choses manquantes.

Ça fonctionne bien.

Donc je suppose que je veux savoir si tout va bien et que je devrais arrêter d'être aussi anxieux à propos de la performance et de l'efficacité, ou si mes craintes sont correctes, auquel cas que devrais-je faire à la place? [S'il vous plaît ne dites pas "Obtenir une vie, mon pote!"]


Non, il n'y a rien de particulièrement faux avec ce code d'un point de vue performance qui se démarque. BEAUCOUP d'objets créent sur le backend dans ASP.NET, votre seul objet est une goutte dans le seau. Puisque l'instanciation de classe est extrêmement rapide, je ne m'en soucierais pas.

Pourquoi ignorez-vous les sessions ici? Les informations de session n'ont pas de date d'expiration, donc il n'y a pas de vérification supplémentaire en coulisse. Sauf si vous utilisez un serveur de session hors proc, il n'y a pas de sérialisation de votre objet (aucun avec le cache non plus). Le cache est pour chaque utilisateur - donc vous avez une chance (quoique légère) d'une erreur de code retournant le mauvais principal où un cache étant par utilisateur - ne court pas le risque de cela.

Si vous voulez que ceci soit disponible pour toutes les requêtes (pas seulement basées sur MVC), je considérerais le paramétrer dans Application_PostAuthenticateRequest






iprincipal