2013-06-25 65 views
7

我的WebAPI项目中有几个控制器使用了一项服务。该服务需要生成URL,因此最好通过构造函数参数获得UrlHelper使用Autofac将WebAPI UrlHelper注入服务

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

。即RegisterApiControllers(Assembly.GetExecutingAssembly())。PropertiesAutowired()。如果您使用此代码,则会失去自动装载合适的选项。 – 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; } 
} 

配置的WebAPI时将存储当前请求

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中,消息处理程序,添加消息处理程序。

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就像任何其他的依赖。

感谢Darrel将我指向正确的方向。

+8

我刚刚为HttpRequestMessage依赖注入添加了对Autofac.WebApi的支持,它将包含在下一个版本中。 https://code.google.com/p/autofac/source/detail?r=60d369499963b89224c1f682cfbf8592eae95342 –

+0

我不能让RegisterHttpRequestMessage工作然而这确实代码的自动装配API控制器性能不RegisterHttpRequestMessage工作任务 – Mick