Custom Routing and ASP.NET MVC Dependencies

In my ASP.NET MVC 3 application, I have a route restriction defined 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 use Ninject as an IoC container for my application that 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 restriction with a friendly dependency injection?

EDIT

I cannot find a way to pass this dependency to 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"]); } 
+5
source share
3 answers
 routes.MapRoute( "Countries", "countries/{country}", new { controller = "Countries", action = "Index" }, new { country = new CountryRouteConstraint( DependencyResolver.Current.GetService<ICountryRepository<Country>>() ) } ); 
+4
source

While the proposed @Darin approach works, nested dependencies should stay alive throughout the life of the application. If, for example, the dependency area depends on the request area, then it will work for the first request, and not for each request after that.

You can get around this using a very simple DI wrapper for route restrictions.

 public class InjectedRouteConstraint<T> : IRouteConstraint where T : IRouteConstraint { private IDependencyResolver _dependencyResolver { get; set; } public InjectedRouteConstraint(IDependencyResolver dependencyResolver) { _dependencyResolver = dependencyResolver; } public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { return _dependencyResolver.GetService<T>().Match(httpContext, route, parameterName, values, routeDirection); } } 

then create your routes like this

 var _dependencyResolver = DependencyResolver.Current; //Get this from private variable that you can override when unit testing routes.MapRoute( "Countries", "countries/{country}", new { controller = "Countries", action = "Index" }, new { country = new InjectedRouteConstraint<CountryRouteConstraint>(_dependencyResolver); } ); 

EDIT: tried to make it doable.

+4
source

You can try using property injection and IDependencyResolver

 public class CountryRouteConstraint : IRouteConstraint { [Inject] public ICountryRepository<Country> CountryRepo {get;set;} } 

Not all IoC containers do this well; Ninject is working.

I am not sure if this will work, cannot check it, unfortunately.

Another option is to use a service locator instead, where you create a static object that is responsible for getting the implementation of the interface.

0
source

Source: https://habr.com/ru/post/920533/


All Articles