无法从 apicontroller 中的 OwinContext 获取 UserManager
Posted
技术标签:
【中文标题】无法从 apicontroller 中的 OwinContext 获取 UserManager【英文标题】:Can't get UserManager from OwinContext in apicontroller 【发布时间】:2014-07-22 23:12:37 【问题描述】:我正在关注 Microsoft 示例以使用 Identity 2.0.0 实现电子邮件验证
我被困在这部分
public ApplicationUserManager UserManager
get
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
private set
_userManager = value;
这在controller
中有效,但HttpContext
在ApiController 中不包含任何GetOwinContext
方法。
所以我尝试了HttpContext.Current.GetOwinContext()
,但方法GetUserManager
不存在。
我不知道如何获取我在 Startup.Auth.cs
中构建的UserManager
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
//Configure the db context, user manager and role manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
...
这一行
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
调用以下函数配置UserManager
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
//Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
;
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
manager.EmailService = new EmailService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
return manager;
如何在ApiController
中访问此UserManager
?
【问题讨论】:
你使用任何 DI 框架吗? 你的 ApiController 中不存在 GetOwinContext() 是什么意思?它是 null 还是空的? 对不起。方法不存在 看看我更新的答案。 【参考方案1】:这一行代码拯救了我的一天...
var manager =
new ApplicationUserManager(new UserStore<ApplicationUser>(new ApplicationDbContext()));
您可以在控制器操作中使用它来获取 UserManager 的实例。
【讨论】:
【参考方案2】:我之前真的误解了你的问题。我认为您只是缺少一些 using 语句。
GetOwinContext().GetUserManager<ApplicationUserManager>()
位于Microsoft.AspNet.Identity.Owin
。
所以尝试添加这部分:
using Microsoft.AspNet.Identity.Owin;
using Microsoft.AspNet.Identity; // Maybe this one too
var manager = HttpContext.Current.GetOwinContext().GetUserManager<UserManager<User>>();
【讨论】:
我以前也是这样做的,但是我在create函数中添加的选项不存在。 整体使用会不会更安全:System.Web.HttpContext.Current.Request.GetOwinContext().GetUserManager.... @RobertAchmann 我不明白为什么这应该更安全甚至更好,因为HttpContext.Current
是一个静态 属性,返回当前线程的HttpContext
。跨度>
这个答案实际上并没有回答这个问题,因为 HttpContext
在 ApiController 中是不可访问的。在 nuget 插件中使用 System.Net.Http
中的扩展名 System.Web.Http.Owin.dll
可以正常工作 - nuget.org/packages/Microsoft.AspNet.WebApi.Owin【参考方案3】:
如果您想对控制器进行单元测试,此扩展方法可能是更好的解决方案。
using System;
using System.Net.Http;
using System.Web;
using Microsoft.Owin;
public static IOwinContext GetOwinContext(this HttpRequestMessage request)
var context = request.Properties["MS_HttpContext"] as HttpContextWrapper;
if (context != null)
return HttpContextBaseExtensions.GetOwinContext(context.Request);
return null;
用法:
public ApplicationUserManager UserManager
get
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
private set
_userManager = value;
【讨论】:
这是更好的答案,应该被接受。不依赖 HttpContext.Current。 我完全同意,HttpContext.Current
引入了对System.Web
的依赖,这在自托管场景中不可用。 Request.GetOwinContext()
被注入,因此允许测试能力。后者两者都不是。
BTW...Request.GetOwinContext()
在 Microsoft.AspNet.WebApi.Owin nuget 包中定义
这帮助我避免了在我使用 HttpContext.Current.GetOwinContext()
时抛出的异常。这好多了。
同意这是更好的答案,因为它避免了 HttpContext.Current
周围的潜在异常问题。然后你可以写Request?.GetOwinContext()
。以上是关于无法从 apicontroller 中的 OwinContext 获取 UserManager的主要内容,如果未能解决你的问题,请参考以下文章
无法从 apicontroller 中的 OwinContext 获取 UserManager
使用 OData 响应 Owin Self-Host 忽略 Web Api 中的 Null 属性/值
从 MVC 控制器动作调用 APIController 动作