service AutoMapper can't be resolved - c#

this might be a duplicate of Unable to resolve service for type 'AutoMapper.Mapper' but it's been a year since that was asked and I have a slightly different setup, I think.
I have a .NET 5.0 webapi project, that has a startup class that looks like this
public class Startup
{
private readonly IConfiguration _config;
public Startup(IConfiguration config)
{
_config = config;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationServices(_config); //This is to keep the Startup class clean
services.AddControllers();
services.AddCors();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ts.API v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(x => x.AllowAnyHeader().AllowAnyMethod()
.WithOrigins("https://localhost:4200"));
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
I have a separate ApplicationServiceExtension that handles services. This is that class. This is where I call AddAutoMapper. I've tried skipping this and putting it directly into the Startup.cs but that didn't make a difference.
public static class ApplicationServiceExtensions
{
public static IServiceCollection AddApplicationServices(this IServiceCollection services, IConfiguration config)
{
services.AddScoped<IUserRepository, UserRepository>();
services.AddAutoMapper(typeof(AutoMapperProfiles).Assembly);
services.AddDbContext<DataContext>(options =>
{
options.UseSqlServer(config.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("ts.Data"));
});
return services;
}
}
In a separate project (a console project) I handle everything to do with data coming from the database. This is also where I use a UserRepository.cs that extends IUserRepository. I hold all my DTOs there as well as my AutoMapper Profiles. Basically, I don't even need AutoMapper in my webapi project but I don't know how else to get it running other than adding it to the Startup.cs. Maybe I should mention that I'm pretty new to .NET core/5.0 and haven't really used AutoMapper before let alone set it up from scratch.
The error I'm getting looks like this
Unhandled exception. System.AggregateException: Some services are not able to be constructed
(Error while validating the service descriptor 'ServiceType: ts.Data.Interfaces.IUserRepository Lifetime:
Scoped ImplementationType: ts.Data.Repositories.UserRepository': Unable to resolve service for type 'AutoMapper.Mapper'
while attempting to activate 'ts.Data.Repositories.UserRepository'.)
Just in case you would like to see it, here is my UserRepository.
public class UserRepository : IUserRepository
{
private readonly DataContext _context;
private readonly Mapper _mapper;
public UserRepository(DataContext context, Mapper mapper)
{
_mapper = mapper;
_context = context;
}
public async Task<IEnumerable<UserDto>> GetAllAsync()
{
return await _context.Users
.ProjectTo<UserDto>(_mapper.ConfigurationProvider)
.ToListAsync();
}
}
If anyone has any idea why I'm getting this error, I'd really appreciate the help. I've been stuck with this too long and it's probably something super simple too.

Remove Assembly and try.
services.AddAutoMapper(typeof(AutoMapperProfiles));
At the end of the Startup.cs add following method
private static void RegisterServices(IServiceCollection services, IConfiguration config)
{
ApplicationServiceExtensions.AddApplicationServices(services, config);
}
Call RegisterServices and pass services and _config at end of ConfigureServices method.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddCors();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" });
});
RegisterServices(services, _config);
}
And make AddApplicationServices void, move AddAutoMapper to the top
public static class ApplicationServiceExtensions
{
public static void AddApplicationServices(IServiceCollection services, IConfiguration config)
{
services.AddAutoMapper(typeof(AutoMapperProfiles));
services.AddScoped<IUserRepository, UserRepository>();
services.AddDbContext<DataContext>(options =>
{
options.UseSqlServer(config.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("ts.Data"));
});
}
}
Also AutoMapperProfiles should inherit Profile
public class AutoMapperProfiles : Profile
{
public AutoMapperProfiles()
{
CreateMap<Initiative, InitiativeViewModel>();
}
}

Try adding automapper like this:
services.AddAutoMapper(configuration => configuration
.AddProfile<AutoMapperProfiles>(), typeof(Startup));
And inject IMapper instead of Mapper in your UserRepository.

Related

How to solve 'Unable to resolve service for type dbContext while attempting to activate Service' for Blazor WASM?

