2015-08-10 20 views
5

Mam aplikację MVC5, która używa Castle Windsor (http://www.artisancode.co.uk/2014/04/integrating-windsor-castle-mvc/). Ostatnio próbowałem dodać metodę Async jako kontroler MVC. Kiedy to zrobię, pojawia się następujący komunikat o błędzie:Async MVC Action with Castle Windsor

Metoda asynchroniczna "test" zwraca zadanie, które nie może być wykonane synchronicznie.

Stworzyłem nową aplikację MVC w VS i nie otrzymałem błędu, więc zgaduję, że zostawiłem coś z konfiguracji Castle Windsor? Jednak nie mam pojęcia, od czego zacząć i nie mogłem znaleźć żadnego artykułu, gdy pomaga.

Aktualizacja pytanie o kodzie:

CastleWindsorActionInvoker.cs

public class CastleWindsorActionInvoker : ControllerActionInvoker 
    { 
     private readonly IKernel kernel; 

     public CastleWindsorActionInvoker(IKernel kernel) 
     { 
      this.kernel = kernel; 
     } 

     protected override ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters) 
     { 
      foreach(IActionFilter filter in filters) 
      { 
       kernel.InjectProperties(null, filter); 
      } 

      return base.InvokeActionMethodWithFilters(controllerContext, filters, actionDescriptor, parameters); 
     } 

     protected override AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList<IAuthorizationFilter> filters, ActionDescriptor actionDescriptor) 
     { 
      foreach(IAuthorizationFilter filter in filters) 
      { 
       Type type = filter.GetType(); 

       IEnumerable<INamedInstanceAttribute> namedInstanceAttributes = type.GetCustomAttributes(typeof(INamedInstanceAttribute), false) as IEnumerable<INamedInstanceAttribute>; 

       if(namedInstanceAttributes != null) 
       { 
        this.kernel.InjectProperties(namedInstanceAttributes, filter); 
       } 
       else 
       { 
        this.kernel.InjectProperties(null, filter); 
       } 
      } 

      return base.InvokeAuthorizationFilters(controllerContext, filters, actionDescriptor); 
     } 
    } 

WindsorDependencyMvcResolver.cs

public class WindsorDependencyMvcResolver : System.Web.Mvc.IDependencyResolver 
    { 
     public IWindsorContainer container { get; protected set; } 

     public WindsorDependencyMvcResolver(IWindsorContainer container) 
     { 
      if(container == null) 
      { 
       throw new ArgumentNullException("container"); 
      } 

      this.container = container; 
     } 

     public object GetService(Type serviceType) 
     { 
      try 
      { 
       return container.Resolve(serviceType); 
      } 
      catch(ComponentNotFoundException) 
      { 
       return null; 
      } 
     } 

     public IEnumerable<object> GetServices(Type serviceType) 
     { 
      return container.ResolveAll(serviceType).Cast<object>(); 
     } 
    } 

CastleWindsorMvcFactory .cs

public class CastleWindsorMvcFactory : DefaultControllerFactory 
    { 
     private readonly IKernel kernel; 

     public CastleWindsorMvcFactory(IKernel kernel) 
     { 
      this.kernel = kernel; 
     } 

     protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
     { 
      if(controllerType == null) 
      { 
       throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path)); 
      } 

      Controller controller = (Controller)kernel.Resolve(controllerType); 

      if(controller != null) 
      { 
       controller.ActionInvoker = kernel.Resolve<IActionInvoker>(); 
      } 

      return controller; 
     } 

     public override void ReleaseController(IController controller) 
     { 
      kernel.ReleaseComponent(controller); 
     } 
    } 

Global.asax

ControllerBuilder.Current.SetControllerFactory(new CastleWindsorMvcFactory(container.Kernel)); 

DependencyResolver.SetResolver(new WindsorDependencyMvcResolver(container)); 

MVC Action

public async Task<ActionResult> Index() 
     { 
      return View(); 
     } 
+0

Zacznij od pokazania nam swojego kodu –

+0

Czy to działanie jest wywoływane przez metodę Html.Action w innym widoku? –

+0

To tylko metoda testowa, wywołana bezpośrednio przez wpisanie adresu URL w przeglądarce – markpirvine

Odpowiedz

2

pracowałem na coś innego i natknąłem się na to article. Na tej podstawie zmieniłem swój CastleWindsorActionInvoker, aby dziedziczył z AsyncControllerActionInvoker i mogłem uruchomić moją akcję asynchroniczną.

Dzięki za wszelkie sugestie!

1

Zastrzeżone: Poniższe linki są na sample Github project stworzyłem.

Podejrzewam, że ten artykuł zaleca złym stylu życia dla kontrolerów. I normalnie używać przemijające, like so:

public class ControllersInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(Classes.FromThisAssembly() 
      .BasedOn<IController>() 
      .LifestyleTransient()); 

     container.Register(Classes.FromThisAssembly() 
      .BasedOn<IHttpController>() 
      .LifestyleTransient()); 
    } 
} 

Korzystanie że instalator, this action postanawia dobrze:

public async Task<ActionResult> Login(Models.LoginFormModel model, string returnUrl = "") 
{ 
    try 
    { 
     if (ModelState.IsValid) 
     { 
      /* ... more code ... */ 
     } 
    } 
    catch (Exception ex) 
    { 
     HandleException(ex); 
    } 

    // If we got this far, something failed; redisplay form 
    return View(model); 
} 
Powiązane problemy