Как зарегистрировать контроллер с параметризованным конструктором, программно?(в Виндзорском замке - ASP.NET MVC) - PullRequest
1 голос
/ 25 сентября 2011

Я хочу зарегистрировать контроллеры программно в Global.asax.cs .с MvcContrib.Castle.WindsorControllerFactory

private static IWindsorContainer _Container;

protected virtual void InitializeWindsor()
        {
            try
            {
                if (_Container == null)
                {
                    _Container = new WindsorContainer();
                    ControllerBuilder.Current.SetControllerFactory(new MvcContrib.Castle.WindsorControllerFactory(_Container));

                    RegisterActiveRecord();
                    RegisterRepositories();
                    RegisterServices();  
                    RegisterControllers();
                    RegisterComponents();
                }

Я сделал это с помощью

 private void RegisterControllers()
        {
            try
            {
                _Container.Register(
                    AllTypes.Of<IController>()
                    .FromAssembly(typeof(HomeController).Assembly)
                    .Configure(c => c.LifeStyle.Transient)
                    );

Он отлично работает для всех контроллеров с конструкторами по умолчанию.Но у меня есть контроллер (LoginController) с параметризованным конструктором.

public class LoginController : Controller
    {
        private IUser _User;

        public LoginController(IUser objUser)
        {
            _User = objUser;
        }

Когда я пытался просмотреть его в браузере (http://localhost:2011/Login),, он выдает мне следующую ошибку.

**No parameterless constructor defined for this object**
Stack Trace: 
[MissingMethodException: No parameterless constructor defined for this object.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
   System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
   System.Activator.CreateInstance(Type type) +6
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +491

[InvalidOperationException: An error occurred when trying to create a controller of type 'NAATEELib.Controllers.LoginController'. Make sure that the controller has a parameterless public constructor.]
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +628
   System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +204

Направь меня. Я не хочу изменять файлы .config (xml). Спасибо.

Ответы [ 3 ]

5 голосов
/ 25 сентября 2011

Кажется, вы забыли использовать фабрику контроллеров Windsor (трассировка стека показывает DefaultControllerFactory).

Взгляните на это Windsor - ASP.NET MVC учебник , в частности часть 2 .

РЕДАКТИРОВАТЬ: ОП отредактировал вопрос, код уже использует фабрику контроллеров Windsor MvcContrib.Либо регистрация неверна (рекомендуется использовать RegisterControllers MvcContrib), либо фабрика контроллеров установлена ​​неправильно.

0 голосов
/ 27 сентября 2011

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

У меня есть:

  • Перенесено в System.Web.Mvc 3
  • Используется MVCContrib.Extras.3.0.51.0
  • Написано WindsorControllerFactory, поскольку MVCContrib 3 исключило его.
  • Используется RegisterControllers метод расширения контейнера

public class WindsorControllerFactory : DefaultControllerFactory
{  
    private IWindsorContainer _container;

    /// <summary>
    /// Creates a new instance of the <see cref="WindsorControllerFactory"/> class.
    /// </summary>
    /// <param name="container">The Windsor container instance to use when creating controllers.</param>
    public WindsorControllerFactory(IWindsorContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }

        _container = container;
    }

    protected override IController GetControllerInstance(RequestContext context, Type controllerType)
    {
        if (controllerType == null)
        {
            throw new HttpException(404, string.Format("The controller for path '{0}' could not be found or it does not implement IController.", context.HttpContext.Request.Path));
        }

        var controller = (IController)_container.Resolve(controllerType) as Controller;

        return controller;
    }

    public override void ReleaseController(IController controller)
    {
        var disposable = controller as IDisposable;

        if (disposable != null)
        {
            disposable.Dispose();
        }

        _container.Release(controller);
    }
}

и Global.asax.cs, для регистрации контроллеров,

_Container.RegisterControllers(typeof(HomeController).Assembly);
0 голосов
/ 25 сентября 2011
Решение

tugberk отлично, но если вы хотите простой способ, вы можете определить конструктор без параметров для LoginController и инициализировать его значением по умолчанию, например:

public LoginController():this(new MyUser()) // MyUser is an implementation of IUser
{
}


public LoginController(IUser objUser)
{
     _User = objUser;
}
...