I want to use IValueResolver in AutoMapper to map two class, and one value will be take from HttpRequest Context, so I want to use IValueResolver
CreateMap<Dto, ViewModel>().ForMember(x=>x.MemberID, opt=>opt.Mapfrom<SpecialResolver>())
and Resolver is simple
public string Resolve(ViewModel viewModel, Dto dto, string destMember, ResolutionContext context)
{
return "test";
}
inside startup class i put this:
services.AddAutoMapper(typeof(Startup));
but every time I map them for MemberID will throw out error say IServiceProvider been disposed. so how to make these work? I tried inject this SpecialResolver in startup but also not work. BTW, I'm use .net core 3.0
I'm strongly convinced that a bug has crept in your code somewhere and hence your problems. On my side, everything works just fine. I tried to recrete what you are trying to do, based on your question and comments. It will surely differ more or less, but you should be able to grasp the idea and get it going on your own.
I'm starting with a mapping profile, where I'm explicitly specifying usage of HttpContextValueResolver
for MemberId
property of ViewModel
class:
public class MyMappingProfile : Profile
{
public MyMappingProfile()
{
CreateMap<Dto, ViewModel>()
.ForMember(x => x.MemberId, opt => opt.MapFrom<HttpContextValueResolver>());
}
}
Then the value resolver:
public class HttpContextValueResolver : IValueResolver<Dto, ViewModel, string>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextValueResolver(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string Resolve(Dto source, ViewModel destination, string destMember, ResolutionContext context)
{
// Obtain whatever you need from HTTP context.
// Warning! HTTP context may be null.
return _httpContextAccessor.HttpContext?.Request.Path;
}
}
To acess HttpContext outside a controller I used a dedicated for that purpose service called IHttpContextAccessor
. Read more about it in the docs.
It isn't automatically available, so I need to register it in Startup
alongside with the AutoMapper:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAutoMapper(typeof(Startup));
services.AddHttpContextAccessor();
}
Take notice that registering AutoMapper while passing just one type (of Startup), requires that all mapping profiles need to be in the same assembly (project) as the Startup. With mapping profiles in more than one assembly, you need to specify those assemblies or types with a suitable overload of the AddAutoMapper()
method.
And finally usage in an example controller:
public class HomeController : Controller
{
private readonly IMapper mapper;
public HomeController(IMapper mapper)
{
this.mapper = mapper;
}
public IActionResult Index()
{
var source = new Dto
{
MemberID = "123",
};
var result = mapper.Map<ViewModel>(source);
return View();
}
}
And here are the dto and view model I used:
public class Dto
{
public string MemberID { get; set; }
}
public class ViewModel
{
public string MemberId { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With