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?


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>>();

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

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.