UserManager kann nicht von OwinContext in apicontroller abgerufen werden

70

Ich folge einem Microsoft-Beispiel, um die E-Mail-Validierung mit Identity 2.0.0 zu implementieren

Ich stecke in diesem Teil fest

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

Dies funktioniert in ein , controlleraber HttpContextenthält keine GetOwinContextMethode in einem ApiController .

Also habe ich es versucht, HttpContext.Current.GetOwinContext()aber die Methode GetUserManagerexistiert nicht.

Ich kann keinen Weg finden, um das zu bekommen, was UserManagerich in Startup.Auth.cs erstellt habe

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

diese Linie

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

ruft die folgende Funktion auf, um die zu konfigurieren 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;
}

Wie kann ich UserManagerin einem darauf zugreifen ApiController?

Marc
quelle
Verwenden Sie ein DI-Framework?
Rikard
Was meinst du damit, dass GetOwinContext () in deinem ApiController nicht vorhanden ist? Ist es null oder leer?
Rikard
Es tut uns leid. Die Methode existiert nicht
Marc
Schau dir meine aktualisierte Antwort an.
Rikard

Antworten:

88

Ich habe Ihre Frage früher wirklich falsch verstanden. Sie vermissen nur einige verwendende Aussagen, denke ich.

Das GetOwinContext().GetUserManager<ApplicationUserManager>()ist in Microsoft.AspNet.Identity.Owin.

Versuchen Sie also, diesen Teil hinzuzufügen:

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

var manager = HttpContext.Current.GetOwinContext().GetUserManager<UserManager<User>>();
Rikard
quelle
1
Das habe ich früher gemacht, aber die Optionen, die ich in der Erstellungsfunktion hinzufüge, sind nicht vorhanden.
Marc
7
Wäre es insgesamt sicherer zu verwenden: System.Web.HttpContext.Current.Request.GetOwinContext (). GetUserManager ....
Robert Achmann
1
@RobertAchmann Ich kann nicht verstehen, warum das sicherer oder sogar besser sein sollte, da HttpContext.Currenteine statische Eigenschaft den Strom HttpContextfür den Thread zurückgibt .
Rikard
1
Diese Antwort beantwortet die Frage nicht wirklich, da HttpContextsie in einem ApiController nicht verfügbar ist. Die Verwendung der Erweiterung in System.Net.Httpfrom System.Web.Http.Owin.dll funktioniert einwandfrei über das Nuget-Plugin - nuget.org/packages/Microsoft.AspNet.WebApi.Owin
dan richardson
28

Diese Erweiterungsmethode ist möglicherweise eine bessere Lösung, wenn Sie Ihre Controller einem Unit-Test unterziehen möchten.

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

Verwendung:

public ApplicationUserManager UserManager
{
   get
   {
      return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
   }
   private set
   {
      _userManager = value;
   }
}
Moander
quelle
1
Dies ist die bessere Antwort und sollte akzeptiert werden. Verlässt sich nicht auf HttpContext.Current.
MPavlak
3
Ich stimme voll und ganz zu, dass HttpContext.Currenteine Abhängigkeit eingeführt wird System.Web, die in selbst gehosteten Szenarien nicht verfügbar ist. Request.GetOwinContext()wird injiziert, wodurch die Testfähigkeit ermöglicht wird. Letzteres ist weder.
Chef_Code
6
Übrigens ... Request.GetOwinContext()ist im Microsoft.AspNet.WebApi.Owin-Nuget-Paket definiert
Chef_Code
Dies half mir, Ausnahmen zu vermeiden, die ausgelöst wurden, wenn ich sie verwenden würde HttpContext.Current.GetOwinContext(). Das ist viel besser.
Petrosmm
Stimmen Sie zu, dass dies die bessere Antwort ist, da potenzielle Ausnahmeprobleme vermieden werden HttpContext.Current. Sie können dann einfach schreiben Request?.GetOwinContext().
ScottB
6

Diese einzelne Codezeile hat mir den Tag gerettet ...

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

Sie können es innerhalb einer Controller-Aktion verwenden, um eine Instanz von UserManager abzurufen.

Mubsher Mughal
quelle