How to set up Ninject DI to create Hyprlinkr RouteLinker instances
asp.net-web-api, dependency-injection, hyprlinkr, ninject
Solution
Register a delegate Function to give you the linker
_kernel.Bind<Func<HttpRequestMessage, IResourceLinker>>()
.ToMethod(context => (request) => new RouteLinker(request));
Inject the delegate
readonly Func<HttpRequestMessage, IResourceLinker> _getResourceLinker;
public controller(Func<HttpRequestMessage, IResourceLinker> getResourceLinker) {
_getResourceLinker = getResourceLinker;
}
Use in your actions
public async Task<Thingy> Get() {
var linker = _getResourceLinker(Request);
linker.GetUri( ... )
}
Problem
I have an MVC4 Web API project and I making use of Mark Seemann's Hyprlinkr component to generate Uris to linked resources. (Customer -> Addresses for example). I have already followed Mark's guide on Dependency injection with Web API (changing appropriately for Ninject) bit I can't quite work out what I should do to inject a IResourceLinker into my controllers. Following Mark's guide my IHttpControllerActivator.Create create method looks like this: ``` IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { var controller = (IHttpController) _kernel.GetService(controllerType); request.RegisterForDispose(new Release(() => _kernel.Release(controller))); return controller; } ``` It is in this method that the Hyprlinkr readme suggests to create the RouteLinker. Unfortunately I'm not sure how to register this with Ninject. I can't just bind like below, as this results in multiple bindings: ``` _kernel.Bind<IResourceLinker>() .ToMethod(context => new RouteLinker(request)) .InRequestScope(); ``` I've got rebind working like this: ``` _kernel.Rebind<IResourceLinker>() .ToMethod(context => new RouteLinker(request)) .InRequestScope(); ``` But I'm concerned that changing the ninject binding graph is potentially a bad thing to do on every request. What is the best way to achieve this? Update following the request from Paige Cook I'm using rebind here: ``` IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { _kernel.Rebind<IResourceLinker>() .ToMethod(context => new RouteLinker(request)) .InRequestScope(); var controller = (IHttpController) _kernel.GetService(controllerType); request.RegisterForDispose(new Release(() => _kernel.Release(controller))); return controller; } ``` IHttpControllerActivator.Create is called on every request. The rest of the bindings are made in the standard way, by standard I mean in the class generated by using the Ninject.MVC3 nuget package. My controller looks like this: ``` public class CustomerController : ApiController { private readonly ICustomerService _customerService; private readonly IResourceLinker _linker; public CustomerController(ICustomerService customerService, IResourceLinker linker) { _customerService = customerService; _linker = linker; } public CustomerModel GetCustomer(string id) { Customer customer = _customerService.GetCustomer(id); if (customer == null) { throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); } return new CustomerModel { UserName = customer.UserName, Firstname = customer.Firstname, DefaultAddress = _linker.GetUri<AddressController>(c => c.Get(customer.DefaultAddressId)), }; } } ```