2

Я использую 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

Я проверил все соответствует тому, что есть на этом сайте:

http://www.asp.net/mvc/overview/releases/how-to-upgrade-an-aspnet-mvc-4-and-web-api-project-to-aspnet-mvc-5-and-web-api-2

Вот что у меня есть:

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, является интерфейсом и не может быть сконструирован. Вы не нашли отображение типа?»

+0

Используете ли вы UnityConfig.RegisterComponents() в любом месте ? Разве вы не должны регистрировать свои зависимости с контейнером, установленным в GlobalConfiguration.Configuration.DependencyResolver, и использовать его из WebApiConfig.Register()? – Sarathy

+0

У меня был класс под названием UnityConfig в папке App_Start, которая не вызывалась. Я зарегистрировал свои службы в нем, прокомментировал инициализацию bootstrapper в global.asax и добавил UnityConfig.RegisterComponents(), но все же получил ошибку конструктора без параметров. Я чувствую, что неправильно смешиваю с Unity с MVC-контроллерами и webapi, потому что все это отлично работает в MVC. – steveareeno

+0

Я предполагаю, что вы должны регистрировать свою реализацию вместе с интерфейсом, таким как контейнер.RegisterType (); – Sarathy

ответ

3

С вашего кода, я вижу, что вы используете Unity, как ваш IoC контейнер. IoC контейнер будет обрабатывать инициализацию класса контроллера.

Чтобы IoC контейнер для создания экземпляра вашего контроллера, ваш класс контроллер должен иметь без параметров открытый конструктор (ака конструктор по умолчанию)

public class EmployeeApiController : ApiController 
{ 
    private readonly IEmployeeService employeeService; 

    public EmployeeAPIController() : base() 
    { 
    } 

    public EmployeeApiController(IEmployeeService employeeService) 
    { 
     this.employeeService = employeeService; 
    } 
} 

UPDATE 1:. 18 фев 2015 из кода я не видел реализацию интерфейса IUnitOfWork. единицей работы является p который широко используется в центральном моделировании домена. Как правило, единичный шаблон работы используется вместе с шаблоном хранилища. Целью единицы работы является создание нескольких репозиториев, работающих в одном контексте базы данных.

Из кода, вы регистрируете

//container.RegisterType<IUnitOfWork>(); 
container.RegisterType<UnitOfWorkHouseDB>(); 

Однако, я думаю, вы должны иметь регистрационный код, как это: (я предполагаю, что UnitOfWorkHouseDB является реализация IUnitOfWork)

container.RegisterType<IUnitOfWork, UnitOfWorkHouseDB>(); 

Который подобно тому, как : (EmployeeRepository - это реализация IEmployeeRepository)

// repositories 
container.RegisterType<IEmployeeRepository, EmployeeRepository>(); 

Обычно, когда я использую единицу работы и хранилище шаблон, я буду делать следующую структуру:

IUnitOfWork интерфейс реализации

public interface IUnitOfWork 
{ 
    void Commit(); 
} 

IUnitOfWork:

public class UnitOfWork : IUnitOfWork 
{ 
    //DBContext could your own db context, or a interface, like IDatabaseFactoryHouseDB 
    private DBContext _ctx; 

    public UnitOfWork(DbContext ctx) 
    { 
     _ctx = ctx; 
    } 

    private IEmployeeRepository _EmployeeRepository; 
    public IEmployeeRepository EmployeeRepository 
    { 
     get { return _EmployeeRepository ?? (_EmployeeRepository = new EmployeeRepository(_ctx)); } 
    } 

    private ICustomerRepository _CustomerRepository; 
    public ICustomerRepository CustomerRepository 
    { 
     get { return _CustomerRepository ?? (_CustomerRepository = new CustomerRepository(_ctx)); } 
    } 

    public void Commit() 
    { 
     _ctx.SaveChange(); 
    } 
} 
+0

DOH! Совершенно верно! Я обнаружил, что мой класс UnitOfWork не реализует IUnitOfWork. Неудивительно, что это давало мне припадки. Я не знаю, как я это пропустил. Еще раз спасибо! – steveareeno

Смежные вопросы

 Смежные вопросы