2013-11-05 8 views
58

È un progetto Web API 2.Come utilizzare il contenitore DI quando OwinStartup

Quando implemento DI utilizzando Ninject, ho ricevuto un messaggio di errore

Si è verificato un errore durante il tentativo di creare un controller di tipo 'TokenController'. Assicurarsi che il controller abbia un costruttore pubblico senza parametri.

[assembly: OwinStartup(typeof(Web.Startup))] 

namespace Web 
{ 
    public partial class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      ConfigureAuth(app); 
      ConfigureWebApi(app); 
     } 
    } 
} 

public class TokenController : ApiController 
{ 

    private IUserService _userService; 

    public TokenController(IUserService userService) 
    { 
     this._userService = userService; 
    } 

    [Route("api/Token")] 
    public HttpResponseMessage PostToken(UserViewModel model) 
    { 
     if (_userService.ValidateUser(model.Account, model.Password)) 
     { 
      ClaimsIdentity identity = new ClaimsIdentity(Startup.OAuthBearerOptions.AuthenticationType); 
      identity.AddClaim(new Claim(ClaimTypes.Name, model.Account)); 
      AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties()); 
      var currentUtc = new SystemClock().UtcNow; 
      ticket.Properties.IssuedUtc = currentUtc; 
      ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30)); 
      return new HttpResponseMessage(HttpStatusCode.OK) 
      { 
       Content = new ObjectContent<object>(new 
       { 
        UserName = model.Account, 
        AccessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket) 
       }, Configuration.Formatters.JsonFormatter) 
      }; 
     } 

     return new HttpResponseMessage(HttpStatusCode.BadRequest); 
    } 
} 

Quando aggiungo <add key="owin:AutomaticAppStartup" value="false" /> al web.config

Ninject funziona bene, ma Startup.OAuthBearerOptions.AccessTokenFormat diventa null

Come utilizzare il contenitore DI con OWIN?

UPDATE

Implementare IDependencyResolver e utilizzare il WebAPI Dipendenza Resolver come di seguito

public void ConfigureWebApi(IAppBuilder app) 
{ 
    HttpConfiguration config = new HttpConfiguration(); 

    config.DependencyResolver = new NinjectDependencyResolver(NinjectWebCommon.CreateKernel()); 

    app.UseWebApi(config); 
} 

NinjectDependencyResolver


Nel caso in cui l'iniettore semplice

public void ConfigureWebApi(IAppBuilder app) 
{ 
    HttpConfiguration config = new HttpConfiguration(); 

    var container = new Container(); 
    container.Register<IUserService, UserService>(); 
    config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container); 

    app.UseWebApi(config); 
} 

SimpleInjectorWebApiDependencyResolver

+0

C'è un motivo per cui non è possibile aggiungere un costruttore vuoto al controller? –

+0

@NikolaiSamteladze Ho già implementato la dipendenza inject nel costruttore vuoto, voglio solo sapere come usare il contenitore DI in questo caso –

+0

[C'è un progetto] (https://github.com/DotNetDoodle/DotNetDoodle.Owin.Dependencies) che fornisce questo supporto, ma forse dovrete scrivere da soli l'adattatore per ninject in quanto fornisce un'implementazione pronta all'uso solo per autofac. –

risposta

32

Si potrebbe voler dare un'occhiata a this blog post.

Sta usando Unity ma dovrebbe essere lo stesso.

In pratica, utilizzare il Resolver Dipendenza WebAPI. Assicurati che tutto sia mappato correttamente e dovrebbe andare bene.

Se dopo aver impostato il DI si ha ancora problemi con il token OAuth, fammi sapere.

Acclamazioni

+0

Uso il Resolver Dipendenza WebAPI e funziona, grazie per la risposta! –

2

Usiamo il pacchetto standard ninject.MVC5 installato con NuGet

PM> install-pacchetto ninject.MVC5

Poi configurare il nostro attacchi in questo modo.

kernel.Bind<IDbContext, DbContext>() 
    .To<BlogContext>() 
    .InRequestScope(); 

kernel.Bind<IUserStore<User>>() 
    .To<UserStore<User>>() 
    .InRequestScope(); 

kernel.Bind<IDataProtectionProvider>() 
    .To<DpapiDataProtectionProvider>() 
    .InRequestScope() 
    .WithConstructorArgument("ApplicationName"); 

kernel.Bind<ApplicationUserManager>().ToSelf().InRequestScope() 
    .WithPropertyValue("UserTokenProvider", 
     new DataProtectorTokenProvider<User>(
      kernel.Get<IDataProtectionProvider>().Create("EmailConfirmation") 
      )); 

Potrebbe essere necessario regolare in base a quanto è stato personalizzato il modello utente. Ad esempio il binding del negozio utente potrebbe essere qualcosa di simile.

kernel.Bind<IUserStore<User, int>>() 
     .To<IntUserStore>().InRequestScope(); 

Anche qualsiasi istituzione della mangiatoia utente si richiede cioè criteri di password può essere impostato nel gestore dell'utente costruttore.

In precedenza questo potrebbe essere trovato nel metodo di creazione nell'esempio, non sarà più necessario. anche ora puoi sbarazzarti delle chiamate di contesto di owin get dato che ninject gestirà la risoluzione per te.

+0

Ci sono state chatter che internamente alcune delle roba di Identity hanno dipendenze da OWIN (cioè, effettua chiamate a OwinContext.Get()). Hai mai visto stranezze o problemi legati a questo? – JasonCoder

+0

@JasonCoder Non è possibile dire che abbiamo riscontrato problemi, abbiamo utilizzato questa impostazione sui progetti in produzione da qualche tempo. – jps

17

Aggiornamento

Questo è ora più semplice grazie al pacchetto Nuget Ninject.Web.WebApi.OwinHost:

Startup.cs

using Ninject; 
using Ninject.Web.Common.OwinHost; 
using Ninject.Web.WebApi.OwinHost; 
using Owin; 
using System.Web.Http; 

namespace Xxx 
{ 
    public class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      var config = new HttpConfiguration(); 
      config.MapHttpAttributeRoutes(); 
      config.Routes.MapHttpRoute("DefaultApi", "myservice/{controller}/{id}", new { id = RouteParameter.Optional }); 

      app.UseNinjectMiddleware(CreateKernel); 
      app.UseNinjectWebApi(config); 
     } 
    } 
    public static IKernel CreateKernel() 
    { 
     var kernel = new StandardKernel(); 

     kernel.Bind<IMyService>().To<MyService>(); 
     return kernel; 
    } 
} 

Ho aggiornato il wiki di conseguenza .

https://github.com/ninject/Ninject.Web.Common/wiki/Setting-up-a-OWIN-WebApi-application

Tutte e tre le opzioni di hosting.

https://github.com/ninject/Ninject.Web.WebApi/wiki/Setting-up-an-mvc-webapi-application

+1

Ho provato questo per un semplice esempio di applicazione ospitata owin e funziona solo per la prima chiamata. Le chiamate successive portano all'errore: "Assicurati che il controller abbia un costruttore pubblico senza parametri.". Tutte le idee perché? –

Problemi correlati