What is the IHttpControllerFactory replacement for Windsor

1,109 views
Skip to first unread message

talkin...@live.com

unread,
Apr 30, 2012, 2:15:36 AM4/30/12
to Castle Project Users
Hi,

I'm new to using Windsor. I have a new MVC 4 WebAPI project and I'm
using the latest code from GitHub. I need to register my
ApiControllers which are based on IHttpController. However, the
IHttpControllerFactory has been deleted from System.Web.Http/
Dispatcher. [http://aspnetwebstack.codeplex.com/SourceControl/network/
forks/asbjornu/aspnet/changeset/changes/f6a7f35302ba]

How do I go about registering ApiControllers without
IHttpControllerFactory?

John Simons

unread,
Apr 30, 2012, 2:43:04 AM4/30/12
to castle-pro...@googlegroups.com

talkin...@live.com

unread,
Apr 30, 2012, 2:00:38 PM4/30/12
to Castle Project Users
I keep getting an errors trying to implement IHttpControllerActivator
Most recent is on this line --
container.Register(Component.For<IHttpControllerActivator>().ImplementedBy<ContextCapturingControllerActivator>());
Error - "Method 'Create' in type
'My.Utilities.CastleWindsor.ContextCapturingControllerActivator' from
assembly 'My.Utilities, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null' does not have an implementation...

How can I make the Windsor container register my ApiControllers and
all of the Interfaces/Classes (internal & abstract) from the dlls so
all of the solutions work together?

I have three separate solutions each containing a project(s). It is a
requirement that these solutions remain separate and distinct and not
be grouped together under one main solution.
These solutions are supposed to use IoC/Dependency Injection so they
are loosly coupled.

1. First solution - My.Utilities is a class library which contains
various classes/interfaces that are used by multiple projects (castle
windsor, db connections/commands/etc., logging, email, etc.)
2. Second solution - My.Schedule is also a class library that contains
the CRUD for getting a schedule and any business logic that needs to
be done. This project references My.Utilities.
There will eventually be several more solutions like #2 and all will
be referenced by the WebAPI. Each solution will do CRUD on specific
data. All of these will also reference My.Utilities.
3. Third solution - My.Web.Mvc, this uses the two class library dlls
(My.Utilities/MySchedule) as references. This is built with MVC4
WebAPI and uses the latest release of the MVC4 code.

Eventually there will be a part 4 to this project that will probably
need to use Windsor - the phone apps (Mono and JQuery Mobile).

Below is part of the code but should give you an idea of what is going
on:
-----------------------------------------------------------------------------------------------
My.Utilities Solution (Class Library)

using System;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;

namespace My.Utilities.CastleWindsor
{
public class ContextCapturingControllerActivator :
IHttpControllerActivator
{
private readonly IHttpControllerActivator _activator;
private readonly
Func<TaskCompletionSource<HttpControllerContext>> _promiseFactory;

public
ContextCapturingControllerActivator(Func<TaskCompletionSource<HttpControllerContext>>
promiseFactory, IHttpControllerActivator activator)
{
this._activator = activator;
this._promiseFactory = promiseFactory;
}

public IHttpController Create(HttpControllerContext
controllerContext, Type controllerType)
{
this._promiseFactory().SetResult(controllerContext);
return this._activator.Create(controllerContext,
controllerType);
}
}


}


using System.Collections;
using System.Linq;
using Castle.Core.Internal;
using Castle.MicroKernel.Registration;
using Castle.Windsor;

