Reputation: 31
I trying create generic repository for ms sql db. Earlier i worked with something like this but with mongo db. I can compile project. but when i trying sent request i see error: "An error occurred when trying to create a controller of type 'EmployeeController'. Make sure that the controller has a parameterless public constructor." can anybody help me?
namespace TestTask.Util
{public class NinjectDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernelParam)
{
kernel = kernelParam;
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
// repository
kernel.Bind<IEmployeeRepository>().To<EmployeeRepository>();
}
}
controller
namespace TestTask.Controllers
{
[RoutePrefix("api/v1")]
public class EmployeeController : ApiController
{
private readonly IEmployeeRepository _employeeRepository;
public EmployeeController(IEmployeeRepository employeeRepository) : base()
{
_employeeRepository = employeeRepository;
}
[HttpGet]
[Route("getItems")]
public IHttpActionResult GetItems(int take = 8, int skip = 0)
{
if(take<1|| skip < 0)
{
ModelState.AddModelError("Error", "Invalid take or skip params.");
return BadRequest(ModelState);
}
var result = _employeeRepository.Find(x => x.Id >= 0, x=>x.Id, take, skip);
return Ok(result);
}
[HttpGet]
[Route("pageCount")]
public IHttpActionResult PageCount(int itemsInPage)
{
var TotalCount = _employeeRepository.Count(x => x.Id >= 0);
var result = Math.Ceiling((double)TotalCount / (double)itemsInPage);
return Ok(result);
}
}
}
generic repository
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Web;
namespace TestTask.Context
{
public abstract class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
private DefaultConnection context = new DefaultConnection();
public virtual List<TEntity> Find(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, object>> order, int take =50, int skip=0) //where TEntity : class
{
return context.Set<TEntity>().Where(predicate).OrderBy(order).Skip(skip).Take(take).ToList();
}
public virtual int Count(Expression<Func<TEntity, bool>> predicate)
{
return context.Set<TEntity>().Where(predicate).Count();
}
}
}
Upvotes: 0
Views: 127
Reputation: 4701
I had to do this a while back and remember it not being as straight forward with Web API as it is with MVC.
I posted details and a demo project as part of a unit of work example here, and github project here.
Below are the pieces for configuring dependency injection with Ninject.
UnitOfWorkExample.WebApi/Controllers/ProductsController.cs
namespace UnitOfWorkExample.WebApi.Controllers
{
[RoutePrefix("products")]
public class ProductsController : ApiController
{
private IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[Route]
public IHttpActionResult GetProducts()
{
// ensure there are products for the example
if (!_productService.GetAll().Any())
{
_productService.Create(new Product { Name = "Product 1" });
_productService.Create(new Product { Name = "Product 2" });
_productService.Create(new Product { Name = "Product 3" });
}
return Ok(_productService.GetAll());
}
}
}
UnitOfWorkExample.WebApi/App_Start/NinjectWebCommon.cs
namespace UnitOfWorkExample.WebApi.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Extensions.Conventions;
using System.Web.Http;
using UnitOfWorkExample.Domain.Helpers;
using UnitOfWorkExample.Data.Helpers;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <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);
// Install our Ninject-based IDependencyResolver into the Web API config
GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
// unit of work per request
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
// default binding for everything except unit of work
kernel.Bind(x => x.FromAssembliesMatching("*").SelectAllClasses().Excluding<UnitOfWork>().BindDefaultInterface());
}
}
}
UnitOfWorkExample.WebApi/App_Start/NinjectDependencyResolver.cs
namespace UnitOfWorkExample.WebApi.App_Start
{
public class NinjectScope : IDependencyScope
{
protected IResolutionRoot resolutionRoot;
public NinjectScope(IResolutionRoot kernel)
{
resolutionRoot = kernel;
}
public object GetService(Type serviceType)
{
IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
return resolutionRoot.Resolve(request).SingleOrDefault();
}
public IEnumerable<object> GetServices(Type serviceType)
{
IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
return resolutionRoot.Resolve(request).ToList();
}
public void Dispose()
{
IDisposable disposable = (IDisposable)resolutionRoot;
if (disposable != null) disposable.Dispose();
resolutionRoot = null;
}
}
public class NinjectResolver : NinjectScope, IDependencyResolver
{
private IKernel _kernel;
public NinjectResolver(IKernel kernel)
: base(kernel)
{
_kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectScope(_kernel.BeginBlock());
}
}
}
Upvotes: 1
Reputation: 52240
ASP.NET does not inject anything into controllers by default. Instead, it looks for a matching controller and just uses new
. So it needs a controller that has a default constructor with no parameters-- unless you do something special to add DI.
To add dependency injection to your controllers, you need to register a custom controller factory. The factory should use Ninject to instantiate the controller, which will automatically populate its constructor arguments with the appropriate dependencies. Here is a bare bones example (you will need to modify it to allow other controller types, as well as implement the rest of the interface):
public class CustomControllerFactory : IControllerFactory
{
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
return _kernel.Get<EmployeeController>();
}
}
You can register it in startup with code like this:
protected void Application_Start()
{
IControllerFactory factory = new CustomControllerFactory();
ControllerBuilder.Current.SetControllerFactory(factory);
}
More info can be found here. The blogger shows you exactly the error that you are seeing and then fixes it.
Upvotes: 0