Moving Code logic from Autofac.integration.mvc to Autofac.integration.webapi - autofac

We are creating the ContainerManger which will be used by Application Engine while resolving the dependency in WebAPI. We have below mention code for fetching the current scope,considering autofac integration MVC framework
/// <summary>
/// Get current scope
/// </summary>
/// <returns>Scope</returns>
public virtual ILifetimeScope Scope()
{
try
{
if (HttpContext.Current != null)
return AutofacDependencyResolver.Current.RequestLifetimeScope;
//when such lifetime scope is returned, you should be sure that it'll be disposed once used (e.g. in schedule tasks)
return Container.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag);
}
catch (Exception)
{
//we can get an exception here if RequestLifetimeScope is already disposed
//for example, requested in or after "Application_EndRequest" handler
//but note that usually it should never happen
//when such lifetime scope is returned, you should be sure that it'll be disposed once used (e.g. in schedule tasks)
return Container.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag);
}
}
wanted to convert it to autofac integration WebAPI framework so that same logic can be used in webapi. if you check the above code you will find AutofacDependencyResolver from autoface.integration.mvc is being used. As WebAPI is Stateless httpContext will be not available for REST API.
Can any body suggest what is the right thing to do for getting the Current Scope in the WebAPI when scope is not provided while resolving the dependency in Web API based service.
Any guidance or sample would be appreciated.

I think it's :
if (HttpContext.Current != null)
return GlobalConfiguration.Configuration.DependencyResolver.GetRequestLifetimeScope();

Related

Blazor Server App and IDbContextFactory not disposing

I have a blazor server application that needs to indirectly connect to a EF core DB context.
None of the blazor components will directly inject an instance of the dbcontext. I am using mediator which will handle all business operations.
The documentation that I have seen so far recommends using IDbContextFactory. I gave it a try but I am not seeing the DbContext created by the factory being disposed. The services that inject IDbContext are not disposed on page changes nor at any other time.
public class QueryHandler : IQueryHandler<Query, Entity>, IDisposable
{
private readonly DbContext dbContext;
public QueryHandler(IDbContextFactory factory)
{
dbContext = factory.CreateDbContext();
}
public Task Handle(Query query)
{
/// do whatever needs to be done.
}
public void Dispose()
{
dbContext.Dispose(); // <-- Dispose never gets called.
}
}
Am I missing something?
The purpose of using a DbContextFactory is to have a DbContext per method.
Exactly because Blazor doesn't offer useful Scopes to handle this.
public class QueryHandler : IQueryHandler<Query, Entity> //, IDisposable
{
...
public QueryHandler(IDbContextFactory factory)
{
_factory = factory;
}
public Task Handle(Query query)
{
using var dbContext = _factory.CreateDbContext();
/// do whatever needs to be done.
}
//public void Dispose() { }
}
This way the DI container and Factory only manage the configuration of the DbContext. Lifecycle management of the DbContext is manual. The Factory is a simple Transient object, is owns no resources.
Manual management usually is with a using statement or using declaration but Blazor also offers an OwningComponentBase. I don't see it being used much.
In Server the DI container exists for the lifetime of the Hub Session and in WASM the lifetime of the Application. Any service objects created within the container, whether Scoped or Transient, implementing IDisposable, are not Disposed until the DI container itself is destroyed. You don't make clear the scope of QueryHandler, but if it's transient that's bad news. You will keep creating new DBContexts without the old ones being disposed.
The purpose of the DbContextFactory is to create unit of work DbContext instances that are used and then quickly disposed correctly. You need to take this approach because DB access will almost certainly be asynchronous. Use a single context and you will quickly hit the situation where you are awaiting one query to complete while trying to use the same context in another operation.
Henk's answer shows you how to use and consume factory created contexts.

How to inject dbcontext with StructureMap and WebApi2