I am using a Blazor WASM Application with .NET6
Whenever I try to use my service class it gives me this error 'Unable to resolve service for type 'Persistence.Data.DataContext' while attempting to activate 'Services.Customers.CustomerService'.'
Heres my classes (simplified):
Persistence.Data.DataContext:
public class DataContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
// Add configurations
base.OnModelCreating(builder);
builder.ApplyConfiguration(new CustomerConfiguration());
}
}
Services.Customers.CustomerService:
public class CustomerService : ICustomerService
{
private readonly DataContext _dbContext;
public CustomerService(DataContext dbContext)
{
this._dbContext = dbContext;
}
//...
}
Client.Program.cs:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddMudServices();
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<ICustomerService, CustomerService>();
await builder.Build().RunAsync();
Server.Startup.cs:
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
[Obsolete]
public void ConfigureServices(IServiceCollection services)
{
var builder = new SqlConnectionStringBuilder(Configuration.GetConnectionString("DataContext"));
services.AddDbContext<DataContext>(options =>
options.UseSqlServer(builder.ConnectionString)
.EnableSensitiveDataLogging(Configuration.GetValue<bool>("Logging:EnableSqlParameterLogging")));
services.AddControllersWithViews();
services.AddScoped<DataInitializer>();
services.AddRazorPages();
services.AddScoped<ICustomerService, CustomerService>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataInitializer dataInitializer)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Vic API"));
dataInitializer.InitializeData();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
}
Thanks in advance
WebAssemblyHostBuilder projects don't use Startup.cs (and its Configure and ConfigureServices).
Blazor WebAssembly 3.2.0 Preview 1 release now available says:
Move the root component registrations in the Blazor WebAssembly client project from Startup.Configure to Program.cs by calling builder.RootComponents.Add(string selector).
Move the configured services in the Blazor WebAssembly client project from Startup.ConfigureServices to Program.cs by adding services to the builder.Services collection.
Remove Startup.cs from the Blazor WebAssembly client project.
ASP.NET Core Blazor Server with Entity Framework Core (EF Core) says:
The recommended approach to create a new DbContext with dependencies is to use a factory. EF Core 5.0 or later provides a built-in factory for creating new contexts.
and the example app at https://github.com/dotnet/blazor-samples/blob/main/6.0/BlazorServerEFCoreSample/BlazorServerDbContextExample/Program.cs does the registration direcly in main:
builder.Services.AddDbContextFactory<ContactContext>(opt => ...

inject all services in startup.cs, .net core, overloaded

This is more a general question.
But I have a question about injecting services in the startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(opt =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
opt.Filters.Add(new AuthorizeFilter(policy));
})
.AddFluentValidation(config =>
{
config.RegisterValidatorsFromAssemblyContaining<Create>();
});
services.AddApplicationServices(Configuration);
services.AddIdentityServices(Configuration);
}
So anyway I split the services in other file:
public static class StartupExtensionClass
{
public static IServiceCollection AddApplicationServices(this IServiceCollection services,
IConfiguration Configuration)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" });
});
services.AddDbContext<DataContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddCors(opt =>
{
opt.AddPolicy("CorsPolicy", policy =>
{
policy.AllowAnyMethod().AllowAnyHeader().WithOrigins("http://localhost:3000");
});
});
services.AddMediatR(typeof(List.Handler).Assembly);
services.AddAutoMapper(typeof(MappingProfiles).Assembly);
services.AddScoped<IUserAccessor, UserAccessor >();
services.AddScoped<IPhotoAccessor, PhotoAccessor>();
services.Configure<CloudinarySettings>(Configuration.GetSection("Cloudinary"));
return services;
}
But for example if you have hundreds of services. IS that not overloading the application in the start phase?
Because all the services will initialized in the beginning.
Is there not a way just to initialise some services when they will directly been called.
Like lazy loading
Thank you
I believe you are just setting up what the runtime will use when a class of the specified type is asked for....you aren't creating the classes immediately. So if your application just started up, but you never made any request to it, it isn't like 100 classes were just instantiated for no reason.

Autofac configuration for ASP.Net Core 3.1 not working

