Castle.Windsor и HttpContextWrapper

HttpContextWrapper и HttpContextBase, как здесь, были введены, чтобы сделать HttpContext более удобным издевательский / проверяемый.

Я пытаюсь использовать его с S # arp Architecture, и у меня возникают некоторые проблемы.

Мои контроллеры MVC настроены на прием аргумента HttpContextBase в конструкторе, и во время Application_Start HttpContextBase регистрируется в Castle.Windor следующим образом:

container.Register(Component.For<HttpContextBase>().UsingFactoryMethod(
    () => new HttpContextWrapper(HttpContext.Current)));

Некоторое время это работало нормально, но потом я понял, что Castle запускает этот метод Factory только один раз, поэтому все запросы получают исходный HttpContextWrapper. На самом деле его нужно создавать заново для каждого запроса. Команда Castle.Windsor для этого будет:

container.Register(Component.For<HttpContextBase().
    LifeStyle.PerWebRequest.UsingFactoryMethod(
    () => new HttpContextWrapper(HttpContext.Current)));

... но оказывается, что Castle.Windsor не позволяет использовать LifeStyle.PerWebRequest в Application_Start (как описано здесь)

Что мне делать? Есть ли простой способ обойти это, или мне следует отказаться от HttpContextWrapper и внедрить свою собственную фабрику, чтобы создавать новые по мере необходимости?


person codeulike    schedule 28.03.2011    source источник


Ответы (3)


Мои контроллеры MVC настроены на прием аргумента HttpContextBase в конструкторе

Здесь вы должны сделать что-то крайне неправильное, поэтому остановитесь, пока не стало слишком поздно и не был нанесен ущерб (материальные, моральные и человеческие жертвы :-)). У вас уже есть HttpContext внутри контроллера.

Не регистрируйте HttpContexts в своей структуре DI. Обработка HttpContext - это работа ASP.NET.

person Darin Dimitrov    schedule 28.03.2011
comment
@jfar, у меня на экране просочилось пиво, когда я прочитал предложение My MVC Controllers are set up to accept an HttpContextBase argument in the constructor. - person Darin Dimitrov; 29.03.2011
comment
Хорошо, но тогда в чем смысл HttpContextWrapper и / или как издеваться над HttpContext, который передается ASP.NET? - person codeulike; 29.03.2011
comment
@codeulike, ну, лично я использую для этой цели MVCContrib TestHelper, но есть вроде 40k альтернатив. - person Darin Dimitrov; 29.03.2011
comment
Между прочим, дело не в том, что я создаю HttpContext, это действительно было бы серьезной территорией для разлива пива. Это скорее случай создания HttpContextWrapper в подходящее время и обертывания его вокруг HttpContext, созданного asp.net. Проблема в том, чтобы Castle.Windor сделал это в нужное время. Я посмотрю на TestHelper и, э-э, 40k других результатов Google. Спасибо. - person codeulike; 29.03.2011
comment
Хм, я думаю, мне нужно второе мнение. Я не уверен, что то, что я пытаюсь сделать, сильно отличается от этого: stackoverflow.com/questions/3990879/ .. если это нормально, то почему вводить нельзя? - person codeulike; 29.03.2011
comment
@codeulike, пример, о котором вы говорите, касается того, как сделать классические веб-формы ASP.NET более пригодными для модульного тестирования. Вы и поправьте меня, если я ошибаюсь (и если я ошибаюсь, пожалуйста, поменяйте свой вопрос), делаете ASP.NET MVC, который сильно отличается от классического приложения ASP.NET WebForms. - person Darin Dimitrov; 29.03.2011
comment
Я использую MVC. Но если внедрение фабрики HttpContextWrapper нормально в классическом ASP.NET (я думаю, это то, что вы предлагаете в другом вопросе?), Почему это не нормально в MVC? - person codeulike; 29.03.2011
comment
@codeulike, в ASP.NET MVC действие контроллера уже имеет HttpContext, введенный платформой ASP.NET MVC. И этот контекст уже представляет собой поддельную абстракцию: HttpContextBase, поэтому вам не нужно делать какие-либо дополнительные работы. Сантехника необходима в классических веб-формах ASP.NET, где нет абстракций, только статическая чушь вроде HttpContext.Current, которую невозможно провести модульным тестированием. - person Darin Dimitrov; 29.03.2011
comment
Ах я вижу. Но когда я создаю объекты Controller в своих модульных тестах, как мне добавить свой Mock HttpContextBase в контроллеры? - person codeulike; 29.03.2011
comment
@codeulike, вы проверяли MvcContrib TestHelper? Этот фреймворк должен делать именно это. Вы, кажется, комментируете здесь немного быстро, не проверяя ссылки, которые я предоставил. Прочтите документацию, попробуйте, поиграйте с Rhino Mocks. Если вы столкнетесь с некоторыми конкретными проблемами, не стесняйтесь показать, что вы пробовали до сих пор, и задайте другой вопрос и т. Д., Чтобы у нас было что-то конструктивное. - person Darin Dimitrov; 29.03.2011
comment
@codeulike, кстати, вы можете проверить образец структуры проекта ASP.NET MVC, который я написал, который использует MvcContrib TestHelper для действия контроллера модульного тестирования. - person Darin Dimitrov; 29.03.2011
comment
Я уверен, что TestHelper это сделает, но потом я отвлекся и понял, почему то, что я делал изначально, было «крайне неправильным». Я считаю, что смогу заставить работать метод Castle.Windsor, возможно, используя Transient lifestyle. Так что, возможно, это немного неоптимально, но я думаю, что это могло бы работать как легкая выдумка для тестирования контроллеров. Но да, я вижу, что TestHelper разобрался бы за меня, а также помог бы с множеством других вещей. Спасибо за помощь, теперь я намного лучше понимаю территорию. - person codeulike; 29.03.2011

Как заметил Дарин, нет смысла внедрять HttpContext в контроллер MVC. Однако, если он вам нужен для других видов услуг, а также в Application_Start (), используйте гибридный perwebrequest-переходный образ жизни. Или, поскольку его легко построить, просто сделайте его временным.

person Mauricio Scheffer    schedule 28.03.2011

Как заявляли другие - вы делаете это неправильно. Мой большой вопрос:

Что вы делаете, что требует от вас внедрения HttpContextBase в ваш контроллер? Людям, желающим помочь вам, было бы более полезно, если бы вы предоставили нам больше информации о том, что вы действительно пытаетесь сделать. Давайте вытащим из него Касла и приступим к тому, что делает ваш контроллер.

Кстати, у вашего контроллера уже есть ссылка на HttpContext. Если вы делаете это для тестируемости, вам ничего не нужно делать на уровне контроллера. Вам просто нужно будет имитировать объект HttpContextBase по мере необходимости в тестах вашего контроллера.

person Alec    schedule 29.03.2011
comment
Я делал это для проверки. Вы правы в том, что издеваться над HttpContextBase в тестах контроллеров легко, но я не видел очевидного способа внедрить макет в контроллеры без фабрики настраиваемых контроллеров. Теперь я знаю, что TestHelper предоставляет именно это. - person codeulike; 30.03.2011