Resolving a dependency at runtime that uses InstancePerRequest service

657 views
Skip to first unread message

Eranga Abeysinghe

unread,
Jan 11, 2011, 12:02:32 AM1/11/11
to aut...@googlegroups.com
Hi All,
I have a asp.net mvc app with entity framework where there should be only 1 DataContext per request.

In the Global.aspx.cs I have following code to register dependencies

            var builder = new ContainerBuilder();
            builder.RegisterType<DataContext>().InstancePerHttpRequest();
  Data.Controller.Instance.Container = builder.Build();

And in the other assembly I have

public abstract class EFRepository<TEntity> : IRepository<TEntity>
{
public EFRepository(DataContext dataContext)
{
 
}

public abstract class Entity
{
//other stuff
        protected TRepository GetRepository<TRepository>()
        {
            return Controller.Instance.Container.Resolve<TRepository>();
        }
}

So when ever I want to call GetRepository method I get the following error {"No scope matching the expression 'value(Autofac.Builder.RegistrationBuilder`3+<>c__DisplayClass0[Em.Mdm.Data.DataContext,Autofac.Builder.ConcreteReflectionActivatorData,Autofac.Builder.SingleRegistrationStyle]).lifetimeScopeTag.Equals(scope.Tag)' is visible from the scope in which the instance was requested."} System.Exception {Autofac.Core.DependencyResolutionException}

Please advice as to how this can be avoided. Any changes I need to do are also welcome.

Thank You.

Alex Meyer-Gleaves

unread,
Jan 13, 2011, 9:03:35 AM1/13/11
to aut...@googlegroups.com
Hi Eranga,

Make sure you have registered the appropriate modules and made the required code changes to make the per request lifetime scope available.


If you are going to access the container directly (which you should avoid if possible) you will need to access the current lifetime scope using the IContainerProviderAccessor interface.

IContainerProviderAccessor accessor = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
ILifetimeScope lifetimeScope = accessor.ContainerProvider.RequestLifetime;

It would be better to inject the repository instances into your controllers instead though.

Cheers,

Alex.


--
You received this message because you are subscribed to the Google Groups "Autofac" group.
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.

Eranga Abeysinghe

unread,
Jan 17, 2011, 1:46:29 AM1/17/11
to aut...@googlegroups.com
Hi Alex,

Thank you for helping me out but I was unable to incorporate your solution.

I am using asp.net MVC 3 so 'IContainerProviderAccessor' is not available.(is there a way to retrieve this?)

As you said Repositories are injected to Controllers. But there are cases where an entity needs to access another entity through the repository or custom lazy loading scenario where I need an instance of the repository.

Additional info.
The entities and UI reside on different assemblies.
Can not control entity creation part since entity framework is creating the entities. (So unable to inject into entities)

Please help.

Thanks & Regards,
Eranga

Alex Meyer-Gleaves

unread,
Jan 17, 2011, 7:04:29 AM1/17/11
to aut...@googlegroups.com
Hi Eranga,

If you are using MVC 3 you will need to compile from source. MVC 3 support will be included in the upcoming Autofac 2.4 release. The link below will help you get started with the MVC 3 integration. 


You no longer need to add the modules to your configuration file or implement the IContainerProviderAccessor interface. Follow the instructions in the "Upgrading from ASP.NET MVC 2" section of the documentation to undo any changes you added by following the previous instructions.

I had wondered about what version you were using but assumed it was MVC 2 because the MVC 3 support had not been released yet. Sorry about the confusion.

Cheers,

Alex.


--

Eranga Abeysinghe

unread,
Jan 17, 2011, 11:21:24 PM1/17/11
to aut...@googlegroups.com
Hi Alex,

Thanks for the reply and sorry for not specifying that I use MVC3. Good to hear that 2.4 is coming soon. I already compiled the source and using it. For the common cases its working great.

My problem is how to resolve a dependency at runtime in another assembly which uses a dependency registered as InstancePerRequest in another assembly.

Say in my UI project(Global.aspx.cs) I have


             var builder = new ContainerBuilder();
            builder.RegisterType<DataContext>().InstancePerHttpRequest();
  Data.Controller.Instance.Container = builder.Build();

And In my Data project I have 


public abstract class EFRepository<TEntity> : IRepository<TEntity>
{
public EFRepository(DataContext dataContext)
{
 
}
public abstract class Entity
{
//other stuff
        protected TRepository GetRepository<TRepository>()
        {
            return Controller.Instance.Container.Resolve<TRepository>();
        }
}
 
public class Item : Entity
{
internal void OnBeforeInsert()
{
var categoryRepository = GetRepository<ICategoryRepository>();
//other stuff 
}
 
So inorder to use the container created in the UI project I used a Singleton to access the container in the Data Project. (Highlighted in bold)

The container is used as highlighted in Blue. But when I access that (Highlighted in Red) I get the following error.

{"No scope matching the expression 'value(Autofac.Builder.RegistrationBuilder`3+<>c__DisplayClass0[Em.Mdm.Data.DataContext,Autofac.Builder.ConcreteReflectionActivatorData,Autofac.Builder.SingleRegistrationStyle]).lifetimeScopeTag.Equals(scope.Tag)' is visible from the scope in which the instance was requested."} System.Exception {Autofac.Core.DependencyResolutionException}

Please help me out. I do not have a deep knowledge of Autofac. I hope you can understand my problem better now.

If the design is flowed (can this be done without the Singleton) please advice.

Thanks & Regards,
Eranga

Nicholas Blumhardt

unread,
Jan 18, 2011, 5:25:56 PM1/18/11
to aut...@googlegroups.com
Hi Eranga,

Instead of InstancePerHttpRequest() use InstancePerLifetimeScope(). This will work in both cases.

Cheers,
Nick


Thanks & Regards,
Eranga

--

era...@gmail.com

unread,
Jan 23, 2011, 10:44:44 PM1/23/11
to aut...@googlegroups.com
Hi Nick,

Thanks for your reply. Found an alternate solution when I went through the source of 'AutofacDependencyResolver'. I access the 'RequestLifetimeScope' property through a delegate from my 'Data' project.

I will try your solution also. Thanks again for helping me out.

Thanks & Regards,
Eranga

bala....@gmail.com

unread,
Jul 26, 2018, 10:13:17 AM7/26/18
to Autofac
Hi,

I to had the same problem, how did you resolve that datacontext
Can you send code are same link.
Reply all
Reply to author
Forward
0 new messages