namespace My.Utilities.CastleWindsor
{
public class Windsor
{

public static IWindsorContainer Container { get { return
(Registry.Instance); } }


public static T Resolve<T>()
{
return (Container.Resolve<T>());
}


public static T Resolve<T>(object argumentsAsAnonymousType)
{
return (Container.Resolve<T>(argumentsAsAnonymousType));
}

public static T Resolve<T>(IDictionary arguments)
{
return (Container.Resolve<T>(arguments));
}


public static void Release(object component)
{
Container.Kernel.ReleaseComponent(component);
}

public static T Assemble<T>(T instance) where T : class
{
if (instance != null)
{
// Look for any properties that can be set
instance.GetType().GetProperties()
.Where(property => property.CanWrite &&
property.PropertyType.IsPublic)
.Where(property =>
Container.Kernel.HasComponent(property.PropertyType))
.ForEach(property =>
property.SetValue(instance, Container.Resolve(property.PropertyType),
null));
}
return (instance);
}

/// <summary>
/// Threadsafe singleton
/// </summary>
private class Registry
{
/// <summary>Singleton access to container.</summary>
internal static readonly IWindsorContainer Instance = new
WindsorContainer();

static Registry()
{
//Instance.AddFacility<FactorySupportFacility>();
// Instance.AddFacility<LoggingFacility>(f =>
f.LogUsing(LoggerImplementation.Log4net).WithConfig("log4Net.config"));


Instance.Register(Component.For<IWindsorContainer>().Instance(Instance));
}
}

}
}

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Castle.MicroKernel;

namespace My.Utilities.CastleWindsor
{

public class WindsorControllerFactory : DefaultControllerFactory
{

private readonly IKernel _kernel;

public WindsorControllerFactory(IKernel kernel)
{
this._kernel = kernel;
}

public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}

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

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


namespace My.Utilities.Db
{
/// <summary>
/// A generic interface that abstracts the details of Oracle data
access structure from the client code.
/// </summary>
public interface IDbAccess
{
IDbConnection CreateConnection(string connStr);
}
}

namespace My.Utilities.Db
{
public abstract class DbAccess : IDbAccess
{
public IDbConnection CreateConnection(string connStr)
{
...
}
}
}
-----------------------------------------------------------------------------------------------

My.Web.Mvc Solution (MVC4 WebAPI)

using System.Linq;
using System.Net.Http.Formatting;
using System.Reflection;
using System.Runtime.Serialization.Formatters;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Castle.Windsor;
using My.Utilities.CastleWindsor;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Web.Mvc
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801

public class WebApiApplication : System.Web.HttpApplication
{
public static void
RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?
favicon.ico(/.*)?" });
routes.IgnoreRoute("{*scripts}", new { scripts = @"(.*/)?
scripts/(.*)?" });

routes.MapHttpRoute(
name: "schedule-brief",
routeTemplate: "api/schedule/{ID}/{date}/brief",
defaults: new
{
controller = "Schedule",
action = "GetGeneric"
},
constraints: new
{
}
);

routes.MapHttpRoute(
name: "schedule",
routeTemplate: "api/schedule/{ID}/{date}",
defaults: new
{
controller = "Schedule",
action = "Get"
},
constraints: new
{
}
);


/// <summary>
/// Registers any dependencies for service resolution.
/// </summary>
public void RegisterDependencies(IWindsorContainer container,
HttpConfiguration configuration)
{

configuration.ServiceResolver.SetService(typeof(IControllerFactory),
new WindsorControllerFactory(container.Kernel));
ControllerBuilder.Current.SetControllerFactory(new
WindsorControllerFactory(container.Kernel));
}


protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);


// Dependency Injection / Service Resolver
IWindsorContainer container = Windsor.Container;
Registry.Register(container);
RegisterDependencies(container,
GlobalConfiguration.Configuration);


BundleTable.Bundles.RegisterTemplateBundles();
}

protected void Application_End()
{ Windsor.Container.Dispose(); }
}
}

using System;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
using My.Schedule;
using My.Utilities.CastleWindsor;


namespace Web.Mvc
{
public class Registry
{
public static void Register(IWindsorContainer container)
{
//My.Schedule

container.Register(Component.For<ISchedule>().ImplementedBy(typeof
(Schedule)));

//My.Utilities

container.Register(Component.For<IDbAccess>().ImplementedBy(typeof
(DbAccess)));


container.Register(Component.For<IHttpControllerActivator>().ImplementedBy<ContextCapturingControllerActivator>());

container.Register(Component.For<IHttpControllerActivator>().ImplementedBy<DefaultHttpControllerActivator>());

container.Register(Component.For<Func<TaskCompletionSource<HttpControllerContext>>>().AsFactory());

container.Register(Component.For<TaskCompletionSource<HttpControllerContext>>().LifestylePerWebRequest());

container.Register(Component.For<HttpControllerContext>().UsingFactoryMethod(k
=>k.Resolve<TaskCompletionSource<HttpControllerContext>>().Task.Result).LifestylePerWebRequest());
}
}
}



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using My.Schedule;
using My.Schedule.Models;

