How I Inject Repository In Service to avoid Error Some services are not able to be constructed or inject service into injected service asp.net core 6 - asp.net-web-api

When I Inject Repository In Service Constructor (This Error Comes ) Some services are not able to be constructed
Program.Cs
builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
builder.Services.AddScoped<IGenreService, GenreService>();
GenreService
public class GenreService : IGenreService
{
private readonly IRepository<GenresDto> _repositoryGenre;
public GenreService( IRepository<GenresDto> repositoryGenre)
{
_repositoryGenre = repositoryGenre;
}

I should register the DbContext in program.cs. So the answer is:
services.AddDbContext(
options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));

Related

How are Exrin services registered to their appropriate models?

After creating a service for a model, how do I tell the model to use that service?
Within the sample Tesla app, there exists constructors which call for a service as an argument:
private readonly IClimateService _service;
public ClimateModel(IExrinContainer exrinContainer, IAuthModel authModel, IClimateService service)
: base(exrinContainer, new ClimateModelState())
{ _service = service; }
I searched but never found where the model receives the service, but I did find this:
protected override void InitServices()
{
RegisterTypeAssembly(typeof(IService), new AssemblyName(nameof(TeslaService)));
base.InitServices();
}
Exrin automatically loads Services, via reflection, if they inherit from
Exrin.Abstraction.IService

Inject service with different configuration into controller

In a Web API application, I have two controllers, MyAController and MyBController, each depending on IMyService but with a different configuration:
public class MyAController : ApiController
{
private readonly IMyService service;
public MyAController(IMyService service)
{
this.service = service;
}
}
public class MyBController : ApiController
{
private readonly IMyService service;
public MyBController(IMyService service)
{
this.service = service;
}
}
public interface IMyService
{
}
public class MyService : IMyService
{
private readonly string configuration;
public MyService(string configuration)
{
this.configuration = configuration;
}
}
I've tried configuring DryIoc the following way:
private enum ServiceKeyEnum
{
ServiceA,
ServiceB
}
container.RegisterInstance("configurationA", serviceKey: "CONFIGURATIONA");
container.RegisterInstance("configurationB", serviceKey: "CONFIGURATIONB");
container.Register<IMyService, MyService>(Reuse.Singleton, Made.Of(() => new MyService(Arg.Of<string>("CONFIGURATIONA"))), serviceKey: ServiceKeyEnum.ServiceA);
container.Register<IMyService, MyService>(Reuse.Singleton, Made.Of(() => new MyService(Arg.Of<string>("CONFIGURATIONB"))), serviceKey: ServiceKeyEnum.ServiceB);
container.Register<MyAController>(Reuse.InResolutionScope, made: Parameters.Of.Details((r, p) => ServiceDetails.IfUnresolvedReturnDefault).Type<IMyService>(serviceKey: ServiceKeyEnum.ServiceA));
container.Register<MyBController>(Reuse.InResolutionScope, made: Parameters.Of.Details((r, p) => ServiceDetails.IfUnresolvedReturnDefault).Type<IMyService>(serviceKey: ServiceKeyEnum.ServiceB));
and if I try to call resolve using:
var controllerA = container.Resolve<MyAController>();
var controllerB = container.Resolve<MyBController>();
I get two controllers configured with configurationA and configurationB respectively.
However, when I try to call the api using a REST call, I get the following error:
An error occurred when trying to create a controller of type 'MyAController'. Make sure that the controller has a parameterless public constructor.
so I guess, that I need to register the controller in a different way... but how?
Any help would be greatly appreciated....
The error is caused by improper setup for controllers. The DryIoc.WebApi extension have already discovered and registered your controllers, so normally you don't need to do it yourself. I will provide the working code (from the question comments) for you specific setup later. But now the reason behind the "parameterless constructor..": when DryIoc fails, WebAPI falls back to using Activator.CreateInstance for controller, which expects parameterless constructor. The fallback masks the original DryIoc error. To find it, you can setup DryIoc.WebApi extension as:
container = container.WithWebApi(throwIfUnresolved: type => type.IsController());
The working setup for your case, which registers dependencies with condition to select controller for injection:
container.Register<IMyService, MyService>(Made.Of(
() => new MyService(Arg.Index<string>(0)), _ => "configurationA"),
Reuse.Singleton,
setup: Setup.With(condition: r => r.Parent.ImplementationType == typeof(MyAController)));
container.Register<IMyService, MyService>(Made.Of(
() => new MyService(Arg.Index<string>(0)), _ => "configurationB"),
Reuse.Singleton,
setup: Setup.With(condition: r => r.Parent.ImplementationType == typeof(MyBController)));
The main thing that this setup does not require special controller registration.
Plus you can avoid using service keys, and no need to register config strings separately.

