Вопрос по castle-windsor, c#, dependency-injection, ioc-container – Почему Castle Windsor пытается преобразовать мои папки «Content» и «Scripts» в качестве контроллера?

2

Я создал приложение ASP.NET MVC и пытаюсь использовать Castle Windsor в качестве своего IOC

Однако, когда контроллеры пытаются решить, я получаю «Content» и «Scripts» в параметр «controllerName» вCreateController(RequestContext requestContext, string controllerName) метод. Излишне говорить, что это не контроллеры. Похоже, они являются папками веб-сайта

Почему он пытается зарегистрировать их в качестве контроллеров?

Как мне игнорировать эти папки ??

Спасибо

исключение из WindsorControllerFactory

Из-за невозможности опубликовать изображение, я должен описать его - в основном это просто говорит

'Контроллер содержимого не найден'

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

            }

        }

Ваш Ответ

2   ответа
1

Стив Сандерсон шаблон при создании WindsorControllerFactory, который работает довольно хорошо. Я изменил его так, чтобы он действительно возвращал правильные 404, когда нет имени контроллера (то есть кто-то печатает "/ garbageblahblah"), потому что его шаблон не поднял его. Итак, я использую Reflector, чтобы получить биты, встроенные в фабрику контроллеров по умолчанию для обработки неверных URL.

Его шаблон использует отражение, чтобы найти все контроллеры в вашем проекте Mvc и зарегистрировать их все при запуске приложения. Вы не хотите использовать CreateController, но вместо этого GetControllerInstance (), так как он вызывается базовой структурой Mvc только тогда, когда будет вызван контроллер. / Контент игнорируется соглашением и поэтому не вызывается.

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

И в моем Globals.asax.cs это все, что вам нужно (то, что у вас есть выше, является огромным излишним! Я уже перебрал и зарегистрировал их в моем CastleWindsorControllerFactor выше).

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

Технически, это не совсем тот код, который я использую. Я фактически абстрагировал весь Замок Виндзор от статического экземпляра в классе, который я называю ComponentFactory. Это позволяет мне иметь настоящие синглтон-паттерны в моих приложениях, среди нескольких дополнений сильного типа.

Я упоминаю об этом, потому что я планирую скоро выпустить ComponentFactory () в своем блоге. Но, напишите мне письмо, и я вышлю вам последнюю версию. Адрес электронной почты: me -at- eduncan911.com

извини, я просто не думаю, что это хороший совет. Мы должны согласиться не согласиться, я думаю ... Mauricio Scheffer
Похоже, ваш ComponentFactory на самом деле является локатором службы, а это не очень хорошая идея для контейнеров IoC. Создание контейнера и регистрация контроллеров внутри фабрики контроллеров нарушает SRP, это не его ответственность. Mauricio Scheffer
спасибо за Ваш ответ. kurasa
@ Маурисио Шеффер: -1 голос за нарушение ПСП? В самом деле? Он не заявил о какой-либо озабоченности по поводу DDD или SRP (а MVCContrib, который, по его словам, работал, делает то же самое, что и я). Каким было бы ваше солютино для автоматической регистрации сотен контроллеров ICont на сайте ASP.NET MVC? Ответственность за "извлечение" контроллера лежит на шаблоне Factory, который не нарушает SRP. Это использует IoC-контейнер для облегчения работы с ним. eduncan911
1

MVCContrib.

Он включает в себя все для интеграции Windsor и ASP.NET MVC, включаяфабрика контроллеров а такжерасширения для регистрации контроллеров.

благодарю вас. Это сработало отлично. kurasa
Разве MVCContrib не делает то же самое, что и мой ответ? лол eduncan911

Похожие вопросы