Re: WebApi DependencyResolver problem

3,050 views
Skip to first unread message

Alex Meyer-Gleaves

unread,
Aug 8, 2012, 8:09:27 AM8/8/12
to aut...@googlegroups.com
This is the expected behaviour. Because the DI support in MVC and Web API are different the integrations have to take different approaches to managing per-request lifetime scopes.

When a request is made in Web API it asks the current IDependencyResolver to create a new IDependencyScope that the controller and its dependencies will be resolved from. When you call GlobalConfiguration.Configuration.DependencyResolver you will always be returned the AutofacWebApiDependencyResolver and not the AutofacWebApiDependencyScope instance it would return when asked to create a new dependency scope. The IDependencyScope interface is the equivalent of an Autofac nested lifetime scope.

In the MVC integration there is no dependency scope concept so this is implemented by creating an Autofac lifetime scope when the request begins and storing it in HttpContext.Current until the request ends (when it will be disposed). When you call DependencyResolver.Current.GetService in the MVC integration the call is redirected to the current request lifetime scope. There is no such mechanism for Web API and this is why calling GlobalConfiguration.Configuration.DependencyResolver does not have the same result.
 
You can access the "PerApiRequest" lifetime scope in Web API using the GetDependencyScope extension method on HttpRequestMessage. Obviously that means it can only be done when you have access to the HttpRequestMessage. Hopefully that clears things up for you.


On 5 August 2012 15:59, PhilipMat <goo...@poi1.com> wrote:
I'm running into a bit of a problem with the WebApi dependency resolver that the MVC one doesn't seem to be experiencing. I don't know how to summarize it, so here's the slightly longer version.

// registration code
builder.RegisterType<SessionFactory>().As<ISessionFactory>();
builder.RegisterType(c => c.Resolve<ISessionFactory>().OpenSession())
  .As<ISession>().InstancePerApiRequest();

DependencyResolver.SetResolver(new AufacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);

// within a controller
DependencyResolver.Current.GetService<ISession>(); // resolves properly
// but
GlobalConfiguration.Configuration.DependencyResolver
  .GetService(typeof(ISession)); 

throws a DependecyResolutionException with the message "No scope with a Tag matching 'AutofacWebRequest' is visible from the scope which the instance was requested."

The exception is thrown from within MatchingScopeLifetime.FindScope where mostNestedVisibleScope.Tag == "root" but the _matcher's lifetimeScopeTagToMatch is "AutofacWebRequest".

One thing I noticed is that normal resolution paths (i.e. via controller constructors) that find themselves into FindScope would have a mostNestedVisibleScope.Tag = "AutofacWebRequest", but GlobalConfig.DependencyResolver uses the lifetime scope from the original container, which has a Tag of "root" (no ParentLifetimeScopes).

I don't know if this is a bug or if I'm misusing the GlobalConfig DependencyResolver. If the former, let me know if you want me to file a bug report. If the later, I'd appreciate some advice on how to work around this problem.

Thank you!

--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To view this discussion on the web visit https://groups.google.com/d/msg/autofac/-/oMmwFE5uD80J.
To post to this group, send email to aut...@googlegroups.com.
To unsubscribe from this group, send email to autofac+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/autofac?hl=en.

Message has been deleted

Alex Meyer-Gleaves

unread,
Oct 17, 2012, 7:51:40 AM10/17/12
to aut...@googlegroups.com
You can get the request lifetime scope through an extension method I added to IDependencyScope:

var dependencyScope = actionContext.Request.GetDependencyScope();
var lifetimeScope = dependencyScope.GetRequestLifetimeScope();

Alternatively, take a look at the support for filters without attributes that I blogged about here:


Cheers,

Alex.

On 16 October 2012 08:25, <sap....@gmail.com> wrote:
Okay, so i have a BasicHttpAuthorizeAttribute .

This means users can post their authentication in the header of their http (which i will secure with ssl later on).

I'm trying to call ((Autofac.Integration.WebApi.AutofacWebApiDependencyResolver)GlobalConfiguration.Configuration.DependencyResolver).GetService(typeof(UserService
));
but as you mentioned before, this won't work (didn't knew though :))

How can i check if my users have a legimate user and password, if i can't access my IUserService methods when i'm in the following class ?

public class BasicHttpAuthorizeAttribute : System.Web.Http.AuthorizeAttribute
... 

Op woensdag 8 augustus 2012 14:09:27 UTC+2 schreef Alex Meyer-Gleaves het volgende:
To view this discussion on the web visit https://groups.google.com/d/msg/autofac/-/sONgnRnfppYJ.
Reply all
Reply to author
Forward
0 new messages