Nex*_*per 49 asp.net owin katana
我是ASP.NET的新手,目前正在学习ASP.NET身份.我知道它建立在微软的OWIN实现之上,而且我也在学习它.所以,我在Owin启动代码中遇到了扩展方法CreatePerOwinContext,我没有看到使用它的明确目的.它是某种依赖注入容器吗?这个方法的真正目的是什么?在什么情况下应该应用它?
Lef*_*tyX 66
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; }
}
Run Code Online (Sandbox Code Playgroud)
和你的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);
}
}
Run Code Online (Sandbox Code Playgroud)
在您的Owin Startup中,您将注册回调:
// IAppBuilder app
app.CreatePerOwinContext<ApplicationDatabaseContext>(ApplicationDatabaseContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
Run Code Online (Sandbox Code Playgroud)
这将调用静态方法:
public static ApplicationDatabaseContext Create()
{
return new ApplicationDatabaseContext();
}
Run Code Online (Sandbox Code Playgroud)
和
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
...
}
Run Code Online (Sandbox Code Playgroud)
现在,您将能够以一种简单直接的方式访问数据库上下文和用户管理器:
ApplicationDatabaseContext dbContext = context.OwinContext.Get<ApplicationDatabaseContext>();
ApplicationUserManager userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
Run Code Online (Sandbox Code Playgroud)
在你的ApiController中(如果你使用的是WebApi):
IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
ApplicationUserManager applicationUserManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
Run Code Online (Sandbox Code Playgroud)
该方法的真正目的是什么?在什么情况下应该使用它?
为了更直接地回答您的问题,这是没有用的。
Get
,对您毫无帮助。那你该怎么办呢?
就个人而言,我是为此使用OO的粉丝,还记得OO吗?Pepperidge农场记得。使用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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
所有这一切都可能是浪费时间,如果有人找到Microsoft工程师为何要使用此文档的话,他们可能有充分的理由,但我对此表示怀疑,因此,让我们在此同时提出一个答案。
更新1
这是Microsoft的原因,原因:https://blogs.msdn.microsoft.com/webdev/2014/02/12/per-request-lifetime-management-for-usermanager-class-in-asp-net-身份/
基本上,UserManager及其所有都是针对这种结构而构建的。安全检查发生在管道中,那么为什么不将单例链接到请求以减少浪费呢?因为它是隐藏的。
我仍然建议在基类上创建自己的db上下文实例,这样可以使使用起来更加简洁。如果确实需要,则可以在基类中有一个属性,该属性从OwinContext中检索单例。
当我们要做的全部事情是:时,我们花了多少时间来尝试开发这些奇特的API和Authorize属性等。
public void DoSomething()
{
DemandAuthenticated();
DemandAuthorised(typeof(somethingClass), "DoSomething");
}
Run Code Online (Sandbox Code Playgroud)
显然,我更喜欢您可以看到的详细代码。
更新2
EF上下文不应作为单例保存,当然也不应通过任何IoC或存储库模式保存。
通常,是的,IoC在某些情况下会很好。但是专门针对dbContext吗?没有。
1)EF DB上下文是一个工作单元,应该短暂存在。如果您让它们长时间运行,则对象缓存将减慢查询的速度,并且对基础数据库的更新/插入会变慢。它的设计寿命很短。2)此外,EF上下文已经松散耦合。您可以在连接字符串中的上下文后面更改RDBMS,甚至可以使用仅内存。3)EF具有LINQ,它非常灵活,易于表达且类型安全。4)数据库不是IoC的业务级服务,它是服务用来与数据库进行通信的工具。也许,您可能具有通过IoC访问的IEmail服务。但是它应该使用新的EF上下文访问内部数据库,该上下文在查询完成后会立即处理。5)鉴于以上1-4,我们当然不会
归档时间: |
|
查看次数: |
18754 次 |
最近记录: |