I would like to inject my dbcontext into my services in web api 2 project. But I’m a little unsure of how to do that. I've read through the docs but lifecycles, scopes, requests, nested containers...they all leave me a little unsure. I have pieced together the following code from my best understanding. After installing the Nuget package StructureMap.WebApi2, I proceeded to update SM from v3 to v4, as well as the SM.MVC5 from v3 to v4.
The following code appears to have the desired effect of using one dbcontext per http request (I think that's what i want...i'm so confused about scopes) so that the same dbcontext is shared for all services during a users transaction, and then disposed when the transaction (http request) is closed. But appearances are not always right.
IoC.cs
public static IContainer Initialize()
{
var container = new Container(_ =>
{
_.AddRegistry<DefaultRegistry>();
_.ForConcreteType<MyDbContext>().Configure.ContainerScoped();
});
DomainEvents.Initialize(container);
return container;
}}
DefaultRegistry.cs:
public DefaultRegistry()
{
var mapperConfig = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new Common.Map.MapProfile());
cfg.CreateMissingTypeMaps = true;
});
var mapper = mapperConfig.CreateMapper();
For<IMapper>().Use(() => mapperConfig.CreateMapper());
For<MyDbContext>().Use(()=> new MyDbContext());
Scan(
scan =>
{
scan.AssemblyContainingType<ServiceBase>();
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.ConnectImplementationsToTypesClosing(typeof(IHandle<>));
});
}
The Nuget package StructureMap.WebApi2 created some other files for wiring up resolution and nested containers, but i'm leaving them out of this question for the sake of brevity.
Have a look at the Mehdime DbContext Scope Factory / Locator: https://github.com/mehdime/DbContextScope and he has a bit of a run-down of it on his blog. (link in the project description.) There are forks off there updated to the latest EF versions.
I've found it to be an excellent unit of work wrapper for EF contexts without having to worry about injecting or passing around those contexts directly.
The trouble with IoC containers and constructor injection is that if you register your DBContext it means that it's hard to work with things like a unit of work within the scope of a request without it essentially being the entire scope of the request. The DbContext Scope solves this by having you register a Scope Factory and a Scope Locator in your Container. Code controlling the Scope (unit of work) will use the Scope Factory to initialize a context scope for your DbContexts. Code operating with DbSets etc. in a DbContext use the ContextScopeLocator to get their UoW /w it's DbContext & sets.

WCF with IOperationInvoker using Entity and Ninject

