tag route password page net for data asp all asp.net owin katana

asp.net - route - select asp-for asp-items



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

Soy un novato en ASP.NET y estoy aprendiendo ASP.NET Identity. Sé que está construido sobre la implementación de OWIN por parte de Microsoft, y también estoy aprendiendo eso también. Entonces, me encontré con el método de extensión CreatePerOwinContext en el código de inicio de Owin, y no veo un claro propósito de usarlo. ¿Es algún tipo de contenedor de inyección de dependencia? ¿Cuál es el verdadero propósito del método? ¿En qué caso debería aplicarse?


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

Para responder a su pregunta más directamente, 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 suyo (IoC) sobre tu elección.
  3. (No me gusta IoC, se siente como un antipatró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 IoC, ¡funciones de fábrica estáticas IoC! ¿De quién fue la idea? ¿Por qué no usar solo la función Factory? Ahora tiene que recordar (Google) una llamada API adicional, y cuando presiona F12 en Get , no le ayuda en nada.

¿Qué deberías hacer entonces?

Personalmente, soy un fan de usar OO para esto, ¿recuerdas OO? Pepperidge Farm recuerda. Con OO, usted mantiene el control, puede depurar, iniciar sesión y puede extenderse.

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 por qué los ingenieros de Microsoft lo incluyen, es posible que tengan una buena razón para ello, pero lo dudo, así que vamos a votar mejor esta respuesta mientras tanto.

ACTUALIZAR

Aquí está el porqué, 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-identity/

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 tu propia instancia del contexto db en una clase base, es 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 desperdiciamos tratando de resolver estas API sofisticadas, y autorizar atributos y cosas por el estilo, cuando todo lo que queremos hacer es:

public void DoSomething() { DemandAuthenticated(); DemandAuthorised(typeof(somethingClass), "DoSomething"); }

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


puedes usar typeof para obtener el nombre así:

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


CreatePerOwinContext registra una devolución de llamada estática que su aplicación utilizará para recuperar una nueva instancia de un tipo especificado.
Esta devolución de llamada se llamará una vez por solicitud y almacenará el objeto / objetos en OwinContext para que pueda usarlos en toda la aplicación.

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

public class ApplicationDatabaseContext : IdentityDbContext<MyApplicationUser, MyRole, Guid, MyUserLogin, MyUserRole, MyUserClaim> { public ApplicationDatabaseContext() : base("<connection string>") { } 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<UserInfo>() .Property(p => p.FirstName) .HasColumnType("varchar") .HasMaxLength(70); modelBuilder.Entity<UserInfo>() .Property(p => p.LastName) .HasColumnType("varchar") .HasMaxLength(70); modelBuilder.Entity<UserInfo>() .Property(p => p.Address) .HasColumnType("varchar") .HasMaxLength(100); modelBuilder.Entity<UserInfo>() .Property(p => p.City) .HasColumnType("varchar") .HasMaxLength(100); modelBuilder.Entity<UserInfo>() .ToTable("UsersInfo"); #endregion } public DbSet<UserInfo> UsersInfo { get; set; } }

y su implementación de UserManager :

public class ApplicationUserManager : UserManager<MyApplicationUser, Guid> { public ApplicationUserManager(IUserStore<MyApplicationUser, Guid> store) : base(store) { } public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) { var manager = new ApplicationUserManager(new MyUserStore(context.Get<ApplicationDatabaseContext>())); manager.UserValidator = new UserValidator<MyApplicationUser, Guid>(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<MyApplicationUser, Guid>(dataProtectionProvider.Create("PasswordReset")); } return (manager); } }

En su Inicio de Owin, registrará la devolución de llamada:

// IAppBuilder app app.CreatePerOwinContext<ApplicationDatabaseContext>(ApplicationDatabaseContext.Create); app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

que llamará al método estático:

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

y

public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> 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<ApplicationDatabaseContext>(); ApplicationUserManager userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();

En su ApiController (si está utilizando WebApi):

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