I'm facing a scenario where I need to inject a service from asp.net core DI container to the constructor of an object created using automapper.
I don't know if this is the best practice but let me explain what I'm trying to accomplish.
I've an asp.net core mvc controller that receives a model parameter, just a POCO, that model needs to be converted into a ViewModel class that contains some business logic, data access etc, in that class object I want to get some info from the injected service, that is the part where I'm having problems, cant figure out how to inject the service from controller to the final ViewModel.
My code at this moment looks something like this.
NewGameModel.cs
namespace MyProject.Shared.Models
{
public class NewGameModel
{
public List<PlayerModel> Players { get; set; }
public bool IsValid => Players.Any();
public NewGameModel()
{
Players = new List<PlayerModel>();
}
}
}
NewGameViewModel.cs
namespace MyProject.Core.ViewModels
{
public class NewGameViewModel
{
private Guid Token = Guid.NewGuid();
private DateTime DateTimeStarted = DateTime.Now;
private readonly IConfiguration _configuration;
public List<PlayerModel> Players { get; set; }
public NewGameViewModel(IConfiguration config)
{
_configuration = config;
}
public string DoSomething()
{
//Do something using _configuration
//Business Logic, Data Access etc
}
}
}
MapperProfile.cs
namespace MyProject.Service
{
public class MapperProfile : Profile
{
public MapperProfile()
{
CreateMap<NewGameModel, NewGameViewModel>();
}
}
}
ASP.NET Core project - Startup.cs
namespace MyProject.Service
{
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton(Configuration);
var autoMapperConfig = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new MapperProfile());
});
var mapper = autoMapperConfig.CreateMapper();
services.AddSingleton(mapper);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
ASP.NET Core project - GameController.cs
namespace MyProject.Service.Controllers
{
[Route("api/[controller]")]
public class GameController : Controller
{
private readonly IConfiguration _configuration;
private readonly IMapper _mapper;
public GameController(IConfiguration config, IMapper mapper)
{
_configuration = config;
_mapper = mapper;
}
[HttpPost]
public IActionResult CreateNewGame([FromBody]NewGameModel model)
{
if (!model.IsValid) return BadRequest();
//Throws error because no constructor parameter was passed
//How to pass the IConfiguration to the destination NewGameViewModel object?
var viewModel = _mapper.Map<NewGameModel, NewGameViewModel>(model);
var result = viewModel.DoSomething();
return CreatedAtRoute("GetGame", new { token = result.GameToken }, result);
}
}
}
I will appreciate your help
For those coming later, the method above is not preferred, as it has state inside profiles. Instead, use the
AutoMapper.Extensions.Microsoft.DependencyInjection
package and inside your startup:Then in your profile, just tell AutoMapper that you want your destination object constructed with the container:
Your controller can then depend in
IMapper
and AutoMapper will use the DI container to construct the view model, and your configuration to ASP.NET Core will just be the one line toservices.AddAutoMapper();
Update the profile to take the configuration as an injected dependency and use
ConstructUsing
when creating the mapping.