我在ASP.NET MVC 5应用程序中使用AutoMapper 6.2.0。
当我通过控制器调用我的视图时,它显示所有正确的事情。但是,当我刷新该视图时,Visual Studio会显示错误:
System.InvalidOperationException:' Mapper已初始化。您必须为每个应用程序域/进程调用一次Initialize。'
我只在一个控制器中使用AutoMapper。尚未在任何地方进行任何配置,也未在任何其他服务或控制器中使用AutoMapper。
我的控制器:
admin.auth().verifyIdToken(idToken)...
控制器内的错误:
我的模特课:
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...
我的ViewModel类:
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; }
}
答案 0 :(得分:31)
如果您希望/需要在单元测试场景中坚持使用静态实现,请注意您可以在调用initialize之前调用AutoMapper.Mapper.Reset()
。请注意,这不应该在文档中提到的生产代码中使用。
来源:http://docs.automapper.org/en/stable/Configuration.html#resetting-static-mapping-configuration
答案 1 :(得分: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>();
...
});
}
}
然后在 Global.asax.cs
中调用此方法protected void Application_Start()
{
App_Start.AutoMapperConfig.Initialize();
}
现在您可以(重新)在控制器操作中使用它。
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 :(得分:18)
之前我使用过此方法,直到版本6.1.1
Mapper.Initialize(cfg => cfg.CreateMap<ContactModel, ContactModel>()
.ConstructUsing(x => new ContactModel(LoggingDelegate))
.ForMember(x => x.EntityReference, opt => opt.Ignore())
);
从版本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);
答案 3 :(得分:16)
如果你真的需要&#34;重新初始化&#34; System.InvalidOperationException
您应该switch to the instance based API避免Mapper already initialized. You must call Initialize once per application domain/process.
:TestServer
例如,在为xUnit
测试创建ServiceCollectionExtensions.UseStaticRegistration
时,您只需将fixure
类构造函数中的false
设置为public TestServerFixture()
{
ServiceCollectionExtensions.UseStaticRegistration = false; // <-- HERE
var hostBuilder = new WebHostBuilder()
.UseEnvironment("Testing")
.UseStartup<Startup>();
Server = new TestServer(hostBuilder);
Client = Server.CreateClient();
}
即可:
from to color
1 54770 54771 darkgrey
2 54770 54775 darkgrey
3 54770 54776 darkgrey
4 54770 54774 darkgrey
5 54771 54775 darkgrey
6 54771 54776 darkgrey
7 54771 54774 red
8 54775 54776 darkgrey
9 54775 54774 darkgrey
10 54776 54774 darkgrey
11 110780 110781 darkgrey
12 110780 110783 darkgrey
13 110780 110784 darkgrey
14 110780 110782 darkgrey
15 110781 110783 darkgrey
16 110781 110784 darkgrey
17 110781 110782 darkgrey
18 110783 110784 darkgrey
19 110783 110782 darkgrey
20 110784 110782 darkgrey
21 20285 20286 darkgrey
22 20285 20287 darkgrey
23 20285 20692 red
24 20285 20693 red
25 20286 20287 darkgrey
26 20286 20692 darkgrey
27 20286 20693 darkgrey
28 20287 20692 darkgrey
29 20287 20693 darkgrey
30 83962 83963 darkgrey
31 83962 83964 darkgrey
32 83962 83960 darkgrey
33 83962 83961 red
34 83963 83964 darkgrey
35 83963 83960 darkgrey
36 83963 83961 darkgrey
37 83964 83960 red
38 83964 83961 darkgrey
39 88564 88565 darkgrey
40 88824 88825 darkgrey
41 88824 88826 darkgrey
42 88824 88565 darkgrey
43 88825 88826 darkgrey
44 88825 88565 red
45 88826 88565 darkgrey
46 72276 72272 red
47 72276 72273 darkgrey
48 72276 72274 darkgrey
49 72276 72275 darkgrey
50 111062 111058 darkgrey
51 111062 111059 darkgrey
52 111062 111060 red
53 111062 111061 darkgrey
54 111074 111070 red
55 111074 111071 red
56 111074 111072 darkgrey
57 111074 111073 darkgrey
答案 4 :(得分:6)
对于单元测试,可以将Mapper.Reset()添加到单元测试类中
[TearDown]
public void TearDown()
{
Mapper.Reset();
}
答案 5 :(得分:5)
您可以将自动映射器用作静态API 和实例API , 已经初始化了映射器是静态API中的常见问题,您可以使用 mapper.Reset() 在哪里初始化了映射器,但这根本不是一个答案。
只需尝试使用实例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);
答案 6 :(得分:5)
Automapper 8.0.0版本
AutoMapper.Mapper.Reset();
Mapper.Initialize(
cfg => {
cfg.CreateMap<sourceModel,targetModel>();
}
);
答案 7 :(得分:1)
您可以简单地使用Mapper.Reset()
。
示例:
public static TDestination MapToObject<TSource, TDestination>(TSource Obj)
{
Mapper.Initialize(cfg => cfg.CreateMap<TSource, TDestination>());
TDestination tDestination = Mapper.Map<TDestination>(Obj);
Mapper.Reset();
return tDestination;
}
答案 8 :(得分:0)
如果您在UnitTest中使用Mapper,并且测试多于一项,则可以使用Mapper.Reset()
//Your mapping.
public static void Initialize()
{
Mapper.Reset();
Mapper.Initialize(cfg =>
{
cfg.CreateMap<***>
}
//Your test classes.
[TestInitialize()]
public void Initialize()
{
AutoMapping.Initialize();
}
答案 9 :(得分:0)
如果使用的是MsTest,则可以使用AssemblyInitialize属性,以便仅对该组件(此处为测试组件)配置一次映射。通常会将其添加到控制器单元测试的基类中。
[TestClass]
public class BaseUnitTest
{
[AssemblyInitialize]
public static void AssemblyInit(TestContext context)
{
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.CreateMap<Source, Destination>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.EmailAddress));
});
}
}
我希望这个答案有帮助
答案 10 :(得分:0)
private static bool _mapperIsInitialized = false;
public InventoryController()
{
if (!_mapperIsInitialized)
{
_mapperIsInitialized = true;
Mapper.Initialize(
cfg =>
{
cfg.CreateMap<Inventory, Inventory>()
.ForMember(x => x.Orders, opt => opt.Ignore());
}
);
}
}