Am I using correct lifetime managers for dependency injection?

I have an asp.net web api application that uses Unity dependency injection libraries from MS Unity.AspNet.WebApi and Unity nuget packages. Also, the application uses Entity Framework version 6 database context for ORM and a generic repository.
Custom service types are consumed by Api controllers. Custom Service classes consumes EF database contexts and the generic repository.
My question is: Are HierarchicalLifetimeManager and ContainerControlledLifetimeManager correct lifetime managers for my web api application?
Codes in the UnityConfig class of my application:
using System;
using System.Configuration;
using System.Data.Entity;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using App.Api.Models;
using App.Dal;
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
public static void RegisterTypes(IUnityContainer container)
{
var connectionStringEntityFramework= ConfigurationManager.ConnectionStrings["AppEntities"].ToString();
// Entity Framework database context and generic repository
// HierarchicalLifetimeManager is used:
container.RegisterType<DbContext, FirstAngularJsEntities>(new HierarchicalLifetimeManager(), new InjectionConstructor(connectionStringFirstAngularJsEntities));
container.RegisterType<IRepository, GenRepository>(new HierarchicalLifetimeManager(), new InjectionConstructor(typeof(DbContext)));
// services
// ContainerControlledLifetimeManager is used:
container.RegisterType<IContactService, ContactService>(new ContainerControlledLifetimeManager());
container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());
}
A sample api controller has custom service injected in its constructor:
public class ContactApiController : ApiController
{
private readonly IContactService _contactService;
public ContactApiController(IContactService contactService)
{
_contactService = contactService;
}
...
}
A sample custom service has EF DbContext and repository injected in its constructor:
public class ContactService : IContactService
{
private readonly IRepository _repo;
private readonly DbContext _context;
public ContactService(DbContext context, IRepository repo)
{
_context = context;
_repo = repo;
}
...
}
Using ContainerControlledLifetimeManager you'll get singletons of your services. One instance for a long time (untill IIS recycling).
HierarchicalLifetimeManager is used with child containers - create new instance of object for every child container, so you don't create child containers it works like a singleton again :)
The best way for WebApi apllication is using PerRequestLifetimeManager.
Create new instances for every request to Api.
I tend to look at this as what is the shortest lifetime that is compatible with the semantics of what you are trying to do, with the default lifetime being Transient unless otherwise required.
DbContext holds state so we need to be consistent for the request so PerRequest or Hierachic
Repository is/should be stateless since it's state is the DbContext, so Transient
Services is/should be stateless so Transient
One reason for going with Hierarchic rather than PerRequest is that the PerRequest manager does not play well with Owin, see http://www.reply.com/solidsoft-reply/en/content/managing-object-lifetimes-with-owin-and-unity, and you will need to write some cleanup middleware to replace the HttpModule

Ninject Binding Issue with Constructor Chaining

