On my ASP.NET MVC 3 App, I have a route constraint defined like below:
public class CountryRouteConstraint : IRouteConstraint {
private readonly ICountryRepository<Country> _countryRepo;
public CountryRouteConstraint(ICountryRepository<Country> countryRepo) {
_countryRepo = countryRepo;
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
//do the database look-up here
//return the result according the value you got from DB
return true;
}
}
I am using Ninject as IoC container on my app which implements IDependencyResolver
and I registered my dependency:
private static void RegisterServices(IKernel kernel) {
kernel.Bind<ICountryRepository<Country>>().
To<CountryRepository>();
}
How can I use this route constraint with a dependency injection friendly manner?
EDIT
I cannot find a way to pass this dependency on unit test:
[Fact]
public void country_route_should_pass() {
var mockContext = new Mock<HttpContextBase>();
mockContext.Setup(c => c.Request.AppRelativeCurrentExecutionFilePath).Returns("~/countries/italy");
var routes = new RouteCollection();
TugberkUgurlu.ReservationHub.Web.Routes.RegisterRoutes(routes);
RouteData routeData = routes.GetRouteData(mockContext.Object);
Assert.NotNull(routeData);
Assert.Equal("Countries", routeData.Values["controller"]);
Assert.Equal("Index", routeData.Values["action"]);
Assert.Equal("italy", routeData.Values["country"]);
}
You can try to use property injection and the
IDependencyResolver
Not all IoC containers play well with this; Ninject works.
I'm not sure whether this will work, can't test this atm unfortunately.
Another option is to use a service locator instead, where you make a static object available that is responsible for retrieving an implementation of the interface.
While the approach @Darin suggested works, the dependencies injected need to stay alive for the entire life of the application. If the scope of the dependency is in request scope, for example, then it will work for the first request then not for every request after that.
You can get around this by using a very simple DI wrapper for your route constraints.
then create your routes like this
EDIT: tried to make it testable.