0
votes

So, I'm honestly not even sure how to ask this question, since I lack experience in this topic. If there is information missing, just let me know and I'll add all I have.

I'm basically trying to add an Exception handling system in my web application by using a filter.

So below you can see the filter I created. In here I'm trying to reach my unitofwork, but I keep getting an exception on the container.Resolve<IUnitOfWork>(); line.

public class LogExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        var dependencyResolver = GlobalConfiguration.Configuration.DependencyResolver 
            as AutofacWebApiDependencyResolver;
        var container = dependencyResolver.Container;
        var uow = container.Resolve<IUnitOfWork>();
    }
}

The exception I'm getting:

DependencyResolutionException was unhandled by user code
An exception of type 'Autofac.Core.DependencyResolutionException' occurred in Autofac.dll but was not handled in user code

Additional information: 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.

Here is the IUnitOfWork interface:

public interface IUnitOfWork : IDisposable
{
    IBoothRepository BoothRepository { get; }
    IEventRepository EventRepository { get; }
    ILocationRepository LocationRepository { get; }
    IPersonRepository PersonRepository { get; }
    IProfessionalRepository ProfessionalRepository { get; }
    IRegistrationRepository RegistrationRepository { get; }
    IStakeholderRepository StakeholderRepository { get; }
    IStudentRepository StudentRepository { get; }
    IVisitRepository VisitRepository { get; }

    void SaveChanges();

    DbContextTransaction BeginTransaction();
}
2
I would revisit your IUnitOfWork interface.... surely it should not know about all the repositories, rather you would have a service, which would know the repositories AND the unit of work, and use them to perform a unit of work. In your current design you have to CHANGE YOUR INTERFACE every time you add a new repository. This is certainly not correctMilney
If you are using Entity Framework (or LINQ) the data context is ALREADY an implementation of the Unit of Work pattern, so you don't need to re-do this at a higher level as wellMilney

2 Answers

2
votes

The additional information is your friend here:

No scope [...] 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.)

An ExceptionFilter is a SingleInstance component, since it's generic (Single Instance) to all requests within the application instead of it having a specific instance be bound to a specific request.

They actually have a pretty decent HowTo for Web API on the Autofac website which comes down to implementing the IAutofacExceptionFilter and using Property Injection to get the stuff resolved in your FilterAttribute. There's also an MVC HowTo, which comes down to calling RegisterFilterProvider to enable Property Injection for filters.

0
votes

1) Are you running a test, from where the AutoFacPerRequestScope has not been initialized ? You might have to use PerLifeTimeScope lifetime instead of PerRequest Lifetime.