2017-02-15 70 views
5

我使用Simple Injector作爲我的.Net MVC項目的IoC容器。以下是我如何註冊服務。.net mvc異步/等待的DI/IoC

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; 
    } 
} 

我的問題是,每當我用異步/ AWAIT,國際奧委會失敗。然後我看了它的documentation,它爲異步方法得到了不同的LifeStyle。所以我改變了DefaultScopeLifeStyleExecutionContextScopeLifestyle(),它出錯了

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

我需要實現混合的生活方式使用ASYN /待機以及同步的方法呢?或者我的設計有什麼不對?

錯誤詳細(與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, 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(IActionFilter filter, ActionExecutingContext preContext, Func 1 continuation) +256 System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +22 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList 1 filters, 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 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.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

編輯 我已經證實,它不是一個簡單的注射器的問題,它真的this。我試圖清理解決方案,刪除bin文件夾中的dll,仍然沒有運氣與相同的錯誤。但是,我將控制器更改爲ApiController,asyn運行良好。

+0

您在使用「WebRequestLifestyle」時聲明「在命中該行之前出錯」。你能發佈你獲得的完整異常詳情(異常類型,異常信息和堆棧跟蹤以及所有內部異常)嗎? – Steven

+0

@Steven添加了完整的錯誤細節。 – Quentin

+0

嗨昆汀,那不是我正在尋找的錯誤。這是您在使用ExecutionContextScopeLifestyle時得到的異常。相反,將'Container.Options.DefaultScopedLifestyle'更改爲'WebRequestLifestyle'併發布與該更改相關的異常。 PS。請不要發佈圖片,而應將例外詳細信息作爲文本發佈。這使得閱讀,複製和其他搜索引擎索引您的問題變得更加容易。 – Steven

回答

2

據我所知,這個問題與Simple Injector及其範圍無關;如果你圍繞一個Web請求包裝一個執行上下文作用域(這可以通過掛接到request_start和request_end事件來完成),你將面臨同樣的問題。

關於這個在Stackoverflow和其他的interwebs,你應該看看有幾個問題,如this q/a

+0

感謝您的意見。那麼在處理異步方法時,我應該使用'ExecutionContextScopeLifestyle'而不是'WebRequestLifestyle'? – Quentin

+2

@Quentin:不,你可以在MVC中繼續使用'WebRequestLifestyle'。 – Steven