A pesar de que he estado aquí por un tiempo, esta es mi primera pregunta sobre SO, así que por favor sean gentiles conmigo.¿Es este principal personalizado en el controlador base ASP.NET MVC 3 terriblemente ineficiente?
Estoy usando ASP.NET MVC 3
y quiero crear un Principal
personalizado para que pueda almacenar un poco más de información sobre el usuario actual que es estándar, por lo tanto, no tiene que ir a la base de datos con demasiada frecuencia. Es bastante estándar lo que estoy buscando. Digamos la dirección de correo electrónico y la identificación del usuario en primera instancia.
He decidido almacenar el objeto en la memoria caché, ya que soy consciente de que no se recomienda almacenarlo en la sesión.
Tampoco quiero tener que continuar lanzando el objeto User
, por lo que quería anular el objeto User
en el controlador. Así que puedo ir al User.UserId
y estar seguro de algo.
Así que he creado un principal personalizada de esta manera:
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; }
}
}
Y tengo un controlador base de esta manera:
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 usted tiene una mirada enseguida se dará cuenta de que si el usuario tiene no ha iniciado sesión entonces cualquier llamada al objeto User
tendrá que ejecutar este código:
return new MyPrincipal(base.User.Identity, new List<string>(0), "", Guid.Empty);
y esto me parece terriblemente ineficiente, aunque solo crea objetos vacíos para las cosas que faltan.
Funciona bien.
Supongo que quiero saber si esto está realmente bien y debería dejar de ser tan anal con el rendimiento y la eficiencia, o si mis temores son correctos, en cuyo caso ¿qué debería hacer? [Por favor, no diga "¡Conseguir una vida, amigo!"]
No hay que olvidar [Knuth] (http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize) ... "La optimización prematura es la raíz de todo mal". Es decir, ¿realmente ha visto problemas de rendimiento? –
+1 Agradable. No, yo no.¡Pero la cosa es que me sentía bastante inteligente por haber hecho que todo funcionara hasta que miré esa desagradable línea de código! ¡Guauu! ¡Realmente soy anal! Supongo que eso es lo que sucede al haber comenzado a codificar en la BBC Micro, donde los ciclos del reloj eran escasos y distantes ... –