2013-06-25 5 views
7

J'ai un service utilisé par quelques contrôleurs dans mon projet WebAPI. Le service doit générer des URL, donc idéalement il obtiendrait un UrlHelper via un paramètre constructeur. J'utilise Autofac comme conteneur IoC. Comment puis-je enregistrer UrlHelper dans le conteneur? Il a besoin d'un HttpRequestMessage et je n'arrive pas à comprendre comment obtenir le message "courant".Injecter WebAPI UrlHelper en service avec Autofac

+0

Jetez un oeil à ce que nous avons travaillé sur le WebAPIBook, il a une solution possible à ce problème ... https://gist.github.com/glennblock/8f18bdee15eec9c1af70 –

+0

Ah, oui, très bien. Je pensais à créer un gestionnaire de messages pour résoudre ce problème :) Je vais essayer. Merci. –

Répondre

6

Utilisez la méthode RegisterHttpRequestMessage pour enregistrer la demande actuelle et vous pouvez également enregistrer l'assistant d'URL comme ceci:

public static IContainer SetupContainer(HttpConfiguration config) 
{ 
    var containerBuilder = new ContainerBuilder(); 

    // Register your Web API. 
    containerBuilder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 
    containerBuilder.RegisterHttpRequestMessage(config); 
    containerBuilder.Register(x => new UrlHelper(x.Resolve<HttpRequestMessage>())); 
    containerBuilder.RegisterWebApiFilterProvider(config); 
    containerBuilder.RegisterWebApiModelBinderProvider(); 

    // Register your other types... 

    var container = containerBuilder.Build(); 

    // Set the dependency resolver to be Autofac. 
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container); 

    return container; 
} 
+0

Autowiring les propriétés des contrôleurs api ne fonctionne pas avec RegisterHttpRequestMessage. c'est-à-dire RegisterApiControllers (Assembly.GetExecutingAssembly()). PropertiesAutowired(). Si vous utilisez ce code, vous perdez l'option d'autofonction des sites. – Mick

0

mieux que je peux penser est de rendre votre service mise en œuvre IAutofacActionFilter comme si

public class MyService : IAutofacActionFilter 
    { 
     private UrlHelper _urlHelper; 

     public void DoSomething() 
     { 
      var link = Url.Link("SomeRoute", new {}); 
     } 

     private UrlHelper Url 
     { 
      get 
      { 
       if(_urlHelper == null) 
        throw new InvalidOperationException(); 

       return _urlHelper; 
      } 
     } 

     public void OnActionExecuted(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext) 
     {    
     } 

     public void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) 
     { 
      this._urlHelper = actionContext.Request.GetUrlHelper(); 
     } 
    } 

puis utiliser quelque chose comme la config Autofac suivante

builder.RegisterType<MyService>() 
       .AsWebApiActionFilterFor<SomeController>() 
       .AsSelf() 
       .InstancePerApiRequest(); 
4

Basé sur le commentaire de Darrel Miller, j'ai créé ce qui suit :

Une classe de conteneur simple pour contenir une référence au "courant" HttpRequestMessage

public class CurrentRequest 
{ 
    public HttpRequestMessage Value { get; set; } 
} 

Un gestionnaire de messages qui stockera la demande actuelle

public class CurrentRequestHandler : DelegatingHandler 
{ 
    protected async override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
    { 
     var scope = request.GetDependencyScope(); 
     var currentRequest = (CurrentRequest)scope.GetService(typeof(CurrentRequest)); 
     currentRequest.Value = request; 
     return await base.SendAsync(request, cancellationToken); 
    } 
} 

En Global.asax, lors de la configuration WebAPI, ajoutez le gestionnaire de messages.

GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new CurrentRequestHandler()); 

Configurez ensuite le conteneur Autofac pour le laisser construire UrlHelper, obtenir la demande actuelle de l'objet CurrentRequest.

var builder = new ContainerBuilder(); 
builder.RegisterType<CurrentRequest>().InstancePerApiRequest(); 
builder.Register(c => new UrlHelper(c.Resolve<CurrentRequest>().Value)); 
builder.RegisterType<MyService>(); 
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 
... 
container = builder.Build(); 

UrlHelper peut alors être injecté dans le MyService comme toute autre dépendance.

Merci à Darrel de m'avoir orienté dans la bonne direction.

+8

Je viens d'ajouter le support de l'injection de dépendance HttpRequestMessage à Autofac.WebApi et il sera inclus dans la prochaine version. https://code.google.com/p/autofac/source/detail?r=60d369499963b89224c1f682cfbf8592eae95342 –

+0

Je ne pouvais pas travailler RegisterHttpRequestMessage mais ce code fait le travail – Mick

Questions connexes