依赖注入错误

时间:2017-10-04 00:47:05

标签: c# asp.net asp.net-web-api dependency-injection

我尝试为ms sql db创建通用存储库。早些时候我使用mongo db工作过这样的事情。我可以编译项目。但是当我尝试发送请求时,我看到错误:“尝试创建'EmployeeController'类型的控制器时发生错误。确保控制器具有无参数的公共构造函数。”有人可以帮助我吗?

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>();
    }
}

控制器

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);
    }
    }
  }

通用存储库

   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();
    }
}

}

2 个答案:

答案 0 :(得分:1)

我不得不这样做一段时间,并记住它不像使用Web API那样直接用于MVC。

我在unit of work example heregithub project here中发布了详细信息和演示项目。

以下是使用Ninject配置依赖注入的部分。

UnitOfWorkExample.WebApi /控制器/的 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());
        }
    }
}

答案 1 :(得分:0)

默认情况下,ASP.NET不会向控制器中注入任何内容。相反,它会查找匹配的控制器并使用new。所以它需要一个没有参数的默认构造函数的控制器 - 除非你做一些特别的事情来添加DI。

要向控制器添加依赖项注入,您需要注册自定义控制器工厂。工厂应该使用Ninject来实例化控制器,控制器将使用适当的依赖关系自动填充其构造函数参数。这是一个简单的例子(你需要修改它以允许其他控制器类型,以及实现接口的其余部分):

public class CustomControllerFactory : IControllerFactory
{
    public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        return _kernel.Get<EmployeeController>();
    }
} 

您可以在启动时使用以下代码进行注册:

    protected void Application_Start()
    {
        IControllerFactory factory = new CustomControllerFactory();
        ControllerBuilder.Current.SetControllerFactory(factory);
    }

可以找到更多信息here。博客显示您正在看到的错误,然后修复它。