Reputation: 1155
We are configuring automapper for my asp.net MVC/Web API project in the method definition as follows.
public HttpResponseMessage GetDetails(int assignmentId)
{
var valuation = _valuationRepository.GetOneById(assignmentId);
Mapper.CreateMap<UserLicenses, UserLicenseResponseModel>()
.ForMember(dest => dest.State, opt => opt.MapFrom(src => src.States.StateCode))
.ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.UserId))
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src => (src.UserProfile != null) ? (src.UserProfile.FirstName + ' ' + src.UserProfile.LastName) : " "));
Mapper.CreateMap<AdditionalExpenses, AdditionalExpensesResponseModel>();
Mapper.CreateMap<ValuationAssignment, ValuationAssignmentResponseModel>();
var model = Mapper.Map<ValuationAssignmentResponseModel>(valuationAssignment);
return Request.CreateResponse(HttpStatusCode.OK, new { Assignment = model });
}
We are noticing that api is randomly not mapping values and response json is returning null values for the mapped fields.
When this happens I'm recycling the app pool and it seems to work for a period of time and we run into the issue again.
Documentation refers to storing all the mappings in Application_Start in Global.asax. However, we are setting them in the method definition - Is that why we are seeing this issue?
Upvotes: 1
Views: 1168
Reputation: 39025
The problem is that Web applications are threaded, and Automapper is not fully thread safe. i.e. there are methods and classes that are thread safe, and others that are not. If you use the static class Mapper
, it can happen that while one thread is trying to map an object the other is trying to redefine the mapping, and that's why you get those random errors.
As Jasen tells in his comment, and you yourself say in your question, one solution is to define all the mappings in a central location, only once, and before the first requests are executed, usually in Application_Start
.
Another option is to use non static classes from AutoMapper. I.e. instead of using Mapper
use other non static classes. In this way each thread has its own instances and thread safety is not a concenr. For more information on the problem, and this alternative solution, please see also this Q&A: Is Mapper.Map in AutoMapper thread-safe?.
By the way, from the performace point of view it's much better to define the mappings only once and reuse them, instead of redefining them all the time. Most probably AutoMapper
uses Reflection, and, if so, caching the types and properties informations is very advisable not to degrade performance.
Upvotes: 1