2

I have a controller DailyExpenseController and I am injecting the IQueryExecutor class into the controller.

DailyExpenseController

using HomeBudgetTrackingSystem.CrossCutting;
using HomeBudgetTrackingSystem.DTO;
using HomeBudgetTrackingSystem.Models;
using HomeBudgetTrackingSystem.Query;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace HomeBudgetTrackingSystem.Controllers
{
    [Produces("application/json")]
    [Route("api/DailyExpense/{Id}")]
    public class DailyExpenseController : Controller
    {
        private readonly IQueryExecutor queryExecutor;

        public DailyExpenseController(IQueryExecutor queryExecutor)
        {
            this.queryExecutor = queryExecutor;
        }

        [HttpPost]
        [Route("Create")]
        public async Task<IActionResult> CreateExpense(long Id, [FromBody] Expenditure expenditure)
        {
            var findEntity = new FindEntityQuery<Expense>(Id);
            var find = queryExecutor.Execute(findEntity);

            /*if (find == null)
                return NotFound();*/


            var createExpenses = new CreateExpenditure(expenditure);
            var expenses = queryExecutor.Execute(createExpenses);
            return Ok(expenses);
        }

        /*If I write this method, it will result in 500 Error, because this method has id which is confusing 
         with the variable Id declared with Controller*/
        /*[HttpGet("{id}")]
        public string Get(int id)
        {
            return "value";
        }*/

        [HttpGet("{id2}")]
        public string Get(long id)
        {
            return "value";
        }

        [HttpPost]
        public void Post([FromBody]string value)
        {
        }

    }
}

Below is my Autofac Configuration details

Startup.cs

using Autofac;
using Autofac.Extensions.DependencyInjection;
using HomeBudgetTrackingSystem.Repository;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace HomeBudgetTrackingSystem
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        //public void ConfigureServices(IServiceCollection services)
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            /*services.AddDbContext<BudgetContext>(options =>
             options.UseSqlServer(Configuration.GetConnectionString("BudgetConnection")
        )); */

            var builder = new ContainerBuilder();
            builder.Populate(services);
            builder.RegisterModule(new RepositoryHandlerModule());
            //builder.RegisterType<QueryExecutor>().As<IQueryExecutor>();
            ApplicationContainer = builder.Build();
            return new AutofacServiceProvider(ApplicationContainer);
        }

        public IContainer ApplicationContainer { get; private set; }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvc();
            appLifetime.ApplicationStopped.Register(() => ApplicationContainer.Dispose());
        }
    }
}

Below is my Model Builder class where I have registered the dependencies

RepositoryHandlerModule.cs

using Autofac;
using HomeBudgetTrackingSystem.CrossCutting;

namespace HomeBudgetTrackingSystem.Repository
{
    public class RepositoryHandlerModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<QueryExecutor>().As<IQueryExecutor>().InstancePerRequest();
        }
    }
}

I have not made any changes to the Program.cs

Program.cs

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace HomeBudgetTrackingSystem
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .Build();
    }
}

Below are the exception details I received

Autofac.Core.DependencyResolutionException: Unable to resolve the type 'HomeBudgetTrackingSystem.CrossCutting.QueryExecutor' because the lifetime scope it belongs in can't be located. The following services are exposed by this registration: - HomeBudgetTrackingSystem.CrossCutting.IQueryExecutor

Details ---> No scope with a tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.

If you see this during execution of a web application, it 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 dependency resolver or the request lifetime scope, never from the container itself. (See inner exception for details.) ---> Autofac.Core.DependencyResolutionException: No scope with a tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.

If you see this during execution of a web application, it 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 dependency resolver or the request lifetime scope, never from the container itself. at Autofac.Core.Lifetime.MatchingScopeLifetime.FindScope(ISharingLifetimeScope mostNestedVisibleScope) at Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration registration, IResolveOperation context, ISharingLifetimeScope mostNestedVisibleScope, IEnumerable1 parameters) --- End of inner exception stack trace --- at Autofac.Core.Resolving.InstanceLookup..ctor(IComponentRegistration registration, IResolveOperation context, ISharingLifetimeScope mostNestedVisibleScope, IEnumerable1 parameters) at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable1 parameters) at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable1 parameters) at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable1 parameters, Object& instance) at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable1 parameters) at Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired) at lambda_method(Closure , IServiceProvider , Object[] ) at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.b__0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.g__CreateController|0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__22.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.d__7.MoveNext()

I have referred multiple links on these. The prominent ones are

http://autofac.readthedocs.io/en/latest/faq/per-request-scope.html http://autofac.readthedocs.io/en/latest/integration/aspnetcore.html (I preferred Configuration without Container) http://www.codedigest.com/posts/49/using-autofac-instead-of-inbuilt-di-container-with-in-aspnet-core-mvc (This is the one I referred)

Could anyone please help me on these?

1 Answer 1

3

I was able to find the solution to the problem.

http://autofaccn.readthedocs.io/en/latest/integration/aspnetcore.html

Here Under the Title 'Differences From ASP.NET Classic', lists a key point Use InstancePerLifetimeScope instead of InstancePerRequest.

I also made a change in my RepositoryHandlerModule.cs like adding the BudgetContext.cs which is as below

public class RepositoryHandlerModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            base.Load(builder);
            builder.RegisterType<QueryExecutor>().As<IQueryExecutor>().InstancePerLifetimeScope();
            builder.RegisterType<BudgetContext>().InstancePerLifetimeScope();
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.