I have a WCF Service from which I need to log the calls to its methods. For this, I used this solution to be able to track the calls and call my internal audit service, which uses Entity 5.1 and injects the services/repositories/DbContext using Ninject.
My Invoke method looks like this:
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var methodParams = (instance).GetType().GetMethod(_operationName).GetParameters();
var parameters = new Dictionary<string, object>();
for (var index = 0; index < inputs.Length; index++)
parameters.Add(methodParams[index].Name, inputs[index]);
_auditService.TrackFilterParametersValues(_operation.Parent.Type.FullName, _operationName, _operation.Action, parameters);
return _baseInvoker.Invoke(instance, inputs, out outputs);
}
In my Ninject module I have the internal stuff registered like this:
Bind<IAuditService>().To<AuditeService>().InRequestScope();
Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Bind<DbContext>().To<MyEntities>().InRequestScope();
Problem comes up when, inside the Repository, I call the dbContext to add the new Audit object like this:
_dbContext.Set<T>().Add(entity);
It errors out claiming that the DbContext has been disposed.
What would be the correct way of registering the DbContext on a WCF Service so it gets registered for an IOperationInvoker??
I have to mention that I have all this declaration the same for the main site I'm feeding up with this backend in MVC4 and it works perfectly (no WCF there). So I'm pretty sure something is needed to be corrected for the WCF lifetime cycle, but not so sure about what.
I found the reason of why this was behaving so nasty: in the chain formed by the IOperationInvoker, IOperationBehavior and IServiceBehavior, I was injecting the AuditService by the constructor of the first 2 of them, but in the latest (IServiceBehavior), since I was decorating the WCF class with it and couldn't overload the constructor, I was using the DependencyResolver to obtain the AuditService with a property like this:
public IAuditService AuditService
{
get { return DependencyResolver.Current.GetService<IAuditService>();
}
Then, when I started to debug, I noticed that the constructors were called when the WCF Test Client was querying the WCF for the WSDL data, but the Invoke method was never called because no web method was being invoked. So the AuditService instance (and DbContext) was all fine during the calls of the constructors, but by the time of invoking a web method and calling the Invoke method of the IOperationInvoker, the DbContext was already disposed long time ago.
My workaround for this was to delete all the references to the AuditService from all constructors and move the property with the DependencyResolver from the ServiceBehavior to the IOperationInvoker implementation. Once I did this, the AuditService is called right when it's needed, never before, and its DbContext is never disposed.
If MyEntities inherits from DbContext, then this should work:
Bind(typeof(DbContext)).To(typeof(MyEntities)).InRequestScope();

Singleton pattern using PHP

I am trying to create a dynamic navigation class.
class myApp_Helper_Breadcrum{
protected $navigationArray=array();
private static $_instance = null;
public static function getInstance()
{
if (!isset(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
private function __construct() {
$this->navigationArray = array();
}
public function popin($popInElement){
array_push($this->navigationArray,$popInElement);
}
public function displayLinks()
{
//print array
}
}
In boostrap I did following
$nlinks=myApp_Helper_Breadcrum::getInstance();
Zend_Registry::set('nlinks',$nlinks);
Now in my controller I am calling as follow
$nlinks= Zend_Registry::get('nlinks');
$nlinks->popin('Home');
$nlinks->displayLinks();
The problem is, even if this class is singleton the constructor is called again and again which makes my array to initialize. what I am trying to achieve is to keep pushing the items in the navigation array as I navigate the site.
Any idea why it is like this in ZF?
PHP isn't running like Java would where you have a JVM to maintain the state of your classes. In Java you can have a singleton behave exactly as you describe, but in PHP all the classes are refreshed with each subsequent call to the web server. So your singleton will stay in place for the duration of that call to the server, but once the response is sent then you start over again on the next call.
If you want to maintain state through successive calls you need to use the $_SESSION to keep track of your state.
EDIT:
My answer above deals with PHP in general and not the Zend Framework specifically. See my comment below.
Try to define your component as below:
class MyApp_Helper_Breadcrum
{
private static $_instance = null; // use private here
public static function getInstance()
{
if (self::$_instance === null) { // use strictly equal to null
self::$_instance = new self();
}
return self::$_instance;
}
private function __construct() // use private here
{
// ...
}
// ...
}
I ran into the exact same problem.
The problem is that the persistence of your classes are on the request scope.
And with zend, you can even have multiple requests for a page load.
PHP is a shared nothing architecture; each
request starts in a new process, and at the end of the request, it's all
thrown away. Persisting across requests simply cannot happen -- unless
you do your own caching. You can serialize objects and restore them --
but pragmatically, in most cases you'll get very little benefit from
this (and often run into all sorts of issues, particularly when it comes
to resource handles).
You may want to use Zend_cache, for persistence
Even though this is old, I would like to add my 2 cent.
Zend DOES NOT create a singleton, that persists across multiple requests. Regardless of the interpretation of the ZF documentation, on each request, the whole stack is re-initialized.
This is where your problem comes from. Since bootstrapping is done on each request, each request also re-initializes your helper method. As far as I know, helpers in ZF 1.x CAN'T be singletons.
The only way I see this being implementes ar you want it to be, is using sessions.

Autofac Session Scope

I am investigating the use of Autofac in our web application having previously used Castle Windsor in the past.
The thing that I really like with Autofac is being able to express dynamic component construction through lamda expressions, as opposed to creating DependancyResolvers etc. in Windsor.
One scenario I have is that I want a particular component to be registered at ASP.NET session level scope. With Windsor I would create/source a new LifestyleManager, however with Autofac I came up with this:
//Register SessionContext at HTTP Session Level
builder.Register(c =>
{
HttpContext current = HttpContext.Current;
//HttpContext handes delivering the correct session
Pelagon.Violet.Core.Interfaces.SessionContext instance = current.Session["SessionContext"] as Pelagon.Violet.Core.Interfaces.SessionContext;
if (instance == null)
{
instance = c.Resolve<Pelagon.Violet.Core.Interfaces.SessionContext>();
current.Session["SessionContext"] = instance;
}
return instance;
})
.FactoryScoped();
Which at some point I might be able to turn into an extension method. I accept this implemtation will bomb if the HttpContext.Current.Session is null as it should only be used in a web app.
The question is:
What is the best practice for such a registration in Autofac. I have seen a lot of mention about the use of nested containers etc. but no concrete examples, and I am keen to understand what might be wrong with the above approach (only thing I can think of is the automatic disposal stuff).
Thanks.
This looks fine.
Marking the component 'ExternallyOwned()' will ensure that Autofac doesn't call Dispose() on it.
The only gotchas here are that your session-scoped component could resolve dependencies of its own via the current container, and thus hold references to things that may belong to the current request (for instance.) This should be easy to spot in testing though.