DI / IoC for .net mvc async / wait

I am using Simple Injector as an IoC container for my .Net MVC project. This is how I register services.

SimpleInjectorInitializer.cs

public static void Initialize() { var container = new Container(); container.Options.DefaultScopedLifestyle = new WebRequestLifestyle(); //container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle(); // replace last line with this for async/await InitializeContainer(container); container.RegisterMvcControllers(Assembly.GetExecutingAssembly()); container.Verify(); DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container)); } private static void InitializeContainer(Container container) { container.Register<MyDbContext>(Lifestyle.Scoped); container.Register(typeof(IUnitOfWork<>), typeof(UnitOfWork<>), Lifestyle.Scoped); container.Register(typeof(IRepository<>), typeof(Repository<>), Lifestyle.Scoped); container.Register<ICustomerService, CustomerService>(Lifestyle.Scoped); //what does this do by the way? //using (container.BeginExecutionContextScope()) { //} } 

CustomerController

 public interface ICustomerService : IService<Customer> {} public class CustomerService : BaseService<Customer, MyDbContext>, ICustomerService { public CustomerService(IUnitOfWork<MyDbContext> unitOfWork) : base(unitOfWork) {} // do stuff } public class CustomerController : Controller { private readonly ICustomerService _service; public CustomerController(ICustomerService service) { _service = service; } public ActionResult Index() { var foo = _service.GetById(112); // works // do stuff return View(); } public async Task<int> Foo() { // error out on calling this method var foo = await _service.GetByIdAsync(112); return foo.SomeId; } } 

My problem is that whenever I used async / wait, ioc failed. Then I looked at his documentation , he got another LifeStyle for asynchronous methods. So I changed the value of DefaultScopeLifeStyle to ExecutionContextScopeLifestyle() , it was wrong

ICustomerService is registered as the "Execution Context Context" lifestyle, but the instance is requested outside the context of the execution context context.

Do I need to implement a hybrid lifestyle to use asyn / await, as well as synchronous methods? Or is there something wrong with my design?

Error Details (with WebRequestLifestyle )

The asynchronous action method "foo" returns a task that cannot be executed synchronously.

Description: An unhandled exception occurred during the execution of the current web request. View the stack trace for more information about the error and its occurrence in the code.

Exception Details: System.InvalidOperationException: Asynchronous action method 'foo' returns a task that cannot be executed synchronously.

Source Error:

An unhandled exception was thrown during the execution of the current web request. Information about the origin and location of the exception can be identified using the exception stack trace below.

Stack trace:

[InvalidOperationException: asynchronous method "foo" returns a task that cannot be executed synchronously.] System.Web.Mvc.Async.TaskAsyncActionDescriptor.Execute (ControllerContext controllerContext, IDictionary 2 parameters) +119 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary 2 parameters) +27 System.Web.Mvc. <> c__DisplayClass15.b__12 () +56 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter (filter IActionFilter, ActionExecutingContext preContext, Func 1 continuation) +256 System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +22 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList 1 filter, actionDescriptor actionDescriptor, IDictionary 2 parameters) +190 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +522 NotFoundMvc.ActionInvokerWrapper.InvokeActionWith404Catch(ControllerContext controllerContext, String actionName) +32 NotFoundMvc.ActionInvokerWrapper.InvokeAction(ControllerContext controllerContext, String actionName) +16 System.Web.Mvc.<>c__DisplayClass22.<BeginExecuteCore>b__1e() +23 System.Web.Mvc.Async.AsyncResultWrapper.<.cctor>b__0(IAsyncResult asyncResult, Action action) +15 System.Web.Mvc.Async.WrappedAsyncResult String actionName) +522 NotFoundMvc.ActionInvokerWrapper.InvokeActionWith404Catch (controllerContext 2 parameters) +190 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +522 NotFoundMvc.ActionInvokerWrapper.InvokeActionWith404Catch(ControllerContext controllerContext, String actionName) +32 NotFoundMvc.ActionInvokerWrapper.InvokeAction(ControllerContext controllerContext, String actionName) +16 System.Web.Mvc.<>c__DisplayClass22.<BeginExecuteCore>b__1e() +23 System.Web.Mvc.Async.AsyncResultWrapper.<.cctor>b__0(IAsyncResult asyncResult, Action action) +15 System.Web.Mvc.Async.WrappedAsyncResult 2 parameters) +190 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +522 NotFoundMvc.ActionInvokerWrapper.InvokeActionWith404Catch(ControllerContext controllerContext, String actionName) +32 NotFoundMvc.ActionInvokerWrapper.InvokeAction(ControllerContext controllerContext, String actionName) +16 System.Web.Mvc.<>c__DisplayClass22.<BeginExecuteCore>b__1e() +23 System.Web.Mvc.Async.AsyncResultWrapper.<.cctor>b__0(IAsyncResult asyncResult, Action action) +15 System.Web.Mvc.Async.WrappedAsyncResult 2.CallEndDelegate (IAsyncResult asyncResult) +16 System.Web.Mvc.Async.WrappedAsyncResultBase 1.End() +49 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +36 System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12 System.Web.Mvc.Async.WrappedAsyncVoid 1.CallEndDelegate (IAsyncResult asyncResult) +22 System.Web.Mvc.Async.WrappedAsyncResultBase 1.End() +49 System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26 System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10 System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21 System.Web.Mvc.Async.WrappedAsyncVoid 1.CallEndDelegate (IAsyncResult asyncResult) +29 System.Web.Mvc.Async.WrappedAsyncResultBase`1.End () +49 System.Web. EndProcessRequest (IAsyncResult asyncResult) +28 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcess Request (result of IAsyncResult) +9 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute () +9765121 System.Web.HttpApplication.ExecuteStep (step IExecutionStep, Boolean and completed synchronously) +155

Edit I have confirmed that this is not a simple injector problem, it is really this . I tried to clear the solution, delete the DLL in the bin folder, still no luck with the same error. However, I changed the controller to ApiController, asyn worked well.

+5
source share
1 answer

As far as I can see, this problem is not related to Simple Injector and its scope; if you overlap the execution context area around the web request (something you can do by connecting to the request_start and request_end events), you will encounter the same problem.

There are several issues in Stackoverflow and other environments that you should pay attention to, such as this q / a .

+2
source

Source: https://habr.com/ru/post/1264273/


All Articles