I have a MVC3 project that uses the Entity Framework and Ninject v2.2, and follows the Unit of Work pattern with a Service Layer wrapping my repositories.
After looking at the code below, hopefully its apparent that Ninject is using constructor chaining to inject the correct classes. It currently works prefectly in my application, however I am at the point that I need to bind an instance of IDatabase to MyDatabase with a different scope such as InSingletonScope() or InNamedScope(), not InRequestScope(). I know that I can use the [Named("MyDatabaseScope")] Attribute to customize which IDatabase object is injected, however it seems that with my code structure, if I wanted to inject my SingletonScoped instance, I would have to recreate a new Abstract and Concrete Implementation of my Unit of Work, my Service and all my Repositories, that will then chain down.
Basically my application currently goes
Controller -> Unit of Work -> Database, (Repositories -> Database)
If I have to change my Database Binding, I will now have to create another chain in addition to the current one:
Controller -> New Unit of Work -> SingletonDatabase, (New Repositories-> SingletonDatabase)
This seems to completely defeat the DRY principal. Is there a way to, from the Controller Constructor, inform Ninject that when doing constructor chaining it should use my singleton (or named binding) rather than my request scope binding, without having to recreate all my classes with a Named attribute, or a new Interface?
Sorry for the long text, I wasnt sure if I could get the point across without my code snippets and my somewhat rambling explaination.
Ninject Module Load Function:
..snip..
Bind<IUserServices>().To<UserServices>();
Bind<IBaseServices>().To<BaseServices>();
Bind<IUserRepository>().To<UserRepository>();
Bind(typeof (IRepository<>)).To(typeof (RepositoryBase<>));
Bind<IUnitOfWork>().To<UnitOfWork>();
Bind<IDatabase>().To<MyDatabase>().InRequestScope();
//This is my problem:
//Bind<IDatabase>().To<MySingletonDatabase>().InSingletonScope();
Unit of Work Implementation Constructor:
public class UnitOfWork : IUnitOfWork
{
private IDatabase _database;
public UnitOfWork(IDatabase database,
IUserRepository userRepository,
IPeopleRepository peopleRepository,
)
{
this._database = database;
this.UserRepository = userRepository;
this.PeopleRepository = peopleRepository;
}
protected IDatabase Database
{
get { return _database; }
}
...snip...
}
User Service Layer Implementation Constructor:
public class UserServices : BaseServices, IUserServices
{
private IUnitOfWork _uow;
public UserServices(IUnitOfWork uow)
: base(uow)
{
_uow = uow;
}
...snip...
}
User Repository Constructor:
public class UserRepository : RepositoryBase<User>, IUserRepository
{
public UserRepository(IDatabase database)
: base(database)
{
}
...snip...
}
Controller Constructor:
public IUserServices _userServices { get; set; }
public ActivityController(IUserServices userServices)
{
_userServices = userServices;
}
}
Using Ninject 3.0.0 you can use WhenAnyAncestrorNamed("Some name") But if you need to run asyncronous things you should thing about splitting your application into a web frontend and a server backend. This could make many things easier.

ServiceLocator not initialized in Tests project

When attempting to write a test related to my new Tasks (MVC3, S#arp 2.0), I get this error when I try to run the test:
MyProject.Tests.MyProject.Tasks.CategoryTasksTests.CanConfirmDeleteReadiness:
SetUp : System.NullReferenceException
: ServiceLocator has not been
initialized; I was trying to retrieve
SharpArch.NHibernate.ISessionFactoryKeyProvider
----> System.NullReferenceException : Object reference not set to an
instance of an object.
at
SharpArch.Domain.SafeServiceLocator1.GetService()
at
SharpArch.NHibernate.SessionFactoryKeyHelper.GetKeyFrom(Object
anObject) at
SharpArch.NHibernate.NHibernateRepositoryWithTypedId2.get_Session()
at
SharpArch.NHibernate.NHibernateRepositoryWithTypedId2.Save(T
entity) at
MyProject.Tests.MyProject.Tasks.CategoryTasksTests.Setup()
in
C:\code\MyProject\Solutions\MyProject.Tests\MyProject.Tasks\CategoryTasksTests.cs:line
36
--NullReferenceException at Microsoft.Practices.ServiceLocation.ServiceLocator.get_Current()
at
SharpArch.Domain.SafeServiceLocator1.GetService()
Other tests which do not involve the new class (e.g., generate/confirm database mappings) run correctly.
My ServiceLocatorInitializer is as follows
public class ServiceLocatorInitializer
{
public static void Init()
{
IWindsorContainer container = new WindsorContainer();
container.Register(
Component
.For(typeof(DefaultSessionFactoryKeyProvider))
.ImplementedBy(typeof(DefaultSessionFactoryKeyProvider))
.Named("sessionFactoryKeyProvider"));
container.Register(
Component
.For(typeof(IEntityDuplicateChecker))
.ImplementedBy(typeof(EntityDuplicateChecker))
.Named("entityDuplicateChecker"));
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(container));
}
}
You are registering DefaultSessionFactoryKeyProvider as an implementation of DefaultSessionFactoryKeyProvider, while you have a dependency on ISessionFactoryKeyProvider, which castle windsor doesn't know how to resolve as no implementations has been registered for that interface.
I think that should be:
container.Register(
Component
.For(typeof(ISessionFactoryKeyProvider))
.ImplementedBy(typeof(DefaultSessionFactoryKeyProvider))
.Named("sessionFactoryKeyProvider"));
Is Castle.Core referenced by your test project?

Resources