The automapper error collection was changed when multiple users create a user

I get the following error, and this error only occurs when several users click the same button. Any help / ideas would be really appreciated:

System.InvalidOperationException: The collection has been modified; enumeration operation cannot be performed. Generated: Wed, 10 Jun 2015 07:29:06 GMT

AutoMapper.AutoMapperMappingException:

Mapping types: User β†’ User ApplicationSecurityManager.Service.User β†’ ApplicationSecurityManager.Models.User

Target Route: User

Initial value: ApplicationSecurityManager.Service.User ---> System.InvalidOperationException: the collection has been changed; enumeration operation cannot be performed. in System.Collections.Generic.List 1.Enumerator.MoveNextRare() at AutoMapper.TypeMap.<get_AfterMap>b__1(Object src, Object dest) at AutoMapper.Mappers.TypeMapObjectMapperRegistry.PropertyMapMappingStrategy.Map(ResolutionContext context, IMappingEngineRunner mapper) at AutoMapper.Mappers.TypeMapMapper.Map(ResolutionContext context, IMappingEngineRunner mapper) at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) --- End of inner exception stack trace --- at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) at AutoMapper.MappingEngine.Map[TDestination](Object source, Action 1 choice) in ApplicationSecurityManager.UserManager.LoadUser (username String) in ApplicationSecurityManager.UserManager.get_AuthenticatedUser () in ApplicationSecurityManager.UsAeManager.sermanager. Infrastructure.ApplicationSecurityAttribute.OnAuthorization (AuthorizationContext fil terContext) in System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters (ControllerContext controllerContext, IList 1 filters, ActionDescriptor actionDescriptor) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult 1.Begin (AsyncCallback callback, object state, Int32 timeout) when System.Web.Mvc.Async.AsyncResultWrapper.Begin [TResult] (AsyncCallback callback, object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate 1 endDelegate, Object tag, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate . Mvc.Controller <. > C__DisplayClass1d.b__17 (AsyncCallback asyncCallback, Object asyncState) with System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult 1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate 1 endDelegate, object tag, Int32 timeout) in System.Web.Mvc.Controller.BeginExecuteCore 1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate ) with System.Web.MvcultAs. WrappedAsyncResult 1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate tag 1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate 1 endgevateDelegate 1 endgevateDelegate System.Web.Mvc.Async.AsyncResultWrapper.Begin (AsyncCallback callback, Object state, Be ginInvokeDelegate beginDelegate, EndInvokeDelegate endDelegate, Object tag) in System.Web.Mvc.Controller.BeginExecute (RequestContext requestContext, AsyncCallback callback, object state) in System.Web.Mvc.MvcHandler <. > C__DisplayClass8.b__2 (AsyncCallback asyncCallback, Object asyncState) when System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult 1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate 1 endDelegate, object tag, Int32 timeout) in System.Web.Mvc.Async.AsyncResultWrapper.Begin 1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate in System.Web.Mvc.MvcHandler.BeginProcessRequest (HttpContextBase httpContext, AsyncCallback callback, object state) in System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute () step IExecutionStep, Boolean & completedSynchronously)

This is the constructor where I think that the problem after installation is the problem, but when debugging I do not get an error.

 Public Sub New(environmentCode As String, applicationCode As String) MyBase.New(environmentCode, applicationCode) SOBaseUrl = System.Configuration.ConfigurationManager.AppSettings(Enums.AppSettingKeys.SOBaseUrl.ToString()) If Not String.IsNullOrEmpty(SOBaseUrl) Then SOBaseUrl = SOBaseUrl.TrimEnd("/") End If 'Setup mapping. Mapper.CreateMap(Of Service.User, Models.User)() _ .ForMember(Function(dest As Models.User) dest.ENumber, Sub(opt) opt.MapFrom(Function(src As Service.User) src.INumber)) _ .AfterMap(Sub(src As Service.User, dest As Models.User) dest.Groups = New List(Of String) Using service = ApplicationSecurityManager.Service.Factory.GetService() Dim applicationPermissions = service.LoadPermissionsForUser(dest.Username, MyBase.EnvironmentCode) If (Not applicationPermissions Is Nothing AndAlso applicationPermissions.Any(Function(x) x.Code = MyBase.ApplicationCode)) Then dest.Groups = applicationPermissions.Single(Function(x) x.Code = MyBase.ApplicationCode).GroupNames.ToList() End If End Using End Sub) 

Display attachments:

 container.RegisterType(Of IUserManager, UserManager)(New PerThreadLifetimeManager(), New InjectionConstructor( ConfigurationManager.AppSettings(Common.Enums.AppSettingKeys.Environment.ToString()), ConfigurationManager.AppSettings(Common.Enums.AppSettingKeys.ApplicationCode.ToString())) ) 

An saveUserResponse occurs in saveUserResponse .

  Public Function Create(user As Common.Models.User, approve As Boolean) As SO.Common.Models.User Implements IUserProvider.Save Dim saveUserResponse = UserManager.SaveUser(Mapper.Map(Of ApplicationSecurityManager.Service.User)(user)) If Not String.IsNullOrEmpty(saveUserResponse.ErrorMessage) Then 'The Security system returned an error. Throw New Exception("Security Service returned error: " & saveUserResponse.ErrorMessage) End If 'Return the username. Return Mapper.Map(Of Common.Models.User)(saveUserResponse.User) End Function 
+5
source share
2 answers

This is because multiple users modify the same user.Groups directory in the AfterMap () method of your mapping. To avoid this, block the code that processes the collection. For instance:

 'class level object private object _myLock = New object() 'Setup mapping. Mapper.CreateMap(Of Service.User, Models.User)() _ .ForMember(Function(dest As Models.User) dest.ENumber, Sub(opt) opt.MapFrom(Function(src As Service.User) src.INumber)) _ .AfterMap(Sub(src As Service.User, dest As Models.User) SyncLock _myLock dest.Groups = New List(Of String) Using service = ApplicationSecurityManager.Service.Factory.GetService() Dim applicationPermissions = service.LoadPermissionsForUser(dest.Username, MyBase.EnvironmentCode) If (Not applicationPermissions Is Nothing AndAlso applicationPermissions.Any(Function(x) x.Code = MyBase.ApplicationCode)) Then dest.Groups = applicationPermissions.Single(Function(x) x.Code = MyBase.ApplicationCode).GroupNames.ToList() End If End Using End SyncLock End Sub) 
+1
source

This is a fairly common mistake modifying a collection when iterating over it. Is it possible that you leave something here, we cannot see? In any case, the code you provided does not have such a scenario from what I see. This means that you can invoke this in a multi-threaded environment, and the collection will be modified in another thread.

What you can try?

Look at the lock on your enumeration to access one thread at a time. It is possible that it is accessed several times when the user clicks a button.

Here is a good link to help you: http://weblogs.asp.net/leftslipper/mvc-locking-the-routecollection

+1
source

All Articles