70

I'm following a Microsoft sample to implement email validation with Identity 2.0.0

I'm stuck at this part

public ApplicationUserManager UserManager
{
   get
   {
      return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
   }
   private set
   {
      _userManager = value;
   }
}

This works in an controller but HttpContext doesn't contain any GetOwinContext method in an ApiController.

So I tried HttpContext.Current.GetOwinContext() but the method GetUserManager doesn't exist.

I can't figure out a way to get the UserManager I build in Startup.Auth.cs

// 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); 
    ...
}

this line

app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

calls the following function to configure the 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;
}

How can I access this UserManager in an ApiController?

Rikard
  • 3,828
  • 1
  • 24
  • 39
Marc
  • 16,170
  • 20
  • 76
  • 119

3 Answers3

90

I really misunderstood your question earlier. You are just missing some using statements, I think.

The GetOwinContext().GetUserManager<ApplicationUserManager>() is in Microsoft.AspNet.Identity.Owin.

So try add this part:

using Microsoft.AspNet.Identity.Owin;
using Microsoft.AspNet.Identity; // Maybe this one too

var manager = HttpContext.Current.GetOwinContext().GetUserManager<UserManager<User>>();
H. Pauwelyn
  • 13,575
  • 26
  • 81
  • 144
Rikard
  • 3,828
  • 1
  • 24
  • 39
  • 1
    That's what I used to do but the options I add in the create function are not there. – Marc Jun 02 '14 at 19:53
  • 7
    Would it be safer overall to use : System.Web.HttpContext.Current.Request.GetOwinContext().GetUserManager.... – Robert Achmann Sep 23 '14 at 19:09
  • 1
    @RobertAchmann I can't see why that should be safer or even better because `HttpContext.Current` is a _static_ property returning the current `HttpContext` for the thread. – Rikard Nov 13 '15 at 10:08
  • 1
    This answer doesn't actually answer the question as `HttpContext` is not accessible in an ApiController. Using the extension in `System.Net.Http` from `System.Web.Http.Owin.dll` works fine from the nuget plugin - https://www.nuget.org/packages/Microsoft.AspNet.WebApi.Owin – dan richardson Aug 31 '16 at 09:18
  • The manager returns null for me, do you have any idea why? – AsIndeed Oct 14 '22 at 09:24
28

This extension method may be a better solution if you want to unit test your controllers.

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;
}

Usage:

public ApplicationUserManager UserManager
{
   get
   {
      return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
   }
   private set
   {
      _userManager = value;
   }
}
moander
  • 2,080
  • 2
  • 19
  • 13
  • 1
    This is the better answer and should be the accepted one. Does not rely on HttpContext.Current. – MPavlak Jan 20 '16 at 17:14
  • 3
    I totally agree, the `HttpContext.Current` introduces a dependency to `System.Web`, which is not available in self-hosted scenarios. `Request.GetOwinContext()` is injected, therefore allowing for test-ability. The latter is neither. – Chef_Code Mar 25 '16 at 21:49
  • 7
    BTW... `Request.GetOwinContext()` is defined in the Microsoft.AspNet.WebApi.Owin nuget package – Chef_Code Mar 25 '16 at 23:04
  • This helped me avoid exceptions that were getting thrown when i would use `HttpContext.Current.GetOwinContext()`. This is much better. – petrosmm Aug 08 '18 at 19:02
  • Agree this is the better answer as it avoids potential exception issues around `HttpContext.Current`. You can then just write `Request?.GetOwinContext()`. – ScottB Nov 10 '19 at 04:59
  • I'm getting "The given key was not present in the dictionary" error when using like this, because Request is returning null because there is no property in request as "MS_HttpContext". I tried with "MS_OwinContext" or "MS_RequestContext", in these cases context returns null – AsIndeed Oct 14 '22 at 09:39
7

This single line of code saved my day...

       var manager = 
       new ApplicationUserManager(new UserStore<ApplicationUser>(new ApplicationDbContext()));

You can use it within a controller action to get an instance of UserManager.

Mubsher Mughal
  • 442
  • 8
  • 19