2013-06-25 2 views
7

У меня есть служба, используемая несколькими контроллерами в моем проекте WebAPI. Сервис должен генерировать URL-адреса, поэтому в идеале он получит значение UrlHelper через параметр конструктора.Inject WebAPI UrlHelper в службу с использованием Autofac

public class MyService 
{ 
    public MyService(UrlHelper urlHelper) { ... } 
} 

Я использую Autofac в качестве контейнера IoC. Как я могу зарегистрировать UrlHelper в контейнере? Ему нужен HttpRequestMessage, и я не могу понять, как получить «текущее» сообщение.

+0

Взгляните на то, что мы работаем над для WebAPIBook, то есть одно из возможных решений к этой проблеме ... https://gist.github.com/glennblock/8f18bdee15eec9c1af70 –

+0

А, да, очень приятно. Я думал о создании обработчика сообщений, чтобы решить эту проблему. Я сделаю это. Благодарю. –

ответ

6

Используйте метод RegisterHttpRequestMessage зарегистрировать текущий запрос, а затем вы можете также зарегистрировать помощник URL вроде так:

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

автоматического связывания свойств контроллеров API не работает с RegisterHttpRequestMessage. то есть RegisterApiControllers (Assembly.GetExecutingAssembly()). PropertiesAutowired(). Если вы используете этот код, вы теряете возможность autwire properites. – Mick

0

Лучшее, что я могу думать о том, чтобы ваш сервис реализовать IAutofacActionFilter как так

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

, а затем использовать что-то вроде следующего Autofac конфигурации

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

Основываясь на комментарий Даррелл Миллера, я создал следующие :

Простой класс контейнера для хранения ссылки на «текущий» HttpRequestMessage

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

обработчик сообщений, который будет хранить текущий запрос

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

В Global.asax, при настройке WebAPI, добавьте обработчик сообщений.

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

Затем настроить контейнер Autofac, чтобы это построить UrlHelper, получить текущий запрос от 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 затем может быть введен в MyService так же, как и любой другой зависимости.

Спасибо Даррел за то, что указали мне в правильном направлении.

+8

Я только что добавил поддержку инъекции зависимостей HttpRequestMessage к Autofac.WebApi, и он будет включен в следующий выпуск. https://code.google.com/p/autofac/source/detail?r=60d369499963b89224c1f682cfbf8592eae95342 –

+0

Я не мог заставить RegisterHttpRequestMessage работать, однако этот код сделал работу – Mick