There are many articles where people writing about how to use WebAPI + Owin, much less talking about Owin + Ninject and very little gathering all together. Also in these rare articles I couldn't find working solution, so I decided to put all eggs in one basket and write how to use WebAPI + Owin + Ninject. It's very strange that most of the posts talking about using Unity, not Ninject, which I love the most (think not only I).
First, let's prepare our environment, I'm using Visual Studio 2013, but if you are still VS2012 user, you can download ASP.NET and Web Tools 2013.1 for Visual Studio 2012 from Microsoft site. Now we are ready to rock!
1. Create new solution. Choose Empty ASP.NET Web application
2. Download required packages from NuGet. I prefer to use Package Manager Console rather than UI form (hello from 90th). Also we won't download all packages at once, to understand what libraries will be needed at every step.
2. Download required packages from NuGet. I prefer to use Package Manager Console rather than UI form (hello from 90th). Also we won't download all packages at once, to understand what libraries will be needed at every step.
Install-Package Microsoft.AspNet.WebApi.Owin Install-Package Microsoft.Owin.Host.SystemWeb
3. Create in you root directory file Startup.cs, which will be fired once when application starts.
HttpConfiguration responsible for API routes. Routes itself described in WebApiConfig class, which will be automatically created with selected template.public class Startup { public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); WebApiConfig.Register(config); app.UseWebApi(config); } }
Extension method UseWebApi allow us to wire up ASP.NET Web API to our Owin server pipeline.
4. Since we use Startup.cs for start-up configuring, feel free to delete Global.asax file
5. Add an interface for the service, the actual service and controller where our service will be injected
HomeController.cs
[RoutePrefix("api/home")] public class HomeController : ApiController { private readonly IFakeService _fakeService; public HomeController(IFakeService fakeService) { _fakeService = fakeService; } [Route("")] public IHttpActionResult Index(string question) { if (_fakeService.GetAnswer(question)) return Ok(); return BadRequest(); } }IFakeService.cs
public interface IFakeService { bool GetAnswer(string question); }FakeService.cs
public class FakeService : IFakeService { public bool GetAnswer(string question) { return question.Contains("Is"); } }
6. Now it's time to install Ninject and related extensions
Install-Package Ninject.Web.Common.OwinHost Install-Package Ninject.Web.WebApi.OwinHost
7. And the final steps to make all stuff works.
Create NinjectConfig.cs file
public static class NinjectConfig { public static Lazy<IKernel>Add dependency assembly to section runtime of Web.configCreateKernel = new Lazy<IKernel> (() => { var kernel = new StandardKernel(); kernel.Load(Assembly.GetExecutingAssembly()); RegisterServices(kernel); return kernel; }); private static void RegisterServices(KernelBase kernel) { kernel.Bind<IFakeService> () .To<FakeService> (); } }
<dependentAssembly> <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.2.2.0" /> </dependentAssembly>Change Startup.cs file this way
public class Startup { public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); WebApiConfig.Register(config);app.UseWebApi(config);app.UseNinjectMiddleware(() => NinjectConfig.CreateKernel.Value); app.UseNinjectWebApi(config); } }
That's all. Now you can send POST request to your controller like this
Full code available on github
http://localhost:PORT/api/home?question=QUESTION_STRINGand see there is no error with absence parameterless public constructor. Happy coding!
Full code available on github
For some reason package manager installs 3.2.0.0 of ninject libraries and it errors out on app.UseNinjectMiddleware. Once I force it to install 3.2.4.0 then it finally started working.
ReplyDeleteVery interesting, I'll take it into account for researching this problem.
DeleteMany thanks!
ReplyDeleteWould this take care of automatically disposing of resources for classes that implement the IDisposable interface?
ReplyDeleteI'm not sure I understood your question correct. Could you specify what kind of classes do you mean, please?
DeleteHow about to use ninject with custom attribute like:
ReplyDeletepublic class HMACAuthenticationAttribute : Attribute, IAuthenticationFilter{....}
It's all up to you. I haven't considered the question of authorization here.
DeleteThank a lot
ReplyDelete