Automapper - Mapper已初始化错误

Rah*_*Ali 26 asp.net asp.net-mvc automapper automapper-6

我在ASP.NET MVC 5应用程序中使用AutoMapper 6.2.0.

当我通过控制器调用我的视图时,它显示所有正确的事情.但是,当我刷新该视图时,Visual Studio显示错误:

System.InvalidOperationException:'Mapper已初始化.您必须为每个应用程序域/进程调用一次Initialize.

我只在一个控制器中使用AutoMapper.尚未在任何地方进行任何配置,也未在任何其他服务或控制器中使用AutoMapper.

我的控制器:

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...
Run Code Online (Sandbox Code Playgroud)

控制器内出错:

在此输入图像描述

我的Model类:

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; }
}
Run Code Online (Sandbox Code Playgroud)

我的ViewModel类:

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; }
}
Run Code Online (Sandbox Code Playgroud)

das*_*h88 37

如果您希望/需要在单元测试场景中坚持使用静态实现,请注意您可以AutoMapper.Mapper.Reset()在调用initialize之前调用.请注意,这不应该在文档中提到的生产代码中使用.

资料来源:http://docs.automapper.org/en/stable/Configuration.html#resetting-static-mapping-configuration

  • 很好的答案,这极大地帮助了我. (2认同)

Jas*_*sen 22

刷新视图时,您正在创建一个新实例StudentsController- 因此重新初始化Mapper - 导致错误消息"Mapper已初始化".

入门指南

我在哪里配置AutoMapper?

如果您使用静态Mapper方法,则每个AppDomain只应进行一次配置.这意味着放置配置代码的最佳位置是应用程序启动,例如ASP.NET应用程序的Global.asax文件.

设置此方法的一种方法是将所有映射配置放入静态方法中.

App_Start/AutoMapperConfig.cs:

public class AutoMapperConfig
{
    public static void Initialize()
    {
        Mapper.Initialize(cfg =>
        {
            cfg.CreateMap<Student, StudentViewModel>();
            ...
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在Global.asax.cs中调用此方法

protected void Application_Start()
{
    App_Start.AutoMapperConfig.Initialize();
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以(重新)在控制器操作中使用它.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的回答,它解决了我的问题.但是在我的脑海中出现了一个新的问题,在更新AutoMapper之前我的代码工作非常糟糕而没有任何问题.然后,为什么这个初始化规则在之前的版本中没有任何意义,可能是6.1.0.你有什么想法...... ??? (2认同)

小智 19

我之前使用过这种方法,直到版本6.1.1

 Mapper.Initialize(cfg => cfg.CreateMap<ContactModel, ContactModel>()
            .ConstructUsing(x => new ContactModel(LoggingDelegate))
            .ForMember(x => x.EntityReference, opt => opt.Ignore())
        );
Run Code Online (Sandbox Code Playgroud)

从版本6.2开始,这不再起作用了.要正确使用Automapper,请创建一个新的Mapper,我们就像这样:

 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);
Run Code Online (Sandbox Code Playgroud)

  • 好的解决方案 但是为什么Auto mapper会改变其核心配置. (6认同)

Dmi*_*lov 16

如果您确实需要"重新初始化" AutoMapper,则应切换到基于实例的API以避免System.InvalidOperationException:Mapper already initialized. You must call Initialize once per application domain/process.

例如,当您创建TestServerfor xUnit测试时,您可以ServiceCollectionExtensions.UseStaticRegistrationfixure类构造函数中设置false以实现技巧:

public TestServerFixture()
{
    ServiceCollectionExtensions.UseStaticRegistration = false; // <-- HERE

    var hostBuilder = new WebHostBuilder()
        .UseEnvironment("Testing")
        .UseStartup<Startup>();

    Server = new TestServer(hostBuilder);
    Client = Server.CreateClient();
}
Run Code Online (Sandbox Code Playgroud)


Buz*_*zzy 6

对于单元测试,可以将Mapper.Reset()添加到单元测试类中

[TearDown]
public void TearDown()
{
    Mapper.Reset();
}
Run Code Online (Sandbox Code Playgroud)


小智 6

Automapper 8.0.0版本

    AutoMapper.Mapper.Reset();
    Mapper.Initialize(
     cfg => {
         cfg.CreateMap<sourceModel,targetModel>();
       }
    );
Run Code Online (Sandbox Code Playgroud)


Thi*_*ath 5

你可以使用automapper作为Static APIInstance API, 已经初始化的Mapper是Static API中的常见问题,你可以使用mapper.Reset()来 初始化mapper,但这根本不是答案.

只需尝试使用实例API

var students = db.Students.Include(s => s.Father);

var config = new MapperConfiguration(cfg => {
               cfg.CreateMap<Student, StudentViewModel>();        
             });

IMapper iMapper = config.CreateMapper();          
return iMapper.Map<List<Student>, List<StudentViewModel>>(students);
Run Code Online (Sandbox Code Playgroud)