Произошла ошибка при попытке создать контроллер типа: D я не зарегистрирую интерфейс
Я новичок в 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 или Google.
Конечно, если я делаю то, что говорит ошибка, и добавляю конструктор без параметров, ошибка исчезает, но _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());
}
}
И стандартный модуль выглядит следующим образом:
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 ответ
Как упоминалось в christophe.chapron, вам необходимо зарегистрировать свои контроллеры API отдельно для контроллеров MVC со следующей строкой:
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
как описано в документации.