使用Autofac将WebAPI UrlHelper注入服务

时间:2013-06-25 09:57:24

标签: c# asp.net-web-api autofac

我的WebAPI项目中的一些控制器使用了一项服务。该服务需要生成URL,因此理想情况下它将通过构造函数参数获得UrlHelper

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

我正在使用Autofac作为我的IoC容器。如何在容器中注册UrlHelper?它需要HttpRequestMessage,我无法弄清楚如何获取“当前”消息。

3 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:4)

根据Darrel Miller的评论,我创建了以下内容:

一个简单的容器类,用于保存对“当前”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

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

答案 2 :(得分: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();