无法从 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 中有效,但HttpContextApiController 中不包含任何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&lt;ApplicationUserManager&gt;() 位于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 属性/值

ApiController 无法处理 404 异常

从 MVC 控制器动作调用 APIController 动作

从 OWIN 中的 OAuth Bearer Token 获取 IPrincipal

无法在 auth 子文件夹中访问我的 apicontroller