Какова цель метода расширения CreatePerOwinContext в реализации OWIN корпорацией Майкрософт
Я новичок в ASP.NET, и в настоящее время обучение ASP.NET личность. Я знаю, что он построен поверх реализации OWIN Microsoft, и я также все еще учусь этому. Итак, я наткнулся на метод расширения CreatePerOwinContext в коде запуска Owin, и я не вижу четкой цели его использования. Это какой-то контейнер внедрения зависимостей? Какова реальная цель метода? В каком случае его следует применять?
3 ответов
CreatePerOwinContext регистрирует статический обратный вызов, который ваше приложение будет использовать для возврата нового экземпляра указанного типа.
Этот обратный вызов будет вызываться один раз за запрос и будет хранить объект/объекты в OwinContext, так что вы сможете использовать их в приложении.
предположим, вы определили свою собственную реализацию 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; }
}
и ваш реализация 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);
}
}
в вашем Owin запуск вы зарегистрируете обратный вызов:
// IAppBuilder app
app.CreatePerOwinContext<ApplicationDatabaseContext>(ApplicationDatabaseContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
который вызовет статический метод:
public static ApplicationDatabaseContext Create()
{
return new ApplicationDatabaseContext();
}
и
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
...
}
теперь вы сможете получить доступ к контексту базы данных и диспетчеру пользователей простым простым способом:
ApplicationDatabaseContext dbContext = context.OwinContext.Get<ApplicationDatabaseContext>();
ApplicationUserManager userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
в своем ApiController (если вы используете WebApi):
IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
ApplicationUserManager applicationUserManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
какова реальная цель этого метода? В каком случае следует применены?
чтобы ответить на ваш вопрос более прямо, это бесполезно.
- это своего рода фабрика МОК, которую некоторые люди любят использовать.
- это заставляет вас использовать их (МОК) по вашему выбору.
- (мне не нравится МОК, это похоже на анти-шаблон для людей, которые хотят чувствовать себя теплыми и нечеткими и использовать термин "архитектура.")
- но серьезно, этот шаблон не интерфейсы IoC, это статические заводские функции IoC! Чья это была идея? Почему бы просто не использовать заводскую функцию самостоятельно? Теперь вам нужно запомнить (Google) дополнительный вызов API, и когда вы нажимаете F12 на
Get
, он не принимает вас нигде полезно.
что вы должны делать вместо этого?
лично я поклонник использования OO для этого, помните OO? Пепперидж фарм помнит. С OO, вы остаетесь в контроль, отладка, журнала, и вы можете продлить.
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();
}
}
}
все это может быть пустой тратой времени, если кто-то найдет документацию, почему инженеры Microsoft поместили это, у них может быть веская причина, но я сомневаюсь в этом, поэтому давайте пока повторим этот ответ.
обновление
вот почему, почему это там для Microsoft: https://blogs.msdn.microsoft.com/webdev/2014/02/12/per-request-lifetime-management-for-usermanager-class-in-asp-net-identity/
в основном, UserManager и все они построены для такого рода структуры. Проверки безопасности происходят в конвейере, так почему бы не иметь синглтон, связанный с запросом, чтобы уменьшить отходы? Потому что он спрятан.
Я бы все равно рекомендовал создать свой собственный экземпляр контекста db на baseclass, это делает его намного чище использовать. Если вы действительно хотите, у вас может быть свойство в вашем baseclass, которое извлекает синглтон из OwinContext.
сколько времени мы тратим, пытаясь разработать эти причудливые API и разрешить атрибуты и тому подобное, когда все, что мы хотим сделать, это:
public void DoSomething()
{
DemandAuthenticated();
DemandAuthorised(typeof(somethingClass), "DoSomething");
}
очевидно, я предпочитаю подробный код, который вы можете видеть.
вы можете использовать typeof
чтобы получить такое имя:
HttpContext.GetOwinContext().Get<ApplicationDbContext>(typeof(ApplicationDbContext).ToString());