The request lifetime scope cannot be created because the HttpContext is not available - asp.net-mvc-3

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.

Related

How to reload appsettings.json at runtime each time it changes in .NET core 1.1 console application?

I attempted to reproduce the method described in this great article by Andrew Lock. However, I am unable to get this running in a .NET core 1.1 console application. When the appsettings.json file is changed and saved, the changes are not reflected in the application without restarting it.
There are multiple files involved, so I created the smallest example I could come up on github. I also provided details in the README.MD file on github.
Any help in resolving this would be most appreciated. Please keep in mind I am new to .NET core, and not an experienced developer. And this is my first question on stackoverflow... Thanks in advance!
The key thing to understand is scope.
There are three scopes in ASP.NET Core - transient, scoped, and singleton. IOptionsSnapshot is configured as a scoped service.
In ASP.NET Core, a scope is started for every request, so every request, you would get a new instance of IOptionsSnapshot, with updated configuration values.
In the example you provided, you are creating an IServiceProvider, and are fetching an instance of IMyService directly from the top level provider:
IServiceCollection services = new ServiceCollection();
Startup startup = new Startup();
startup.ConfigureServices(services);
IServiceProvider serviceProvider = services.BuildServiceProvider();
while (true)
{
var service = serviceProvider.GetService<IMyService>();
var reply = service.DoSomething();
Console.WriteLine(reply);
}
Essentially, you're always using the same scope for every request to the service provider, so you're always getting the same instance of IOptionsSnapshot. Effectively, if you never create a new scope, all of your scoped services become singletons!
The way to fix this is to create a new scope each time you fetch the service:
IServiceCollection services = new ServiceCollection();
Startup startup = new Startup();
startup.ConfigureServices(services);
IServiceProvider serviceProvider = services.BuildServiceProvider();
while (true)
{
using (var scope = serviceProvider.CreateScope())
{
var service = scope.ServiceProvider.GetService<IMyService>();
var reply = service.DoSomething();
Console.WriteLine(reply);
}
}
This also becomes important if you're doing things like creating an EF Core DbContext outside the context of a request in ASP.NET Core app (or in a console app). Always create a new scope before accessing services from the service provider!
P.S. I've created a pull request to fix your sample :)

Autofac WebApi integration not working with MultiTenant Container

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.

ASP .Net 4 Web Api RC + Autofac manual resolving

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

HttpContext is null when calling Ninject outside of an MVC3 controller

this question Ninject Dependency Injection in MVC3 - Outside of a Controller is close to what I'm experiencing, but not quite.
I have an ASP.NET MVC3 site using Ninject 3 and it works wonderfully with constructor injection. All my dependencies are resolved, including those that pass in HttpContext.Current.
My issue is that in global.asax, I kick off a TaskManager class that periodically performs some tasks on a timer. Inside the TaskManager class, I don't have controllers, so if I need access to one of my dependencies (like my error logging service), I use a static wrapper class that has access to the kernel object:
var logger = MyContainer.Get<ILoggingService>();
logger.Error("error doing something...", ex);
The .Get method simply performs a kernel.Get call resolve my dependency. Works great every time I use this method on my other dependencies. However, ILoggingService has a dependency called MyWebHelper that is injected via it's constructor and includes HttpContext in it's constructor.
public class DefaultLogger : ILoggingService
{
public DefaultLogger(IRepository<Log> logRepository, IWebHelper webHelper)
{
_logRepository = logRepository;
_webHelper = webHelper;
}
}
public class MyWebHelper : IWebHelper
{
public MyWebHelper(HttpContext httpContext)
{
_httpContext = httpContext;
}
}
In the rest of my web site, this all works just fine because all the dependencies are injected into my MVC controllers. But what doesn't work is if I manually call my static wrapper class to get my dependencies that way. I get the error:
Error activating HttpContext using binding from HttpContext to method
Provider returned null.
So, it's not giving me an HttpContext like it does throughout the rest of my MVC application. I hope this makes sense, I'm not a ninject expert yet, but I'm trying...
My issue is that in global.asax, I kick off a TaskManager class that
periodically performs some tasks on a timer.
That's a bad idea as Phil Haack explains in details. Don't do this in your web application. Those recurring tasks should be done in a separate application (Windows Service or some console application which is scheduled to run at regular intervals).
Now the thing is that you are running background threads. Those background threads run outside of any user HTTP request and as a consequence HttpContext.Current is obviously null inside them. So even if you don't follow Phil Haack's advice and continue running background tasks in your ASP.NET application you will have to rearchitecture your method so that it no longer depends on any HttpContext because there's no such thing in those background threads.