namespace Web.Mvc.Controllers
{
public class ScheduleController : ApiController
{
private readonly ISchedule _service;

public ScheduleController(ISchedule service)
{
if (service == null)
{
throw new ArgumentNullException("service");
}

_service = service;
}

public IQueryable GetGeneric(int ID, int date)
{
IList<Sched> schedule = Get(ID, date).ToList();
return (schedule.Select(c => new
{
...//Json formatting
}).AsQueryable());
}

public IQueryable<Sched> Get(int ID, int date)
{

return _service.GetSchedule(ID, date).AsQueryable();
}

}
}

-----------------------------------------------------------------

My.Schedule Solution (Class Library)

using System.Linq;
using System.Text;
using My.Schedule.Models;
using My.Utilities.Db;
using My.Utilities.Logging;


namespace My.Schedule
{
public interface ISchedule
{
IQueryable<Sched> GetSchedule(int ID, int date);
}
}


using System.Collections.Generic;
using System.Linq;
using My.Schedule.Models;
using My.Schedule.Repository;
namespace My.Schedule
{
public class Schedule : ISchedule
{
private readonly IScheduleRepository _repository;

public Schedule()
{
_repository = new ScheduleRepository();
}

public IQueryable<Sched> GetSchedule(int ID, int date)
{
... //business logic
return (schedule.AsQueryable());
}
}
}


using System.Linq;
using MySchedule.Models;

namespace My.Schedule.Repository
{
internal interface IScheduleDbRepository
{
IQueryable<Sched> GetSchedule(int ID, int date);
}
}



using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OracleClient;
using System.Globalization;
using System.Linq;
using System.Configuration;
using System.Text;
using My.Schedule.Models;
using My.Utilties.Db;

namespace My.Schedule.Repository
{
internal class ScheduleDbRepository : IScheduleDbRepository
{

public IQueryable<Sched> GetSchedule(int ID, int date)
{
IList<Sched> schedule = new List<Sched>();

...//connect to database, run sql

return (schedule.AsQueryable());
}
}
}
On Apr 30, 1:43 am, John Simons <johnsimons...@yahoo.com.au> wrote:
> This post may be able to help you:http://blog.ploeh.dk/2012/04/19/WiringHttpControllerContextWithCastle...
>
>
>
>
>
>
>
> On Monday, April 30, 2012 4:15:36 PM UTC+10, talkin...@live.com wrote:
>
> > Hi,
>
> > I'm new to using Windsor.  I have a new MVC 4 WebAPI project and I'm
> > using the latest code from GitHub.  I need to register my
> > ApiControllers which are based on IHttpController.  However, the
> > IHttpControllerFactory has been deleted from System.Web.Http/
> > Dispatcher. [http://aspnetwebstack.codeplex.com/SourceControl/network/
> > forks/asbjornu/aspnet/changeset/changes/f6a7f35302ba<http://aspnetwebstack.codeplex.com/SourceControl/network/forks/asbjor...>]

talkin...@live.com

unread,
Apr 30, 2012, 2:01:21 PM4/30/12
to Castle Project Users
> This post may be able to help you:http://blog.ploeh.dk/2012/04/19/WiringHttpControllerContextWithCastle...
>
>
>
>
>
>
>
> On Monday, April 30, 2012 4:15:36 PM UTC+10, talkin...@live.com wrote:
>
> > Hi,
>
> > I'm new to using Windsor.  I have a new MVC 4 WebAPI project and I'm
> > using the latest code from GitHub.  I need to register my
> > ApiControllers which are based on IHttpController.  However, the
> > IHttpControllerFactory has been deleted from System.Web.Http/
> > Dispatcher. [http://aspnetwebstack.codeplex.com/SourceControl/network/
> > forks/asbjornu/aspnet/changeset/changes/f6a7f35302ba<http://aspnetwebstack.codeplex.com/SourceControl/network/forks/asbjor...>]
Reply all
Reply to author
Forward
0 new messages