7

I'm having a trouble, making Ninject and WebAPI.All working together. I'll be more specific:
First, I played around with WebApi.All package and looks like it works fine to me.
Second, I added to RegisterRoutes in Global.asax next line:

routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory(), typeof(ContactsApi)));

So the final result was:


public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory(), typeof(ContactsApi)));

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

    ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());

}

Everything seems to be fine, but when I'm trying to redirect user to a specific action, something like:

return RedirectToAction("Index", "Home");

Url in browser is localhost:789/api/contacts?action=Index&controller=Home Which is not good. I swaped lines in RegisterRoute and now it looks:


public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );
            routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory(), typeof(ContactsApi)));
            ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());

        }

Now the redirection works fine, but when I try to access to my API actions, I get error telling me that Ninject couldn't return controller "api" which is absolutely logical, I don't have such controller.

I did search some info how to make Ninject work with WebApi, but everything I found was only for MVC4 or .Net 4.5. By the technical issues I can't move my project to a new platform, so I need to find a working solution for this versions.

This answer looked like a working solution, but when I'm trying to launch project I get compiler error in line

CreateInstance = (serviceType, context, request) => kernel.Get(serviceType);

telling me:

System.Net.Http.HttpRequestMessage is defined in an assembly that is not referenced

and something about adding refference in assembly

System.Net.Http, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35

I have no Idea what to do next, I couldn't find any useful info about ninject with webapi on .NET 4 and MVC3. Any help would be appreciated.

Gericke
  • 2,109
  • 9
  • 42
  • 71
DmitryL
  • 233
  • 1
  • 4
  • 10
  • first, that other post relates to pre-release version of WebApi when it was part of WCF WebApi (now it was moved to MVC4 WebApi changing its whole model).. you're using the final version of WebApi, right? – kabaros Oct 21 '12 at 09:25
  • Yes, I'm using current version: AspNetWebApi 4.0.20710.0 – DmitryL Oct 21 '12 at 09:30
  • are you sure? because ServiceRoute is part of System.ServiceModel that is part of WCF .. are you sure there is no mixup? – kabaros Oct 21 '12 at 10:15
  • No, sincerely I'm not sure. I have mixed with dlls and packages many times. Thanks to answer below I managed to solve many problems. – DmitryL Oct 21 '12 at 10:49
  • yeah, I've been in the same situation. Darin's solution should work but just get rid of System.ServiceModel DLLs and clean your solution, otherwise you'll have mixup that will haunt you back and you could still be using things from wcf that don't apply (like UriTemplates, ServiceOperation attributes and like this line you had for new ServiceRoute) .. it's painful but it's worth doing it sooner rather than later – kabaros Oct 21 '12 at 11:06

1 Answers1

11

Here are a couple of steps I have compiled for you that should get you started:

  1. Create a new ASP.NET MVC 3 project using the Internet Template
  2. Install the following 2 NuGets: Microsoft.AspNet.WebApi and Ninject.MVC3
  3. Define an interface:

    public interface IRepository
    {
        string GetData();
    }
    
  4. And an implementation:

    public class InMemoryRepository : IRepository
    {
        public string GetData()
        {
            return "this is the data";
        }
    }
    
  5. Add an API controller:

    public class ValuesController : ApiController
    {
        private readonly IRepository _repo;
        public ValuesController(IRepository repo)
        {
            _repo = repo;
        }
    
        public string Get()
        {
            return _repo.GetData();
        }
    }
    
  6. Register an API Route in your Application_Start:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
        GlobalConfiguration.Configuration.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    
        routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
    
  7. Add a custom Web API Dependency Resolver using Ninject:

    public class LocalNinjectDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver
    {
        private readonly IKernel _kernel;
    
        public LocalNinjectDependencyResolver(IKernel kernel)
        {
            _kernel = kernel;
        }
    
        public System.Web.Http.Dependencies.IDependencyScope BeginScope()
        {
            return this;
        }
    
        public object GetService(Type serviceType)
        {
            return _kernel.TryGet(serviceType);
        }
    
        public IEnumerable<object> GetServices(Type serviceType)
        {
            try
            {
                return _kernel.GetAll(serviceType);
            }
            catch (Exception)
            {
                return new List<object>();
            }
        }
    
        public void Dispose()
        {
        }
    }
    
  8. Register the custom dependency resolver inside the Create method (~/App_Start/NinjectWebCommon.cs):

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
    
        RegisterServices(kernel);
    
        GlobalConfiguration.Configuration.DependencyResolver = new LocalNinjectDependencyResolver(kernel); 
        return kernel;
    }
    
  9. Configure the kernel inside the RegisterServices method (~/App_Start/NinjectWebCommon.cs):

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IRepository>().To<InMemoryRepository>();
    }        
    
  10. Run the application and navigate to /api/values.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thank you. It really works on separate project. Now I'm trying to import all this code into my working project. Have only one question: should I do something with my NinjectControllerFactory? Should I leave it, or use NinjectWebCommon instead with repositories binding? – DmitryL Oct 21 '12 at 10:24
  • Your simple and easy to follow instructions helped greatly, thanks! – JCherryhomes Mar 25 '13 at 13:21
  • 1
    The LocalNinjectDependencyResolver was the key to my problem. thanks! – Filip Cornelissen Feb 27 '14 at 09:44