2015-08-10 15 views
5

Ho un'applicazione MVC5 che utilizza Castle Windsor (http://www.artisancode.co.uk/2014/04/integrating-windsor-castle-mvc/). Recentemente ho provato ad aggiungere un metodo Async a un controller MVC. Quando si esegue questa operazione, viene visualizzato il seguente messaggio di errore:Async MVC Action con Castle Windsor

Il metodo di prova asincrona 'test' restituisce un'attività, che non può essere eseguita in modo sincrono.

Ho creato una nuova applicazione MVC in VS e non ho ricevuto l'errore, quindi immagino che abbia lasciato qualcosa fuori dalla configurazione di Castle Windsor? Tuttavia non ho idea da dove cominciare e non sono stato in grado di trovare alcun articolo in caso di aiuto.

Aggiornamento domanda con il codice:

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

cs CastleWindsorMvcFactory

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 azione

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

Inizia mostrando il codice –

+0

Questa azione è richiamata dal metodo Html.Action in un'altra vista? –

+0

È solo un metodo di prova, chiamato direttamente inserendo l'url in un browser – markpirvine

risposta

2

stavo lavorando su qualcosa d'altro e sono imbattuto in questo article. Sulla base di ciò, ho cambiato il mio CastleWindsorActionInvoker per ereditare da AsyncControllerActionInvoker e sono stato in grado di eseguire la mia azione asincrona.

Grazie per tutti i suggerimenti!

1

responsabilità: i link qui sotto sono per un sample Github project ho creato.

Sospetto che l'articolo stia raccomandando lo stile di vita sbagliato per i controller. Io di solito uso transitorio, 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()); 
    } 
} 

Utilizzando tale installazione, this action risolve bene:

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