ASP.NET MVC и Unity 1.2 Вопрос контейнера

Я пытаюсь использовать контейнер Unity, чтобы упростить unit test мои контроллеры. Мой контроллер использует конструктор, который принимает интерфейс к репозиторию. В файле global.asax я создаю экземпляр UnityContainerFactory и регистрирую его с помощью структуры MVC, а затем регистрирую репозиторий и его реализацию. Я добавил атрибут [Dependency] в параметр контроллера CTOR Repository. Кажется, что все это работает нормально, за исключением того, что время от времени factory GetControllerInstance (Type controllerType) вызывается более одного раза и передается пустой аргумент в качестве типа controllerType.

Первый вызов factory корректен, и в качестве аргумента передается тип контроллера ControlController. Но иногда, factory называется еще пару раз после того, как представление было отображено с нулевым значением для контроллера, и я не уверен, почему. Когда передается правильное значение типа контроллера, что "Call Stack" имеет смысл для меня, но когда передается значение null, я не уверен, почему или кто делает вызов. Любые идеи?

Ниже приведены коды и стеки вызовов для этого примера.

Вызов стека при работе

Test.DLL! Test.UnityHelpers.UnityControllerFactory.GetControllerInstance(System.Type controllerType = {Name = "ProductsController" FullName = "Test.Controllers.ProductsController" }) Строка 23 С# Test.DLL! Test._Default.Page_Load (object sender = {ASP.default_aspx}, System.EventArgs e = {System.EventArgs}) Строка 18 + 0x1a байты С#

Вызов стека, когда NULL передается по типу controller

Test.DLL! Test.UnityHelpers.UnityControllerFactory.GetControllerInstance(System.Type controllerType = null) Строка 27 С#

Сначала я создал UnityControllerFactory

public class UnityControllerFactory : DefaultControllerFactory
{
 UnityContainer container;
 public UnityControllerFactory(UnityContainer container)
 {
 this.container = container;
 }
 protected override IController GetControllerInstance(Type controllerType)
 {
 if (controllerType != null)
 {
 return container.Resolve(controllerType) as IController;
 }
 else
 {
 return null; // I never expect to get here, but I do sometimes, the callstack does not show the caller
 }
 }
}

Затем я добавил следующий код файла global.asax для создания экземпляра контейнера factory

protected void Application_Start()
 {
 RegisterRoutes(RouteTable.Routes);
 // Create Unity Container if needed
 if (_container == null)
 {
 _container = new UnityContainer();
 }
 // Instantiate a new factory
 IControllerFactory unityControllerFactory = new UnityControllerFactory(_container);
 // Register it with the MVC framework
 ControllerBuilder.Current.SetControllerFactory(unityControllerFactory);
 // Register the SqlProductRepository
 _container.RegisterType<iproductsrepository, sqlproductrepository="">
 (new ContainerControlledLifetimeManager());
 }
</iproductsrepository,>

В приложении есть один контроллер

public class ProductsController : Controller
{
 public IProductsRepository productsRepository;
 public ProductsController([Dependency]IProductsRepository productsRepository)
 {
 this.productsRepository = productsRepository;
 }
}
1 ответ

Вероятно, это связано с тем, что некоторый тип файла не сопоставляется с контроллером на ваших маршрутах. (изображения, например). Это будет происходить чаще, когда вы отлаживаете локально с помощью Cassini в моем опыте, поскольку Cassini разрешает все запросы на маршрутизацию через ASP.NET, в то время как в IIS многие запросы обрабатываются IIS для вас. Это также было бы причиной того, что вы не видите свой код в стеке для этого запроса. Если вы отключите опцию "Только мой код" в Visual Studio, вы можете иногда лучше понять это.

Это не единственная причина, по которой это может произойти, но это обычное явление.

Соответствующая задача - разрешить базовому методу обрабатывать запрос в этих ситуациях. Обычно это простой запрос на файл и не должен влиять на вас.

Проще всего было бы сделать так:

if (controllerType != null)
 {
 return container.Resolve(controllerType) as IController;
 }
 else
 {
 return base.GetControllerInstance(requestContext, controllerType);
 }

Это должно сделать это.

Чтобы узнать, для чего нужен запрос, вы можете проверить HttpContext.Current.Request, чтобы узнать, какой файл отсутствует в вашем маршруте. Много раз это не то, что вам нужно контролировать, но это заставит вас почувствовать себя лучше, чтобы узнать, что такое происхождение запроса.

licensed under cc by-sa 3.0 with attribution.