当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - DI/IoC for .net mvc async/await

问题描述:

I'm using Simple Injector as the IoC container for my .Net MVC project. Here is how I register the 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/await, the ioc failed. Then I looked its documentation, it got a different LifeStyle for Asynchronous methods. So I changed the DefaultScopeLifeStyle to ExecutionContextScopeLifestyle(), it errored out

The ICustomerService is registered as 'Execution Context Scope' lifestyle, but the instance is requested outside the context of a Execution Context Scope.

Do I need to implement a hybrid lifestyle for using asyn/await as well as synchronous methods? Or something is wrong in my design?

Error detail (with WebRequestLifestyle)

The asynchronous action method 'foo' returns a Task, which cannot be executed synchronously.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: The asynchronous action method 'foo' returns a Task, which cannot be executed synchronously.

Source Error:

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

Stack Trace:

[InvalidOperationException: The asynchronous action method 'foo' returns a Task, which cannot be executed synchronously.]

System.Web.Mvc.Async.TaskAsyncActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +119

System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) +27

System.Web.Mvc.<>c__DisplayClass15.b__12() +56

System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +256

System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +22

System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor, IDictionary2 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.WrappedAsyncResult2.CallEndDelegate(IAsyncResult asyncResult) +16

System.Web.Mvc.Async.WrappedAsyncResultBase1.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.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +22

System.Web.Mvc.Async.WrappedAsyncResultBase1.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.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +29

System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49

System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28

System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9

System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9765121

System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

Edit

I've confirmed it's not a Simple Injector issue, it's really this. I've tried to clean the solution, remove the dlls in the bin folder, still no luck with same error. However, I changed the controller to an ApiController, the asyn worked well.

网友答案:

As far as I can see, this problem is not related to Simple Injector and its scoping; if you wrap an execution context scope around a web request (which is something you can do by hooking into the request_start and request_end events), you will be faced by the same problem.

There are several issues about this on Stackoverflow and the rest of the interwebs, that you should take a look at, such as this q/a.

分享给朋友:
您可能感兴趣的文章:
随机阅读: