2009-10-21 5 views
2

J'ai créé une application ASP.NET MVC et essaie d'utiliser le château de Windsor comme mon CIOPourquoi Castle Windsor essaie-t-il de résoudre mon dossier 'Content' et 'Scripts' en tant que contrôleur?

Cependant, lorsque les contrôleurs tentent de résoudre je reçois « Contenu » et « scripts » dans le paramètre « ControllerName » dans la méthode CreateController(RequestContext requestContext, string controllerName). Inutile de dire que ce ne sont pas des contrôleurs. Ils semblent être les dossiers du site Web

Pourquoi essaie-t-il de les enregistrer en tant que contrôleurs?

Comment ignorer ces dossiers ??

grâce

exception de WindsorControllerFactory

En raison de ne pas être en mesure d'afficher l'image je dois décrire - il dit fondamentalement juste

'Le contentcontroller n'a pas été trouvé'

Global.asax.cs

public static IIocContainer Ioc; 

      protected void Application_Start() 
      { 
       InitialiseIocContainer(); 
       RegisterViewEngine(ViewEngines.Engines); 
       RegisterRoutes(RouteTable.Routes); 
       StartProfiling(); 
      } 


private void InitialiseIocContainer() 
     { 
      IWindsorContainer _container = new WindsorContainer(); 

      var controllerTypes = typeof (GidgetController).Assembly.GetTypes(); 
      foreach (var controllerType in controllerTypes.Where((t=>typeof(IController).IsAssignableFrom(t)))) 
      { 
       _container.AddComponentLifeStyle(controllerType.Name.ToLower(), controllerType, LifestyleType.Transient); 
      } 


      _container.AddComponent("a",typeof(IGidgetService), typeof(GidgetService)); 
      _container.AddComponent("b",typeof(IGidgetRepository), typeof(GidgetRepository)); 
      _container.AddComponent("c",typeof(IGidgetValidator), typeof(GidgetValidator)); 


      ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container)); 

     } 

windsorControllerFactory.cs

public IController CreateController(RequestContext requestContext, string controllerName) 
     { 
      try 
      { 
       controllerName = controllerName.ToLower() + "controller"; 
       var controller = _container.Resolve<IController>(controllerName); 
       return controller; 
      } 
      catch (ComponentNotFoundException) 
      { 
       throw new HttpException(404, string.Format("The {0} controller was not found", controllerName)); 

      } 

     } 

Répondre

1

I suivent Steve Sanderson's modèle dans la création d'un WindsorControllerFactory, qui fonctionne très bien. J'ai modifié le sien pour renvoyer les vrais 404 quand il n'y a pas de contrôleur par le nom (c'est-à-dire que quelqu'un tape "/ garbageblahblah") parce que son modèle ne l'a pas détecté. Donc, j'utilise Reflector pour saisir les bits qui sont construits dans la fabrique de contrôleurs par défaut pour gérer les mauvaises urls. Son modèle utilise la réflexion pour trouver tous les contrôleurs de votre projet Mvc et les enregistrer tous au démarrage de l'application. Vous ne voulez pas utiliser CreateController, mais GetControllerInstance() à la place, car cela n'est appelé que par le framework Mvc sous-jacent lorsqu'un contrôleur va être appelé./Le contenu est ignoré par convention et n'est donc pas appelé.

Mon CastleWindsorControllerFactory:

/// <summary> 
/// Represents a special controller factory. 
/// </summary> 
public class CastleWindsorControllerFactory : DefaultControllerFactory 
{ 
    WindsorContainer _container; 

    public CastleWindsorControllerFactory() 
    { 
     // register all controllers from the calling assembly. 
     // (e.g. the mvc site calling this factory) 
     // 
     _container = 
      new WindsorContainer(
       new XmlInterpreter(
        new ConfigResource("castle") 
       ) 
      ); 

     // change this to Assembly.GetAssembly() if used directly from 
     // your MVC website. The code below is for when this class 
     // exists in a seperate assembly. 
     // 
     var controllers = 
      from t in Assembly.GetCallingAssembly().GetTypes() 
      where typeof(IController).IsAssignableFrom(t) 
      select t; 

     foreach (Type t in controllers) 
      _container.AddComponentLifeStyle(
       t.FullName, t, LifestyleType.Transient); 
    } 

    protected override IController GetControllerInstance(Type controllerType) 
    { 
     if (controllerType == null) 
     { 
      throw new HttpException(
       0x194 
       , string.Format(
        CultureInfo.CurrentUICulture 
        , "Controller Not Found" 
        , new object[] { 
         this.RequestContext.HttpContext.Request.Path })); 
     } 
     if (false == typeof(IController).IsAssignableFrom(controllerType)) 
     { 
      throw new ArgumentException(
       string.Format(
        CultureInfo.CurrentUICulture 
        , "Type does not sub-class the controller base" 
        , new object[] { controllerType }), "controllerType"); 
     } 

     return 
      (IController) _container.Resolve(controllerType); 
    } 
} 

et dans mes Globals.asax.cs, cela est tout ce que vous avez besoin (ce que vous avez ci-dessus est vaste surpuissance je l'ai déjà une boucle à travers et les enregistrer dans mon CastleWindsorControllerFactor ci-dessus!).

protected void Application_Start() 
{ 
    RegisterRoutes(RouteTable.Routes); 

    // custom controller factory that uses Windsor 
    ControllerBuilder.Current.SetControllerFactory(
     new CastleWindsorControllerFactory()); 

    // Uncomment to debug routes 
    //RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes); 
} 

Techniquement, ce n'est pas exactement le code que j'utilise. J'ai effectivement extrait tout le Castle Windsor à une instance statique dans une classe que j'appelle ComponentFactory. Cela me permet d'avoir de vrais motifs Singleton à travers mes applications, parmi plusieurs ajouts de type fort.

Je mentionne cela, car je prévois de publier ComponentFactory() bientôt sur mon blog. Mais, envoyez-moi un email et je vous enverrai la dernière version. Le courrier électronique est: me -at- eduncan911.com

+0

On dirait que votre ComponentFactory est en fait un localisateur de service, ce qui n'est pas une bonne idée pour les conteneurs IoC. La création du conteneur et l'enregistrement des contrôleurs dans controllerfactory violent la plate-forme SRP, ce n'est pas sa responsabilité. –

+0

merci pour votre réponse. – kurasa

+0

@Mauricio Scheffer: un vote -1 pour violer SRP? Vraiment? Il n'a pas exprimé d'inquiétude pour DDD ou SRP (et le MVCContrib qu'il a dit travaillé a fait la même chose que j'ai posté). Quel serait alors votre solutino pour l'enregistrement automatique de 100 IControllers sur un site ASP.NET MVC? "Récupérer" un contrôleur serait la responsabilité d'un modèle d'usine, qui ne viole pas SRP. Cela utilise un conteneur IoC pour le gérer plus facilement. – eduncan911