ASP.NET MVC Custom Route Constraints and Dependency Injection

青春壹個敷衍的年華 提交于 2019-12-04 08:00:31
routes.MapRoute(
    "Countries",
    "countries/{country}",
    new { 
        controller = "Countries", 
        action = "Index" 
    },
    new { 
        country = new CountryRouteConstraint(
            DependencyResolver.Current.GetService<ICountryRepository<Country>>()
        ) 
    }
);

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.

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 testable.

You can try to use property injection and the IDependencyResolver

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

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!