ASP.NET MVC 5 - Identidad. Cómo obtener el usuario de aplicación actual
Tengo una entidad Artículo en mi proyecto que tiene la ApplicationUser
propiedad denominada Author
. ¿Cómo puedo obtener el objeto completo actualmente registrado ApplicationUser
? Al crear un nuevo artículo, tengo que establecer la Author
propiedad en Article
el archivo actual ApplicationUser
.
En el antiguo mecanismo de Membresía era simple, pero en el nuevo enfoque de Identidad no sé cómo hacerlo.
Intenté hacerlo de esta manera:
- Agregue la declaración de uso para las extensiones de identidad:
using Microsoft.AspNet.Identity;
- Luego intento obtener el usuario actual:
ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.Id == User.Identity.GetUserId());
Pero recibo la siguiente excepción:
LINQ to Entities no reconoce el método 'System.String GetUserId(System.Security.Principal.IIdentity)' y este método no se puede traducir a una expresión de tienda. Fuente = Marco de entidad
No debería necesitar consultar la base de datos directamente para el usuario de aplicación actual.
Eso introduce una nueva dependencia de tener un contexto adicional para empezar, pero en el futuro las tablas de la base de datos del usuario cambian (3 veces en los últimos 2 años), pero la API es consistente. Por ejemplo , users
ahora la tabla se llama AspNetUsers
en Identity Framework y los nombres de varios campos de clave principal seguían cambiando, por lo que el código en varias respuestas ya no funcionará tal como está .
Otro problema es que el acceso OWIN subyacente a la base de datos utilizará un contexto separado, por lo que los cambios desde el acceso SQL separado pueden producir resultados no válidos (por ejemplo, no ver los cambios realizados en la base de datos). Nuevamente, la solución es trabajar con la API proporcionada y no intentar solucionarlo .
La forma correcta de acceder al objeto de usuario actual en la identidad ASP.Net (a esta fecha) es:
var user = UserManager.FindById(User.Identity.GetUserId());
o, si tienes una acción asíncrona, algo como:
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
FindById
requiere que tenga la siguiente declaración de uso para que los métodos no asíncronos UserManager
estén disponibles (son métodos de extensión para UserManager, por lo que si no incluye esto, solo verá FindByIdAsync
):
using Microsoft.AspNet.Identity;
Si no está en ningún controlador (por ejemplo, está utilizando la inyección de IOC), entonces la identificación del usuario se recupera en su totalidad de:
System.Web.HttpContext.Current.User.Identity.GetUserId();
Si no está en el controlador de cuenta estándar, deberá agregar lo siguiente (como ejemplo) a su controlador:
1. Agregue estas dos propiedades:
/// <summary>
/// Application DB context
/// </summary>
protected ApplicationDbContext ApplicationDbContext { get; set; }
/// <summary>
/// User manager - attached to application DB context
/// </summary>
protected UserManager<ApplicationUser> UserManager { get; set; }
2. Agregue esto en el constructor del Controlador:
this.ApplicationDbContext = new ApplicationDbContext();
this.UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(this.ApplicationDbContext));
Actualización marzo 2015
Nota: La actualización más reciente del marco de identidad cambia una de las clases subyacentes utilizadas para la autenticación. Ahora puede acceder a él desde el contexto Owin del HttpContent actual.
ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
Apéndice:
Al utilizar EF e Identity Framework con Azure, a través de una conexión de base de datos remota (por ejemplo, pruebas de host local en la base de datos de Azure), puede aparecer aleatoriamente el temido "error: 19 - La conexión física no se puede utilizar". Como la causa está oculta dentro de Identity Framework, donde no puede agregar reintentos (o lo que parece faltar .Include(x->someTable)
), necesita implementar una costumbre SqlAzureExecutionStrategy
en su proyecto.
Está en los comentarios de las respuestas, pero nadie ha publicado esto como la solución real.
Sólo necesitas agregar una declaración de uso en la parte superior:
using Microsoft.AspNet.Identity;