将config.DependencyResolver.GetService(typeof(IUserService))作为IUserService进行的Autofac.Core.DependencyResolutionException

时间:2014-01-28 21:58:07

标签: asp.net-web-api autofac

我需要在我的身份验证处理程序中获取IUserService类型的已注册实例。

// Register services

// Build the container.
 var containr = builder.Build();
 var resolver = new AutofacWebApiDependencyResolver(container);
 configuration.DependencyResolver = resolver;

当我现在运行这行代码时:

var userService = configuration.DependencyResolver.GetService(typeof (IUserService)) as IUserService;

我得到了这个例外:

   An exception of type 'Autofac.Core.DependencyResolutionException' occurred in Autofac.dll but was not handled in user code

    Additional information: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.

我不想手动创建用户服务,因为我必须手动解决依赖类...

当我不在请求中时,如何获得某项服务? Dependency.Resolver未知/无法解决以某种方式使用它。

更新

我现在将服务注册更改为:

  builder.RegisterType<UserService>()
                   .As<IUserService>()
                   .WithParameter(namedParameter)
                   .InstancePerLifetimeScope();

而不是InstancePerRequestApi()

并解决用户服务:

var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;

            var bla = resolver.GetRootLifetimeScope();
            IUserService userService = bla.Resolve<IUserService>(); // Woot!

这有效,但我以前的InstancePerApiRequest怎么样?我也想保留它!

更新

public static void Register(HttpSelfHostConfiguration config)
        {
            config.MapHttpAttributeRoutes();

            var resolver = (AutofacWebApiDependencyResolver)config.DependencyResolver;

            var scope = resolver.GetRootLifetimeScope();
            var userService = scope.Resolve<IUserService>();
            scope.Dispose();

            var authenticationHandler = new AuthenticationHandler(userService);
            var tokenHandler = new TokenHandler();

            config.MessageHandlers.Add(new HttpsHandler());
            config.MessageHandlers.Add(new AllowCommonVerbsHandler());
            config.MessageHandlers.Add(authenticationHandler);
            config.MessageHandlers.Add(tokenHandler);

            config.Routes.MapHttpRoute(
                name: "Authentication",
                routeTemplate: "api/users/{id}",
                defaults: new { controller = "users", id = RouteParameter.Optional },
                constraints: null,
                handler: authenticationHandler // Put this handler later on the DefaultApi
            );
            config.Routes.MapHttpRoute(
               name: "TokenApi",
               routeTemplate: "api/{controller}/{id}",
               defaults: new { id = RouteParameter.Optional },
               constraints: null,
               handler: tokenHandler
               );
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { controller = "Home", action = "Start" }
                );

            var jsonFormatter = new JsonMediaTypeFormatter();
            config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
        }

2 个答案:

答案 0 :(得分:1)

我假设您的身份验证处理程序是DelegatingHandler。如果是这种情况,您可以使用以下代码访问当前请求的生命周期范围:

var scope = request.GetDependencyScope();
var requestScope = scope.GetRequestLifetimeScope();

在上面的代码request中,HttpRequestMessage实例传递给SendAsync的{​​{1}}方法。

在这种情况下,您将无法拥有构造函数依赖项。在DelegatingHandler方法内部,使用上面提供的代码在需要使用时解析SendAsync实例。

要为处理程序创建测试,您需要模拟Web API依赖范围。

IUserService

请参阅var builder = new ContainerBuilder(); // Configure container for test. var container = builder.Build(); var request = new HttpRequestMessage(); var lifetimeScope = container.BeginLifetimeScope(AutofacWebApiDependencyResolver.ApiRequestTag); var scope = new AutofacWebApiDependencyScope(lifetimeScope); request.Properties.Add(HttpPropertyKeys.DependencyScope, scope); 了解如何对HttpMessageInvoker进行单元测试。

http://nerditorium.danielauger.com/blog/2013/02/05/unit-testing-a-webapi-delegatinghandler-with-a-dependencyscope-via-an-httpmessageinvoker/

答案 1 :(得分:0)

我认为您在使用IRepository时创建类的对象时可能忘记添加readonly,或者在声明构造函数之前可能忘记了访问修饰符。希望这对你有帮助。