I'm trying to use depedency resolver inside a Web Api method. This worked fine and works fine with classic ASP.NET MVC with the DepedencyResolver.GetService()
But I can't get this to work inside WepApi methods.
My registration register all instances as InstancePerApiRequest and if I add any of all the types I have registred in my bootstrapper on the constructor of my WebAPiConroller thay inject fine but not anymore when calling them inside.
Like this in my say Get Method
var userRepository = (IUserRepositoryu)GlobalConfiguration
.Configuration.DependencyResolver.GetService(typeof(IUserRepository));
I got the no scope WebRequest error. The strange thing is that it worked fine in Beta before they change it all to the GlobalConfiguration.
So my question is, how can I activate my Autofac registered assemblies in the lifetime scope of my webAPi as before?
My error:
"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 reqested 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."
var resolver = new AutofacWebApiDependencyResolver(container);
configuration.DependencyResolver = resolver;
In Web API the global dependency resolver is used to access global instances. Per-request services come from a dependency scope that Web API creates to handle the request. I'm not sure that there is any way in Web API to access the current dependency scope - it would be interesting to know.
The best option here is to just use dependency injection rather than calling the resolver directly like this. Which part of your code needs to make this call?
AutoFac has integration with ASP.NET WebAPI consider to use it.
Also dependecy resolver for WebAPi is slightly different to ASP.NET MVC, so make shure, that you have implemented resolver suitable for WebAPI and added it to WebAPI configuration.
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
As the error indicated, you must always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime. The correct way is getting the dependency from current web api request:
// Get the request lifetime scope so you can resolve services.
var requestScope = Request.GetDependencyScope();
// Resolve the service you want to use.
var userRepository = requestScope.GetService(typeof(IUserRepository)) as IUserRepository;
See more from Autofac offical documentations:
http://docs.autofac.org/en/latest/integration/webapi.html#standard-web-api-filter-attributes-are-singletons
Related
In a OWIN Web API method you can get the current scope within a Web API method like so...
public IHttpActionResult GetTaxRate()
{
var scope = Request.GetOwinContext().GetAutofacLifetimeScope();
ISomething mySomething = scope.Resolve<ISomething>();
Is there anyway to get the current scope through a static method instead of a member on the ApiController?
In short: Nope.
Autofac puts its request scope in the OWIN context so it can be shared across middleware components, so the question of how to access the Autofac-specific scope from an OWIN context is more a question of "How do you get the OWIN context?" OWIN doesn't have a static mechanism like HttpContext, so you're stuck there. That's not an Autofac issue, that's the design of OWIN.
Web API in particular also doesn't have a static notion of something like HttpContext. That's a Web API restriction, not an Autofac restriction. The request scope (and other request context things) in Web API flows with the request message. There's some Autofac-specific doc on this here but, again, this isn't an Autofac-specific issue - it's the design of Web API.
i try to configure my NServiceBus for a WebApi. I've tried this one: https://coderkarl.wordpress.com/2012/03/16/injecting-nservicebus-into-asp-net-webapi/
The Problem is the Syntax has been changed in the newest NServiceBus-Versin. I can't use the Functions for the Configure-Class because they will be removed in further Versions. The new way to configure the Bus is using the BusConfiguration-Class but i have no idea how.
Here is the older Code:
public static Configure ForWebApi(this Configure configure)
{
// Register our http controller activator with NSB
configure.Configurer.RegisterSingleton(typeof(IHttpControllerActivator),
new NSBHttpControllerActivator());
// Find every http controller class so that we can register it
var controllers = Configure.TypesToScan
.Where(t => typeof(IHttpController).IsAssignableFrom(t));
// Register each http controller class with the NServiceBus container
foreach (Type type in controllers)
configure.Configurer.ConfigureComponent(type, ComponentCallModelEnum.Singlecall);
// Set the WebApi dependency resolver to use our resolver
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NServiceBusResolverAdapter(configure.Builder));
// Required by the fluent configuration semantics
return configure;
}
And Application_Start():
AreaRegistration.RegisterAllAreas();
// Use LocalDB for Entity Framework by default
Database.DefaultConnectionFactory = new SqlConnectionFactory("Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True");
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
Configure.WithWeb()
.DefaultBuilder()
.ForWebApi() // <------ here is the line that registers it
.Log4Net()
.XmlSerializer()
.MsmqTransport()
.IsTransactional(false)
.PurgeOnStartup(false)
.UnicastBus()
.ImpersonateSender(false)
.CreateBus()
.Start();
Does someone has managed it for the NServiceBus Version 5?
As wlabaj says, the documentation on the particular website says it all. Almost.
We use AutoFac so we don't need any direct reference to IBus or ISendOnlyBus and therefor we do this
ContainerBuilder builder = new ContainerBuilder();
var container = builder.Build();
configuration.UseContainer<AutofacBuilder>(x => x.ExistingLifetimeScope(container));
What we do in WebAPI and ASP.NET applications is this
NServiceBus.Bus.CreateSendOnly(configuration);
Because it's not a good practice to expect reply messages to come back after sending them.
Here you can see 3.0 vs 4.0 vs 5.0 configuration syntax. At the top of the page you have a link to download code samples.
The examples are for ASP .NET though, so you'll need to tweak it slightly for WebAPI. Let me know if you need further help with that.
ForWebApi was never a part of NServiceBus, this was an extension method from the sample that was used to configure NServiceBus dependency resolver to instantiate controllers. The way how it was done is shown here.
There is no need to use NServiceBus resolver since it is just a wrapper around another container. By default it uses Autofac, so you can just use Autofac to work for you in the whole application.
Autofac WebAPI integration is properly described in the documentation.
NServiceBus documentation has a page about using your own container.
This is a very well known setup that you can easily implement.
I am quite sure I am missing a very basic and simple thing here.
I am using Autofac and it's multitenant container as below
var builder = new ContainerBuilder();
// Registratino of modules here
var container = builder.Build();
var tenantStrategy = new AppSettingsTenantIdentifier(appSettings);
var mtc = new MultitenantContainer(tenantStrategy, container);
//Registration of tenant specific modules here
var resolver = new AutofacWebApiDependencyResolver(mtc);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
This is called from Application_Start. After above is called, I try to resolved one of the registered classes as below
var webApiConfig = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof (WebApiConfig)) as WebApiConfig;
One of the dependencies on this class is registered as InstancePerAPiRequest. At this point I get following error.
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.
I am not sure how can I fix this. I Know that I can create a new lifetime scope with tag AutofacWebRequest and then resolve using that lifetime scope but that does not look right to me.
If you register something as InstancePerRequest or InstancePerApiRequest then you can't resolve it outside of a request.
If you need to resolve a dependency outside of a request lifetime (outside an actual API request), choose a different lifetime for it. InstancePerLifetimeScope is very close to InstancePerApiRequest and will work on a per-request basis, too.
But be careful: If you resolve something outside a request from the container and it is IDisposable then the object will stick around for the lifetime of the application because Autofac will hold onto it and try to dispose it for you. If you're unaware of the behavior, this can be a slow memory leak. You can read more about that on the Autofac wiki.
I added ASP.NET Web API RC to my MVC3 project using NuGet:
Install-Package AspNetWebApi
Then I configured it. In Global.asax.cs:
// configure regular controllers
var configuration = GlobalConfiguration.Configuration;
var container = Bootstrapper.ConfigureContainer(configuration);
containterProvider = new ContainerProvider(container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Set the dependency resolver implementation for Web API.
var resolver = new AutofacWebApiDependencyResolver(container);
configuration.DependencyResolver = resolver;
And in Boostrapper.ConfigureContainer(...) I added:
// I register my types as InstancePerLifetimeScope()
// but I also tried .InstancePerHttpRequest().InstancePerApiRequest()
// to the same end
builder.RegisterType<SomeService>()
.AsImplementedInterfaces().InstancePerLifetimeScope();
// Register API controllers using assembly scanning.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterWebApiFilterProvider(config);
This is described here and here.
I also updated Autofac, Autofac.Web, Autofac.Mvc3 packages using NuGet and installed Autofac.WebApi package.
With this configuration I tried running my ApiController and got the following error:
No scope with a Tag matching 'httpRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested 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.
Then as I read this comment from Alex Meyer-Gleaves:
I suspect you are using the Web API package with MVC3 and this is causing the problem. In the MVC3 integration the tag for the InstancePerHttpRequest lifetime scope was "httpRequest". It was in the MVC4 Beta and Web API Beta packages that I changed both InstancePerHttpRequest and InstancePerApiRequest to use the common tag "AutofacWebRequest". You can grab the MVC4 integration package from NuGet using Autofac.Mvc4.
source article with comment
So following the advice from Alex I got the package Autofac.Mvc4 but it works only with Mvc4 and my project wouldn't build. I then grabbed the source code of Autofac to build Autofac.Mvc4 against Mvc3:
hg clone https://code.google.com/p/autofac/ --branch "MVC4 beta" C:\my\path
After using this assembly as my reference ApiController started working but regular Controllers worked ok only for a single controller action call. When the view called Html.RenderAction(...) and when I refresh or navigate to another controller action it crashes with this error:
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 reqested 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.
I thought building from the newest source for Autofac.Mvc4 version 2.6.2.859 against Mvc3 could help but I can't find the source for that. Or maybe there's something else wrong in here?
I found the problem. I also used Autofac.Integration.Web to inject dependencies into custom Membership and Role providers. But in WebLiftime.cs there was this line:
public static readonly object Request = "httpRequest";
Once I changed it to:
public static readonly object Request = "AutofacWebRequest";
and used the built assembly everything works fine and I get no errors :)
I believe this constant value should the same as in all projects Autofac.Integration.Web, Autofac.Integration.Mvc and 'Autofac.Integration.WebApi for Mvc4 so this supposedly is a bug.
Having a hard time trying to setup AutoFac with some async non httprequest.
I have the following on App_Start
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<sfEntities>().As<IUnitOfWork>().InstancePerHttpRequest();
builder.RegisterGeneric(typeof(sfRepository<>)).As(typeof(IRepository<>)).InstancePerHttpRequest();
builder.RegisterGeneric(typeof(BaseServices<>)).As(typeof(IBaseServices<>)).InstancePerHttpRequest();
builder.RegisterType<EmailServices>().As<IEmailServices>().InstancePerHttpRequest();
builder.RegisterType<UserServices>().As<IUserServices>().InstancePerHttpRequest();
builder.RegisterType<ChatServices>().As<IChatServices>().InstancePerHttpRequest();
builder.RegisterType<DefaultFormsAuthentication>();
builder.RegisterType<WebSecurity>();
builder.RegisterType<Chat>();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
If I change to InstancePerLifetimeScope() I get problems with UnitofWork.SaveChanges(). Setup this way works fine except for async calls.
p.s.: UnitOfWork pass the EF DbContext between services to ensure that the same instance is used and to dispose properly. If I change to InstancePerLifetimeScope I was getting identity conflicts when calling .SaveChanges(), probably because there should be more than one instance of UnitOfWork.
The following code throws the following exception:
Timer timer = new Timer(new TimerCallback(OnTimer), null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
private static void OnTimer(object o)
{
using (var timerScope = AutofacDependencyResolver.Current.ApplicationContainer.BeginLifetimeScope())
{
var chatServices = timerScope.Resolve<IChatServices>();
chatServices.MarkInactiveUsers();
}
}
No scope with a Tag matching 'httpRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested 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.
On SignalR, the following code throws the following exception:
SignalR.GlobalHost.DependencyResolver.Register(typeof(Chat), () => new Chat(DependencyResolver.Current.GetService<IUnitOfWork>(), DependencyResolver.Current.GetService<IChatServices>(), DependencyResolver.Current.GetService<IUserServices>()));
The request lifetime scope cannot be created because the HttpContext is not available
Thanks in advance!
Having a hard time trying to setup AutoFac with some async non httprequest.
For non-http requests, or more specifically, for non-ASP.NET pipeline requests (like WCF or ServiceStack), you should definitely change all InstancePerHttpRequest() code to InstancePerLifetimeScope(). You can and should do this because InstancePerLifetimeScope() will make it resolvable in both ASP.NET pipeline and non-ASP.NET pipeline contexts.
If I change to InstancePerLifetimeScope() I get problems with UnitofWork.SaveChanges(). Setup this way works fine except for async calls... If I change to InstancePerLifetimeScope I was getting identity conflicts when calling .SaveChanges(), probably because there should be more than one instance of UnitOfWork.
Yes, there should be more than one instance of UnitOfWork, but you can achieve that with a single registration that should be scoped to InstancePerLifetimeScope():
Example:
builder.RegisterType<NhUnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
The IChatServices service is registered as InstancePerHttpRequest and will therefore only be available within the http request lifetime scope. You are resolving from the application scope which have no "access" to the current request and therefore fail with the error you mention. So yes, to get the timer to work you must register the service in the application scope.
Basically, you can have request scoped services that access application scoped services, but not the other way around.
Question is: what is UnitOfWork.SaveChanges do and what "problems" do you get? Please elaborate.