MVC3 Action Filter Using Database (EF 4.1 DBContext, Ninject)

I'm trying to setup an 'Authorization' Filter on an Action, creating my own ActionFilterAttribute where I do a database lookup to determine if a user has access to a certain resource.
On my class inheriting from ActionFilterAttribute, I have created an Injected(Ninject) property to hold the service that I am using for the database access. I have a parameterless constructor so that I can use this as an attribute on my actions. In the 'OnActionExecuting' Method, I am able to gain access to the Injected property (it's not null), but the base DBCotext that it is using is closed.
This working fine, up until the RTM of MVC3, where the Release Notes stated:
Breaking Changes:
In previous versions of ASP.NET MVC, action filters are create per
request except in a few cases. This
behavior was never a guaranteed
behavior but merely an implementation
detail and the contract for filters
was to consider them stateless. In
ASP.NET MVC 3, filters are cached more
aggressively. Therefore, any custom
action filters which improperly store
instance state might be broken.
The first time I use this filter, it works as expected, but if I refresh the page or another user access this filter, I get the error:
The operation cannot be completed
because the DbContext has been
disposed.
which is what I guess I should expect given the breaking changes notes.
My question is this, what would be the preferred/recommended way of accomplishing what I need to do? Should this be in an ActionFilterAttribute, or should this 'authorization' be done somewhere else?
I'd do authentication in Application_AuthenticateRequest and authorization in your attribute using Thread.CurrentPrincipal, but your method should work too. You just need to count with fact that DbContext will be different for each request but your attribute won't. Something like this should do the trick (I'm assuming you are using DependencyResolver):
public class MyMightyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var context = (DbContext)DependencyResolver.Current.GetService(typeof(DbContext))
// authenticate, authorize, whatever
base.OnActionExecuting(filterContext);
}
}
I have been battling with this for a while and finally solved my problem. So here is my solution in the hope it may help someone else.
The setup:
1. I have an MVC3 project, a custom action filter that accesses the db using EF5 via a business service.
2. I use Unity and unity.MVC to resolve my dependencies on a per request basis.
3. I use property injection into my custom Action filter, as it has a parameterless constructor.
The result.
Dependency injection works correctly for all the services used by actions, my EF DbContext is correctly disposed of at the end of each request.
The Problem
Although my property dependency is resolved in my custom action filter, it contains a stale instance of my DbContext (e.g. it seems to have been cached from the previous request)
As mentioned in previous posts, MVC3 is more aggressive with filter caching and the state of a filter cannot be relied on. So the suggestion was to resolve the dependency in the OnActionExecuting method. So I removed my injected property and did just that called resolve on my unity container. However I still got a stale version of the DbContext. Any changes in the DB were correctly queried in my main actions, but the custom action filter didn’t pick them up.
The solution.
Unity.MVC Manages per-request lifetime by using child containers and disposing these at the end of each request. By resolving my dependency’s in the action filter from my unity container I was resolving from the parent container which is not disposed of on each request.
So rather than
IoC.Instance.CurrentContainer.Resolve<IService>();
I used this to obtain an instance of the child container rather than parent.
var childContainer = HttpContext.Current.Items["perRequestContainer"] as IUnityContainer;
var service = childContainer.Resolve<IServcie>();
I'm sure there must be a clean way to achive the same result, so please add suggestions.
Ok slight refinement to allow my unit test to inject a mock of the service.
1. remove the dependency resolve from the the OnActionexecuting and add two constructors.
public MyCustomActionfilter() : this(((IUnityContainer)HttpContext.Current.Items["perRequestContainer"].Resolve<IService>())
and
public MyCustomActionfilter(IService service)
{
this.service = service;
}
Now the constructor resolves your service and stores it as a private readonly. This can now be consumed in your OnActionExecutng function. Unit tests can now call the second constructor and inject a mock.

Resources