尝试创建类型的控制器时发生错误:DI不会注册接口

时间:2017-08-03 14:35:04

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

我是Web API / MVC,Autofac和DI的新手,所以我确定我的手上弄得一团糟。

我有一个控制器,我试图注入一个服务接口依赖。

    [RoutePrefix("api/gameboard")]
    public class GameBoardController : BaseApiController
    {
        private readonly IGameBoardService _service;
        private ApplicationDbContext _con = new ApplicationDbContext();


        public GameBoardController(IGameBoardService service)
        {
            _service = service;
        }

        /*
        Routes
        */
    }

控制器实现了一个基本控制器:

 public class BaseApiController : ApiController
    {

        private ModelFactory _modelFactory;
        private ApplicationUserManager _AppUserManager = null;
        private ApplicationRoleManager _AppRoleManager = null;

        protected ApplicationUserManager AppUserManager
        {
            get
            {
                return _AppUserManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
        }

        public BaseApiController()
        {

        }

        protected ModelFactory TheModelFactory
        {
            get
            {
                if (_modelFactory == null)
                {
                    _modelFactory = new ModelFactory(this.Request, this.AppUserManager);
                }
                return _modelFactory;
            }
        }

        protected IHttpActionResult GetErrorResult(IdentityResult result)
        {
            if (result == null)
            {
                return InternalServerError();
            }

            if (!result.Succeeded)
            {
                if (result.Errors != null)
                {
                    foreach (string error in result.Errors)
                    {
                        ModelState.AddModelError("", error);
                    }
                }

                if (ModelState.IsValid)
                {
                    // No ModelState errors are available to send, so just return an empty BadRequest.
                    return BadRequest();
                }

                return BadRequest(ModelState);
            }

            return null;
        }

        protected ApplicationRoleManager AppRoleManager
        {
            get
            {
                return _AppRoleManager ?? Request.GetOwinContext().GetUserManager<ApplicationRoleManager>();
            }
        }
    }

当在GameBoardController中对使用_service的路线进行任何调用时,我收到以下错误:

{
  "message": "An error has occurred.",
  "exceptionMessage": "An error occurred when trying to create a controller of type 'GameBoardController'. Make sure that the controller has a parameterless public constructor.",
  "exceptionType": "System.InvalidOperationException",
  "stackTrace": "   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n   at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()",
  "innerException": {
    "message": "An error has occurred.",
    "exceptionMessage": "Type 'LearningAngular.Api.Controllers.GameBoardController' does not have a default constructor",
    "exceptionType": "System.ArgumentException",
    "stackTrace": "   at System.Linq.Expressions.Expression.New(Type type)\r\n   at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"
  }
}

如果我打电话给不使用该服务的路线,它可以正常工作。

我使用Autofac来处理我的DI,我尝试了无数次尝试注册使用IGameBoardService;到了我在SO或谷歌上搜索任何我想到的东西已经筋疲力尽了。

当然,如果我执行错误说明并添加无参数构造函数,则错误消失,但_service始终为空。

目前,这就是我配置Autofac的方法。我有一个配置类来处理所有注册:

public class AutofacConfig
    {
        public static IContainer RegisterAutoFac()
        {
            var builder = new ContainerBuilder();

            AddMvcRegistrations(builder);
            AddRegisterations(builder);

            var container = builder.Build();

            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
            GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);

            return container;
        }

        private static void AddMvcRegistrations(ContainerBuilder builder)
        {
            //mvc
            builder.RegisterControllers(Assembly.GetExecutingAssembly());
            builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());
            builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
            builder.RegisterModelBinderProvider();

            //web api
            builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            builder.RegisterModule<AutofacWebTypesModule>();
        }

        private static void AddRegisterations(ContainerBuilder builder)
        {
            builder.RegisterType<GameBoardService>().As<IGameBoardService>();
            builder.RegisterModule(new StandardModule());
        }
    }

StandardModule如下:

public class StandardModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            base.Load(builder);

            // obtain database connection string once and reuse by Connection class
            var conn = ConfigurationManager.ConnectionStrings["DBConnection"];

            // Register Connection class and expose IConnection 
            // by passing in the Database connection information
            builder.RegisterType<Connection>() // concrete type
                .As<IConnection>() // abstraction
                .WithParameter("settings", conn)
                .InstancePerLifetimeScope();

            // Register Repository class and expose IRepository
            builder.RegisterType<Repository>()
                .As<IRepository>()
                .InstancePerLifetimeScope();

            builder.RegisterType<GameBoardService>()
                .As<IGameBoardService> ()
                .InstancePerLifetimeScope();
        }
    }

然后在我的WebApiConfig中,我打电话给AutofacConfig.RegisterAutoFac();

如果我在AutofacConfig中放置一个断点,它会在启动时被点击,所以我知道它正在运行它。从我收集到的所有信息中,我认为我拥有所需的一切,但显然我无法让它发挥作用。可能是我对一些让我遗漏的东西不熟悉,但我不知所措。我已经关注了示例和教程以及多个SO线程,但没有任何作用。

为了让_service在我的控制器中可用,我在这里缺少什么?

额外信息 - 我不知道是否需要,但这是我的GameBoardService及其界面:

public class GameBoardService : IGameBoardService
    {
        private readonly IRepository _repo;
        private GameBoardHelper gameBoard;
        private Cache cache = new Cache();

        public GameBoardService(IRepository repo)
        {
            _repo = repo;
        }

        public bool createGameBoard()
        {
            gameBoard = new GameBoardHelper();
            cache.insertCacheItem("GameBoard", gameBoard);

            return true;
        }

        public List<Card> playCard(int slot, Card card)
        {
            gameBoard = (GameBoardHelper)cache.getCacheItemByName("GameBoard");

            return gameBoard.playCard(slot, card);
        }

        public bool setHand(int player, List<Card> cardList)
        {
            gameBoard = (GameBoardHelper)cache.getCacheItemByName("GameBoard");

            gameBoard.setHand(player, cardList);
            return true;
        }

        public int getTurn()
        {
            gameBoard = (GameBoardHelper)cache.getCacheItemByName("GameBoard");

            return gameBoard.turn;
        }

        public void setTurn(int player)
        {
            gameBoard = (GameBoardHelper)cache.getCacheItemByName("GameBoard");
            gameBoard.turn = player;
        }

        public Slot opponentTurn()
        {
            gameBoard = (GameBoardHelper)cache.getCacheItemByName("GameBoard");

            return gameBoard.opponentTurn();
        }


        public async Task<IEnumerable<GameBoard>> GetGameBoardAsync()
        {
            // execute the stored procedure called GetEmployees
            return await _repo.WithConnection(async c =>
            {
                // map the result from stored procedure to Employee data model
                var results = await c.QueryAsync<GameBoard>("GetEmployees", commandType: CommandType.StoredProcedure);
                return results;
            });
        }
    }

public interface IGameBoardService
    {
        Task<IEnumerable<GameBoard>> GetGameBoardAsync();
        bool createGameBoard();
        List<Card> playCard(int slot, Card card);
        bool setHand(int player, List<Card> cardList);
        int getTurn();
        void setTurn(int player);
        Slot opponentTurn();
    }

1 个答案:

答案 0 :(得分:0)

christophe.chapron所述,您需要使用以下行将API控制器分别注册到MVC控制器:

builder.RegisterApiControllers(Assembly.GetExecutingAssembly‌​());

documentation中所述。