Saltar al contenido

¿Cuál es el propósito del método de extensión CreatePerOwinContext en la implementación de OWIN por Microsoft?

Hola, tenemos la solución a tu interrogante, continúa leyendo y la obtendrás aquí.

Solución:

CreatePerOwinContext registra un static callback que su aplicación usará para recuperar una nueva instancia de un tipo específico.
Esta devolución de llamada se llamará una vez por solicitud y almacenará el objeto / objetos en OwinContext para que pueda utilizarlos durante toda la aplicación.

Digamos que ha definido su propia implementación de IdentityDbContext:

public class ApplicationDatabaseContext : IdentityDbContext

    public ApplicationDatabaseContext() : base("")
    
    

    public static ApplicationDatabaseContext Create()
    
        return new ApplicationDatabaseContext();
    

        protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
        
        base.OnModelCreating(modelBuilder);

        // Customize your table creation here.

            #region USERS - INFOS

        modelBuilder.Entity()
            .Property(p => p.FirstName)
            .HasColumnType("varchar")
            .HasMaxLength(70);

        modelBuilder.Entity()
            .Property(p => p.LastName)
            .HasColumnType("varchar")
            .HasMaxLength(70);

        modelBuilder.Entity()
            .Property(p => p.Address)
            .HasColumnType("varchar")
            .HasMaxLength(100);

        modelBuilder.Entity()
            .Property(p => p.City)
            .HasColumnType("varchar")
            .HasMaxLength(100);

        modelBuilder.Entity()
            .ToTable("UsersInfo");

        #endregion  
        

        public DbSet UsersInfo  get; set; 

y su implementación de UserManager:

public class ApplicationUserManager : UserManager

    public ApplicationUserManager(IUserStore store) : base(store)
        
        

        public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context)
        
            var manager = new ApplicationUserManager(new MyUserStore(context.Get()));

            manager.UserValidator = new UserValidator(manager)
            
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            ;

            manager.PasswordValidator = new PasswordValidator()
            
                RequiredLength = 6,
                RequireNonLetterOrDigit = false,    
                // RequireDigit = true,
                RequireLowercase = false,
                RequireUppercase = false,
            ;

            var dataProtectionProvider = options.DataProtectionProvider;

            if (dataProtectionProvider != null)
            
                manager.UserTokenProvider = new DataProtectorTokenProvider(dataProtectionProvider.Create("PasswordReset"));
            

            return (manager);
        

En tu Owin Puesta en marcha registrará la devolución de llamada:

// IAppBuilder app

app.CreatePerOwinContext(ApplicationDatabaseContext.Create);
app.CreatePerOwinContext(ApplicationUserManager.Create);

que llamará al static método:

public static ApplicationDatabaseContext Create()

    return new ApplicationDatabaseContext();

y

public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context)

    ...

Ahora podrá acceder al contexto de su base de datos y al administrador de usuarios de una manera sencilla y directa:

ApplicationDatabaseContext dbContext = context.OwinContext.Get();
ApplicationUserManager userManager = context.OwinContext.GetUserManager();

En tus ApiController (si está usando WebApi):

IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
ApplicationUserManager applicationUserManager = HttpContext.Current.GetOwinContext().GetUserManager();

¿Cuál es el verdadero propósito del método? ¿En qué caso debería aplicarse?

Para responder a su pregunta de manera más directa, esto es inútil.

  1. Es una especie de fábrica de IoC, que a algunas personas les gusta usar.
  2. Este te hace usar el de ellos (IoC) sobre tu elección.
  3. (No me gusta IoC, se siente como un anti-patrón para las personas que quieren sentirse cálidas y confusas y usan el término “arquitectura”).
  4. Pero en serio, este patrón no tiene interfaces de IoC, es IoC static funciones de fábrica! ¿De quién fue la idea? ¿Por qué no utilizar la función Factory usted mismo? Ahora debe recordar (Google) una llamada adicional a la API, y cuando presione F12 en Get, no te lleva a ninguna parte útil.

¿Qué deberías hacer en su lugar entonces?

Personalmente, soy fanático de usar OO para esto, ¿recuerdas OO? La granja de Pepperidge recuerda. Con OO, usted mantiene el control, puede depurar, registrar y extender.

public class BaseApiController : ApiController

    private AppDbContext _db = null;

    protected AppDbContext db
    
        get
        
            if (_db == null)
            
                _db = AppDbContext.Create(); //Hey look a proper factory that you can extend with other overloads! And I can debug this line - neat!
            
            return _db;
        

    

    protected override void Dispose(bool disposing)
    
        if (disposing)
        
            if (_db != null)
                _db.Dispose();
        
    


Todo esto podría ser una pérdida de tiempo, si alguien encuentra alguna documentación sobre la razón por la que los ingenieros de Microsoft pusieron esto, podría tener una buena razón por la cual, pero lo dudo, así que vamos a votar esta respuesta mientras tanto.

ACTUALIZACIÓN 1

Aquí está el por qué, por qué está ahí para Microsoft: https://blogs.msdn.microsoft.com/webdev/2014/02/12/per-request-lifetime-management-for-usermanager-class-in-asp-net- identidad/

Básicamente, el UserManager y todos ellos están diseñados para este tipo de estructura. Las comprobaciones de seguridad ocurren en la tubería, entonces, ¿por qué no tener un singleton vinculado a la solicitud, para reducir el desperdicio? Porque está escondido.

Aún así, recomendaría crear su propia instancia del contexto db en una clase base, lo hace mucho más limpio de usar. Si realmente lo desea, puede tener una propiedad en su clase base que recupere el singleton de OwinContext.

¿Cuánto tiempo perdemos tratando de desarrollar estas sofisticadas API y Authorize attributes y similares, cuando todo lo que queremos hacer es:

public void DoSomething()

   DemandAuthenticated();
   DemandAuthorised(typeof(somethingClass), "DoSomething");

Claramente, prefiero el código detallado que pueda ver.

Actualización 2

Los contextos de EF no deben mantenerse como singletons, y ciertamente no a través de ningún patrón de repositorio o de IoC.

Generalmente, sí, IoC puede ser bueno en situaciones. ¿Pero específicamente para un dbContext? No.

1) Los contextos EF DB son una unidad de trabajo, deben ser de corta duración. Si los mantiene en ejecución durante mucho tiempo, la caché de objetos ralentizará las consultas y las actualizaciones / inserciones en la base de datos subyacente se ralentizarán. Está diseñado para tener una vida útil corta. 2) Además, los contextos EF ya están débilmente acoplados. Puede cambiar el RDBMS detrás de un contexto en la conexión string, incluso puede usar solo memoria. 3) EF tiene LINQ, que es muy flexible, expresivo y seguro para escribir. 4) La base de datos no es un servicio de nivel empresarial para IoC, es una herramienta que utilizan los servicios para comunicarse con la base de datos. Quizás, podría tener algún tipo de servicio IEmail al que se accede a través de IoC. Pero debería acceder a la base de datos interna utilizando un nuevo contexto EF que se elimina inmediatamente después de completar las consultas. 5) Dado 1-4 arriba, ciertamente no queremos que ninguna capa de interfaz intermedia (Servicio o Repositorio) arruine todos los beneficios de usar EF en primer lugar.

puedes utilizar typeof para obtener el nombre así:

HttpContext.GetOwinContext().Get(typeof(ApplicationDbContext).ToString());

Reseñas y valoraciones

Tienes la opción de añadir valor a nuestro contenido informacional contribuyendo tu veteranía en las explicaciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *