我在哪里配置这个 AutoMapper ASP.NET
Where do I configure this AutoMapper in ASP.NET
我使用的是普通 ASP.NET 而不是 .NET Core。
目前,映射运行良好,但我将以下初始化代码放入 控制器 并在控制器内调用,经过研究这可能不是一个好主意。
所以试图让它创建一个新的 class 来初始化,然后从 Global.asax 调用。但我有一个问题 - 'Mapper' 不包含 'Initialize' 的定义。看起来我正在使用旧版本的 AutoMapper 或其他东西。我在 doco 上读到这个:Configuration should only happen once per AppDomain.这意味着放置配置代码的最佳位置是在应用程序启动时,例如 ASP.NET 应用程序的 Global.asax 文件。通常,配置引导程序 class 在它自己的 class 中,而这个引导程序 class 是从启动方法中调用的。引导程序 class 应该构造一个 MapperConfiguration 对象来配置类型映射。
那么这如何适应我目前的尝试?
我的下一个问题,一旦这个设置正确,我该如何在控制器中调用它呢?
我很感激你 feedback/comment。
谢谢
控制器中的当前配置(可能不是一个好主意 - 但有效):
private MapperConfiguration configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<Activity, ActivityDTO>()
.ForMember(dst => dst.OwnerId, src => src.MapFrom(ol => ol.User.Id))
.ForMember(dst => dst.OwnerName, src => src.MapFrom(ol => ol.User.FirstName + " " + ol.User.LastName))
.ForMember(dst => dst.CategoryName, src => src.MapFrom(ol => ol.Category.Name));
cfg.CreateMap<ActivityDTO, Activity>()
.ForMember(dst => dst.UserId, opt => opt.MapFrom(src => HttpContext.Current.User.Identity.GetUserId()));
});
当前方法调用上面的配置:
var activitiesDTO = await (db.Activities
.Include(b => b.User)
.Include(c => c.Category)
.Where(q => q.UserId == userId)
.ProjectTo< ActivityDTO>(configuration)
.AsQueryable()
.ApplySort(sortfields)
.Skip((pageNumber - 1) * pageSize).Take(pageSize)).ToListAsync();
尝试 - 失败:
AutomapperWebProfile.cs:
public class AutomapperWebProfile : AutoMapper.Profile
{
public AutomapperWebProfile()
{
CreateMap<Activity, ActivityDTO>()
.ForMember(dst => dst.OwnerId, src => src.MapFrom(ol => ol.User.Id))
.ForMember(dst => dst.OwnerName, src => src.MapFrom(ol => ol.User.FirstName + " " + ol.User.LastName))
.ForMember(dst => dst.CategoryName, src => src.MapFrom(ol => ol.Category.Name));
CreateMap<ActivityDTO, Activity>()
.ForMember(dst => dst.UserId, opt => opt.MapFrom(src => HttpContext.Current.User.Identity.GetUserId()));
}
public static void Run()
{
AutoMapper.Mapper.Initialize(a =>
{
a.AddProfile<AutomapperWebProfile>();
});
}
}
Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AutomapperWebProfile.Run();
GlobalConfiguration.Configuration.Formatters
.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
}
经过进一步研究,我想出了这种方法,它与我之前所做的类似,但更适用于任何人:
AutomapperConfig.cs:
public class ClientMappingProfile : Profile
{
public ClientMappingProfile()
{
CreateMap<Activity, ActivityDTO>()
.ForMember(dst => dst.OwnerId, src => src.MapFrom(ol => ol.User.Id))
.ForMember(dst => dst.OwnerName, src => src.MapFrom(ol => ol.User.FirstName + " " + ol.User.LastName))
.ForMember(dst => dst.CategoryName, src => src.MapFrom(ol => ol.Category.Name));
CreateMap<ActivityDTO, Activity>()
.ForMember(dst => dst.UserId, opt => opt.MapFrom(src => HttpContext.Current.User.Identity.GetUserId()));
}
}
public class AutoMapperConfig
{
public MapperConfiguration Configure()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<ClientMappingProfile>();
});
return config;
}
}
XXXController.cs:
public class ActivitiesController : ApiController
{
private ApplicationDbContext db = new ApplicationDbContext();
....
[HttpGet]
[Route("api/v1/Activities/{sortfields=Id}/{pagenumber=1}/{pagesize=10}", Name="GetActivities")]
[CacheOutput(ClientTimeSpan = 60, ServerTimeSpan = 60)]
public async Task<IHttpActionResult> GetActivities(string sortfields, int pageNumber, int pageSize)
{
var config = new AutoMapperConfig().Configure();
...
var activitiesDTO = await (db.Activities
.Include(b => b.User)
.Include(c => c.Category)
.Where(q => q.UserId == userId)
.ProjectTo< ActivityDTO>(config)
.AsQueryable()
.ApplySort(sortfields)
.Skip((pageNumber - 1) * pageSize).Take(pageSize)).ToListAsync();
....
return Ok(Data)
}
}
我可能会将 var config = new AutoMapperConfig().Configure();
移动到公开给任何方法的私有属性中。
有人在用这种方法吗?我看到有些人通过 Global.asax 之类的东西进行配置,比如我所做的失败尝试(原始问题)。再次不确定这种方法是否是旧的解决方案。
你的想法?
我使用的是普通 ASP.NET 而不是 .NET Core。
目前,映射运行良好,但我将以下初始化代码放入 控制器 并在控制器内调用,经过研究这可能不是一个好主意。
所以试图让它创建一个新的 class 来初始化,然后从 Global.asax 调用。但我有一个问题 - 'Mapper' 不包含 'Initialize' 的定义。看起来我正在使用旧版本的 AutoMapper 或其他东西。我在 doco 上读到这个:Configuration should only happen once per AppDomain.这意味着放置配置代码的最佳位置是在应用程序启动时,例如 ASP.NET 应用程序的 Global.asax 文件。通常,配置引导程序 class 在它自己的 class 中,而这个引导程序 class 是从启动方法中调用的。引导程序 class 应该构造一个 MapperConfiguration 对象来配置类型映射。
那么这如何适应我目前的尝试?
我的下一个问题,一旦这个设置正确,我该如何在控制器中调用它呢?
我很感激你 feedback/comment。
谢谢
控制器中的当前配置(可能不是一个好主意 - 但有效):
private MapperConfiguration configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<Activity, ActivityDTO>()
.ForMember(dst => dst.OwnerId, src => src.MapFrom(ol => ol.User.Id))
.ForMember(dst => dst.OwnerName, src => src.MapFrom(ol => ol.User.FirstName + " " + ol.User.LastName))
.ForMember(dst => dst.CategoryName, src => src.MapFrom(ol => ol.Category.Name));
cfg.CreateMap<ActivityDTO, Activity>()
.ForMember(dst => dst.UserId, opt => opt.MapFrom(src => HttpContext.Current.User.Identity.GetUserId()));
});
当前方法调用上面的配置:
var activitiesDTO = await (db.Activities
.Include(b => b.User)
.Include(c => c.Category)
.Where(q => q.UserId == userId)
.ProjectTo< ActivityDTO>(configuration)
.AsQueryable()
.ApplySort(sortfields)
.Skip((pageNumber - 1) * pageSize).Take(pageSize)).ToListAsync();
尝试 - 失败:
AutomapperWebProfile.cs:
public class AutomapperWebProfile : AutoMapper.Profile
{
public AutomapperWebProfile()
{
CreateMap<Activity, ActivityDTO>()
.ForMember(dst => dst.OwnerId, src => src.MapFrom(ol => ol.User.Id))
.ForMember(dst => dst.OwnerName, src => src.MapFrom(ol => ol.User.FirstName + " " + ol.User.LastName))
.ForMember(dst => dst.CategoryName, src => src.MapFrom(ol => ol.Category.Name));
CreateMap<ActivityDTO, Activity>()
.ForMember(dst => dst.UserId, opt => opt.MapFrom(src => HttpContext.Current.User.Identity.GetUserId()));
}
public static void Run()
{
AutoMapper.Mapper.Initialize(a =>
{
a.AddProfile<AutomapperWebProfile>();
});
}
}
Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AutomapperWebProfile.Run();
GlobalConfiguration.Configuration.Formatters
.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
}
经过进一步研究,我想出了这种方法,它与我之前所做的类似,但更适用于任何人:
AutomapperConfig.cs:
public class ClientMappingProfile : Profile
{
public ClientMappingProfile()
{
CreateMap<Activity, ActivityDTO>()
.ForMember(dst => dst.OwnerId, src => src.MapFrom(ol => ol.User.Id))
.ForMember(dst => dst.OwnerName, src => src.MapFrom(ol => ol.User.FirstName + " " + ol.User.LastName))
.ForMember(dst => dst.CategoryName, src => src.MapFrom(ol => ol.Category.Name));
CreateMap<ActivityDTO, Activity>()
.ForMember(dst => dst.UserId, opt => opt.MapFrom(src => HttpContext.Current.User.Identity.GetUserId()));
}
}
public class AutoMapperConfig
{
public MapperConfiguration Configure()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<ClientMappingProfile>();
});
return config;
}
}
XXXController.cs:
public class ActivitiesController : ApiController
{
private ApplicationDbContext db = new ApplicationDbContext();
....
[HttpGet]
[Route("api/v1/Activities/{sortfields=Id}/{pagenumber=1}/{pagesize=10}", Name="GetActivities")]
[CacheOutput(ClientTimeSpan = 60, ServerTimeSpan = 60)]
public async Task<IHttpActionResult> GetActivities(string sortfields, int pageNumber, int pageSize)
{
var config = new AutoMapperConfig().Configure();
...
var activitiesDTO = await (db.Activities
.Include(b => b.User)
.Include(c => c.Category)
.Where(q => q.UserId == userId)
.ProjectTo< ActivityDTO>(config)
.AsQueryable()
.ApplySort(sortfields)
.Skip((pageNumber - 1) * pageSize).Take(pageSize)).ToListAsync();
....
return Ok(Data)
}
}
我可能会将 var config = new AutoMapperConfig().Configure();
移动到公开给任何方法的私有属性中。
有人在用这种方法吗?我看到有些人通过 Global.asax 之类的东西进行配置,比如我所做的失败尝试(原始问题)。再次不确定这种方法是否是旧的解决方案。
你的想法?