可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am using AutoMapper 6.2.0 in my ASP.NET MVC 5 application.
When I call my view through controller it shows all things right. But, when I refresh that view, Visual Studio shows an error:
System.InvalidOperationException: 'Mapper already initialized. You must call Initialize once per application domain/process.'
I am using AutoMapper only in one controller. Not made any configuration in any place yet nor used AutoMapper in any other service or controller.
My controller:
public class StudentsController : Controller { private DataContext db = new DataContext(); // GET: Students public ActionResult Index([Form] QueryOptions queryOptions) { var students = db.Students.Include(s => s.Father); AutoMapper.Mapper.Initialize(cfg => { cfg.CreateMap<Student, StudentViewModel>(); }); return View(new ResulList<StudentViewModel> { QueryOptions = queryOptions, Model = AutoMapper.Mapper.Map<List<Student>,List<StudentViewModel>>(students.ToList()) }); } // Other Methods are deleted for ease...
Error within controller:

My Model class:
public class Student { [Key] public int Id { get; set; } public string Name { get; set; } public string CNIC { get; set; } public string FormNo { get; set; } public string PreviousEducaton { get; set; } public string DOB { get; set; } public int AdmissionYear { get; set; } public virtual Father Father { get; set; } public virtual Sarparast Sarparast { get; set; } public virtual Zamin Zamin { get; set; } public virtual ICollection<MulaqatiMehram> MulaqatiMehram { get; set; } public virtual ICollection<Result> Results { get; set; } }
My ViewModel Class:
public class StudentViewModel { [Key] public int Id { get; set; } public string Name { get; set; } public string CNIC { get; set; } public string FormNo { get; set; } public string PreviousEducaton { get; set; } public string DOB { get; set; } public int AdmissionYear { get; set; } public virtual FatherViewModel Father { get; set; } public virtual SarparastViewModel Sarparast { get; set; } public virtual ZaminViewModel Zamin { get; set; } }
回答1:
When you refresh the view you are creating a new instance of the StudentsController -- and therefore reinitializing your Mapper -- resulting in the error message "Mapper already initialized".
From the Getting Started Guide
Where do I configure AutoMapper?
If you're using the static Mapper method, configuration should only happen once per AppDomain. That means the best place to put the configuration code is in application startup, such as the Global.asax file for ASP.NET applications.
One way to set this up is to place all of your mapping configurations into a static method.
App_Start/AutoMapperConfig.cs:
public class AutoMapperConfig { public static void Initialize() { Mapper.Initialize(cfg => { cfg.CreateMap<Student, StudentViewModel>(); ... }); } }
Then call this method in the Global.asax.cs
protected void Application_Start() { App_Start.AutoMapperConfig.Initialize(); }
Now you can (re)use it in your controller actions.
public class StudentsController : Controller { public ActionResult Index(int id) { var query = db.Students.Where(...); var students = AutoMapper.Mapper.Map<List<StudentViewModel>>(query.ToList()); return View(students); } }
回答2:
I've used this method before and it worked till version 6.1.1
Mapper.Initialize(cfg => cfg.CreateMap<ContactModel, ContactModel>() .ConstructUsing(x => new ContactModel(LoggingDelegate)) .ForMember(x => x.EntityReference, opt => opt.Ignore()) );
Since version 6.2, this doesn't work any more. To correctly use Automapper create a new Mapper and us this one like this:
var mapper = new MapperConfiguration(cfg => cfg.CreateMap<ContactModel, ContactModel>() .ConstructUsing(x => new ContactModel(LoggingDelegate)) .ForMember(x => x.EntityReference, opt => opt.Ignore())).CreateMapper(); var model = mapper.Map<ContactModel>(this);
回答3:
If you want/need to stick with the static implementation in a unit testing scenario, note that you can call AutoMapper.Mapper.Reset() before calling initialize. Do note that this should not be used in production code as noted in the documentation.
Source: http://docs.automapper.org/en/stable/Configuration.html#resetting-static-mapping-configuration
回答4:
In case you really need to "re-initialize" AutoMapper you should switch to the instance based API to avoid System.InvalidOperationException: Mapper already initialized. You must call Initialize once per application domain/process.
For example, when you are creating the TestServer for xUnit tests you can just set ServiceCollectionExtensions.UseStaticRegistration inside fixure class constructor to false to make the trick:
public TestServerFixture() { ServiceCollectionExtensions.UseStaticRegistration = false; // <-- HERE var hostBuilder = new WebHostBuilder() .UseEnvironment("Testing") .UseStartup<Startup>(); Server = new TestServer(hostBuilder); Client = Server.CreateClient(); }