我是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();
}
答案 0 :(得分:0)
如christophe.chapron所述,您需要使用以下行将API控制器分别注册到MVC控制器:
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
如documentation中所述。