I am trying to use Autofac with ASP.Net Core 3.1 but I am getting an exception which does not make sense.
I am getting the following exception:
Autofac.Core.Activators.Reflection.NoConstructorsFoundException: 'No accessible constructors were found for the type 'Microsoft.AspNetCore.Mvc.ModelBinding.CompositeBindingSource'.'
I think the issue might be because of the order of services registered but I can't figure out what I am doing wrong. My configuration is as follows:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Startup.cs class
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public ILifetimeScope AutofacContainer { get; private set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDbContext<EShopDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DBConnection")));
services.AddSwaggerGen();
services.AddOptions();
}
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterModule(new AutofacModule());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
this.AutofacContainer = app.ApplicationServices.GetAutofacRoot();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "eShop");
c.RoutePrefix = string.Empty;
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
AutofacModule.cs class
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
// scan all assemblies in current application domain and resolve them on convention
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.AsImplementedInterfaces();
}
}
What am I missing?
I was able to find the problem with the help of examples code...
The problem for me was in the AutofacModule.cs class. I was scanning the assembly incorrectly. Here is the working code.
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
// scan all assemblies in current application domain and resolve them on convention
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.AsImplementedInterfaces();
}
}
Autofac has examples of projects in Github and I found out that their documentation was different from their example code. This is the link of the ASP.Net Core 3.1 Example. for anyone who wants to see the configuration.

unable to inject dependency in .net core 3.1

Hi i am following microsoft docs ...
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#json-configuration-provider
in order to inject configurations as singleton in .NET Core Web API
Here is Program.cs code where i load my configurations:
public class Program
{
public static Dictionary<string, string> arrayDict =
new Dictionary<string, string>
{
{"connString", "Data Source =xxx/xxx;User Id =xxx;Password =xxx"}
};
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(builder =>
{
builder.AddInMemoryCollection(arrayDict);
builder.AddJsonFile(
"appsettings.json", optional: false, reloadOnChange: false);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Here in Startup.cs i use following
public class Startup
{
private readonly IConfiguration Configuration;
public Startup(IConfiguration config)
{
Configuration = config;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<IConfiguration>(Configuration);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Still when i am using dependency injection in my Controller i am unable to inject IConfiguration, and get following error at invoking cotroller action (runtime error):
A suitable constructor for type 'IrisDotNetCore.Controllers.LoginController' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.
LoginController.cs Code:
[Route("api/[controller]")]
[ApiController]
public class LoginController : ControllerBase
{
IConfiguration _configuration;
LoginController(IConfiguration configuration)
{
_configuration = configuration;
}
}
What is possibly wrong here?
Your constructor has to be public or internal - remember that in your situation the instance of the LoginController can't be created (because LoginController method is private). Even the error message (Ensure the type is concrete and services are registered for all parameters of a public constructor) suggests this.

Problem registering object and interface on the startup file more specifically in the ConfigureServices method, the app does not execute

Well, I have created an application to start on ASP net core 3.1 from scratch, I have created an API application and I have already created some layers to have better control on my application, However, when I created my object with its interface and registered them in the startup file on this way:
services.AddScoped<IMySpaceService, MySpaceService>();
I have gotten this error when I run the application:
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MySpaceService.Services.Interfaces.IMySpaceService Lifetime: Scoped ImplementationType:
this is my code:
public class MySpaceService: IMySpaceService
{
private IMySpaceRepository _mySpaceRepository;
public MySpaceService(IMySpaceRepository mySpaceRepository)
{
_mySpaceRepository = mySpaceRepository;
}
public IList<MySpaceDto> getSpaces()
{
List<MySpaceDto> spaces = new List<MySpaceDto>();
var data = _mySpaceRepository.getSpaces();
foreach (var item in data)
{
SpaceDto spaceDto = new SpaceDto();
spaceDto.Identification = item.Identification;
spaceDto.Name = item.Name;
spaces.Add(spaceDto);
}
return spaces;
}
}
My startup code:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<IMySpaceService, MySpaceService>();
services.AddScoped<IMySpaceRepository, MySpaceRepository>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Any Ideas about it?.
Your MySpaceService has only one constructor with parameter IMySpaceRepository. You need to register your repository as well:
services.AddScoped<IMySpaceRepository, MySpaceRepository>();
services.AddScoped<IMySpaceService, MySpaceService>();
Well, definitely the problem was that I had not registered yet a dependency, however, the dependency that I hadn't registered was "Dbcontext" and I am calling it from my repository class on the constructor. Therefore, I have to say that your comments helped me to solve my problem because finally, it was a problem with the dependency that didn't register.
I had to do this on my startup file:
services.AddDbContext<ExampleContext>(
options => options.UseMySql("Server=localhost;port=3306;Database=exampleDB;User=UserRegistered;Password=*******", mySqlOptions => mySqlOptions
.ServerVersion(new ServerVersion(new Version(8, 0, 18), ServerType.MySql))));

Categories