Inject WebAPI UrlHelper into service using Autofac

后端 未结 3 1085
遇见更好的自我
遇见更好的自我 2021-02-14 18:10

I have a service used by a few controllers in my WebAPI project. The service needs to generate URLs, so ideally it would get a UrlHelper via a constructor parameter

相关标签:
3条回答
  • 2021-02-14 18:38

    Based on Darrel Miller's comment, I created the following:

    A simple container class to hold a reference to the "current" HttpRequestMessage

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

    A message handler that will store the current request

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

    In Global.asax, when configuring WebAPI, add the message handler.

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

    Then, configure the Autofac container to let it construct UrlHelper, getting the current request from the CurrentRequest object.

    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 can then be injected into the MyService just like any other dependency.

    Thanks to Darrel for pointing me in the right direction.

    0 讨论(0)
  • 2021-02-14 18:45

    Use the RegisterHttpRequestMessage method to register the current request and then you can also register the URL helper like so:

    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 讨论(0)
  • 2021-02-14 18:56

    Best I can think of is make your service implement IAutofacActionFilter like so

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

    and then use something like the following Autofac config

    builder.RegisterType<MyService>()
                     .AsWebApiActionFilterFor<SomeController>()
                     .AsSelf()
                     .InstancePerApiRequest();
    
    0 讨论(0)
提交回复
热议问题