Я использую webapi, единство и mvc. Я получаю сообщение об ошибке «Удостоверьтесь, что контроллер имеет беззадачный публичный конструктор». Я видел шаги по подобным проблемам, но до сих пор не могу заставить его работать. Я установил unity.webapi и, кажется, есть все необходимые ссылки:ошибка: убедитесь, что у контроллера есть без параметров публичный конструктор webapi
- Microsoft.Practices.Unity - время выполнения: v4.0.30319, версия: 3.5.0.0
- Microsoft.Practices.Unity.Mvc - время выполнения : v4.0.30319, версия: 3.5.0.0
- Unity.WebApi - время выполнения: v4.0.30319, версия: 5.1.0.0
- System.Web.Http - время выполнения: v4.0.30319, версия: 5.2.2.0
- System.Web.Mvc - runtime: v4.0.30319, версия: 5.2.2.0
Я проверил все соответствует тому, что есть на этом сайте:
Вот что у меня есть:
Bootstrapper:
public static class Bootstrapper
{
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<IDatabaseFactoryHouseDB, DatabaseFactoryHouseDB>(new HierarchicalLifetimeManager());
container.RegisterType<UnitOfWorkHouseDB>();
// repositories
container.RegisterType<IEmployeeRepository, EmployeeRepository>();
// services
container.RegisterType<IEmployeeService, EmployeeService>();
RegisterTypes(container);
return container;
}
public static void RegisterTypes(IUnityContainer container) { }
}
Global.asax:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Database.SetInitializer<HouseDBContext>(null);
Bootstrapper.Initialise();
//required for setting routes in the attributes of a controller method
GlobalConfiguration.Configuration.EnsureInitialized();
}
}
Api c ontroller:
public class EmployeeApiController : ApiController
{
private readonly IEmployeeService employeeService;
public EmployeeApiController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}
// rest of controller
}
WebApiConfig:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// use json strings as the default return value for the app
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
// Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
// To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
// For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
//config.EnableQuerySupport();
// To disable tracing in your application, please comment out or remove the following line of code
// For more information, refer to: http://www.asp.net/web-api
config.EnableSystemDiagnosticsTracing();
}
UnityConfig:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Не уверен, что мне не хватает.
Редактировать: Я заметил, что у меня был класс UnityConfig в папке App_Start. Изучив комментарий Сарати, я понял, что это нельзя назвать. Я заметил мою инициализацию загрузчика в global.asax и добавил UnityConfig.RegisterComponents линии(), так что теперь моя global.asax выглядит следующим образом:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
UnityConfig.RegisterComponents(); // <--- added
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Database.SetInitializer<HouseDBContext>(null);
//Bootstrapper.Initialise(); <-- not using bootstrapper anymore
//required for setting routes in the attributes of a controller method
GlobalConfiguration.Configuration.EnsureInitialized();
}
}
и мой UnityConfig выглядит следующим образом:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IDatabaseFactoryHouseDB, DatabaseFactoryHouseDB>(new HierarchicalLifetimeManager());
//container.RegisterType<IUnitOfWork>();
container.RegisterType<UnitOfWorkHouseDB>();
// repositories
container.RegisterType<IEmployeeRepository, EmployeeRepository>();
// services
container.RegisterType<IEmployeeService, EmployeeService>();
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}
Тем не менее, я все еще получаю ошибку конструктора без параметров. Что забавно, несмотря на то, что я добавил конструктор без параметров:
public class EmployeeApiController : ApiController
{
private readonly IEmployeeService employeeService;
public EmployeeApiController()
: base()
{
}
public EmployeeApiController(IEmployeeService employeeService)
{
this.employeeService = employeeService;
}
}
я все еще получаю ошибку при использовании unityconfig подхода. С bootstrapper я не получил ошибку, но мои службы не были инициализированы.
Я полностью смущен. Каким-то образом я чувствую, что смешиваю MVC и WebApi, и все не так правильно разрешается ...
EDIT 2:
Я смотрел на внутреннее исключение моей ошибки конструктор без параметров и заметил, что это упоминает мой IUnitOfWork класс:
"Resolution of the dependency failed, type = \"AngularMVC.Controllers.EmployeeApiController\", name = \"(none)\".\r\nException occurred while: while resolving.\r\nException is: InvalidOperationException - The current type, AngularMVC.Models.Interfaces.IUnitOfWork, is an interface and cannot be constructed. Are you missing a type mapping?\r\n-----------------------------------------------\r\nAt the time of the exception, the container was:\r\n\r\n Resolving AngularMVC.Controllers.EmployeeApiController,(none)\r\n Resolving parameter \"employeeService\" of constructor AngularMVC.Controllers.EmployeeApiController(AngularMVC.Services.IEmployeeService employeeService)\r\n Resolving AngularMVC.Services.EmployeeService,(none) (mapped from AngularMVC.Services.IEmployeeService, (none))\r\n Resolving parameter \"unitOfWork\" of constructor AngularMVC.Services.EmployeeService(AngularMVC.Models.Repositories.IEmployeeRepository employeeRepository, AngularMVC.Models.Interfaces.IUnitOfWork unitOfWork)\r\n Resolving AngularMVC.Models.Interfaces.IUnitOfWork,(none)\r\n"
, который только это:
public interface IUnitOfWork
{
void Commit();
}
Когда я делаю следующее в своем UnityConfig:
container.RegisterType<IUnitOfWork>();
IUnitOfWork sm = container.Resolve<IUnitOfWork>();
Я получаю ту же ошибку: «Текущий тип, AngularMVC.Models.Interfaces.IUnitOfWork, является интерфейсом и не может быть сконструирован. Вы не нашли отображение типа?»
Используете ли вы UnityConfig.RegisterComponents() в любом месте ? Разве вы не должны регистрировать свои зависимости с контейнером, установленным в GlobalConfiguration.Configuration.DependencyResolver, и использовать его из WebApiConfig.Register()? – Sarathy
У меня был класс под названием UnityConfig в папке App_Start, которая не вызывалась. Я зарегистрировал свои службы в нем, прокомментировал инициализацию bootstrapper в global.asax и добавил UnityConfig.RegisterComponents(), но все же получил ошибку конструктора без параметров. Я чувствую, что неправильно смешиваю с Unity с MVC-контроллерами и webapi, потому что все это отлично работает в MVC. – steveareeno
Я предполагаю, что вы должны регистрировать свою реализацию вместе с интерфейсом, таким как контейнер.RegisterType(); –
Sarathy