如何在ASP.NET Core中设置Automapper

the*_*utz 219 c# automapper asp.net-core

我是.NET的新手,我决定解决.NET Core而不是学习"老方法".我在这里找到了一篇关于为.NET Core设置AutoMapper的详细文章,但新手有更简单的演练吗?

the*_*utz 489

我想到了!这是详细信息:

  1. 通过NuGet将主AutoMapper包添加到您的解决方案中.
  2. 通过NuGet将AutoMapper依赖注入包添加到您的解决方案中.

  3. 为映射配置文件创建新类.(我在主解决方案目录中创建了一个类,MappingProfile.cs并添加以下代码.)我将使用一个UserUserDto对象作为示例.

    public class MappingProfile : Profile {
        public MappingProfile() {
            // Add as many of these lines as you need to map your objects
            CreateMap<User, UserDto>();
            CreateMap<UserDto, User>();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 然后在Startup.cs如下所示添加AutoMapperConfiguration :

    public void ConfigureServices(IServiceCollection services) {
        // .... Ignore code before this
    
       // Auto Mapper Configurations
        var mappingConfig = new MapperConfiguration(mc =>
        {
            mc.AddProfile(new MappingProfile());
        });
    
        IMapper mapper = mappingConfig.CreateMapper();
        services.AddSingleton(mapper);
    
        services.AddMvc();
    
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 要在代码中调用映射对象,请执行以下操作:

    public class UserController : Controller {
    
        // Create a field to store the mapper object
        private readonly IMapper _mapper;
    
        // Assign the object in the constructor for dependency injection
        public UserController(IMapper mapper) {
            _mapper = mapper;
        }
    
        public async Task<IActionResult> Edit(string id) {
    
            // Instantiate source object
            // (Get it from the database or whatever your code calls for)
            var user = await _context.Users
                .SingleOrDefaultAsync(u => u.Id == id);
    
            // Instantiate the mapped data transfer object
            // using the mapper you stored in the private field.
            // The type of the source object is the first type argument
            // and the type of the destination is the second.
            // Pass the source object you just instantiated above
            // as the argument to the _mapper.Map<>() method.
            var model = _mapper.Map<UserDto>(user);
    
            // .... Do whatever you want after that!
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

我希望这有助于有人开始使用ASP.NET Core!我欢迎任何反馈或批评,因为我还是.NET世界的新手!

  • @theutz你可以将这两个CreateMap行与一个.ReverseMap()结合在一起.也许评论它,但我发现它更直观. (18认同)
  • 这与.net核心1.1一起工作得很好,一旦我升级到.net核心2.0,就不再这样了.我想,我需要明确指定逻辑配置文件类程序集.还在研究如何实现这一目标.更新:答案取决于你的评论,我必须传递typeof类,这是我的个人资料.// services.AddAutoMapper(typeof(Startup)); // < - 较新的automapper版本使用此签名 (7认同)
  • 在步骤3中提及添加"使用AutoMapper"可能会有所帮助.在顶部,以便导入扩展方法. (6认同)
  • 链接的详细文章https://lostechies.com/jimmybogard/2016/07/20/integrating-automapper-with-asp-net-core-di/解释了`Profile`类的定位方式 (3认同)
  • 是的,在最新版本的 AutoMapper 中,您可以非常轻松地注册服务,例如 services.AddAutoMapper(typeof(MappingProfile)); (3认同)
  • 您应该包含MappingProfile的构造函数以包含对CreateMap的调用 (2认同)
  • 在AutoMapper v8和Dependency Injection v5附加组件中,唯一需要的是services.AddAutoMapper();。Startup类的ConfigureServices方法中的行。对我来说,它甚至能够在从属类库项目中找到Profile类。 (2认同)
  • 为什么要添加AutoMapper依赖注入包?您手动添加了映射器服务并且没有使用 services.AddAutoMapper 方法! (2认同)

Sai*_*war 55

步骤将AutoMapper与ASP.NET Core一起使用.

步骤1.从NuGet包安装AutoMapper.Extensions.Microsoft.DependencyInjection.

在此输入图像描述

步骤2.在解决方案中创建一个文件夹,以使映射保持名称"Mappings".

在此输入图像描述

步骤3.添加Mapping文件夹后,我们添加了一个名为" MappingProfile " 的类,这个名称可以是任何独特且易于理解的.

在本课程中,我们将维护所有映射.

在此输入图像描述

步骤4.在启动"ConfigureServices"中初始化Mapper

在Startup Class中,我们需要初始化我们创建的Profile以及Register AutoMapper Service.

  Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());

  services.AddAutoMapper();
Run Code Online (Sandbox Code Playgroud)

代码片段显示我们需要初始化和注册AutoMapper的ConfigureServices方法.

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }


    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });


        // Start Registering and Initializing AutoMapper

        Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
        services.AddAutoMapper();

        // End Registering and Initializing AutoMapper

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    }}
Run Code Online (Sandbox Code Playgroud)

步骤5.获取输出.

要获取Mapped结果,我们需要调用AutoMapper.Mapper.Map并传递Proper Destination和Source.

AutoMapper.Mapper.Map<Destination>(source);
Run Code Online (Sandbox Code Playgroud)

CodeSnippet

    [HttpPost]
    public void Post([FromBody] SchemeMasterViewModel schemeMaster)
    {
        if (ModelState.IsValid)
        {
            var mappedresult = AutoMapper.Mapper.Map<SchemeMaster>(schemeMaster);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用的是 ASP.NET CORE 3.0,请查看本教程如何在 ASP.NET Core 3.0 中设置 AutoMapper https://tutexchange.com/how-to-set-up-automapper-in-asp-net-core-3 -0/ (5认同)
  • 我收到以下错误:''Mapper'不包含'initialize'的定义。我正在使用7.0.0版的AutoMapper.Extensions.Microsoft.DependencyInjection` (4认同)

Gra*_*Cat 35

我想扩展@theutz的答案 - 即这一行:

// services.AddAutoMapper(typeof(Startup));  // <-- newer automapper version uses this signature.
Run Code Online (Sandbox Code Playgroud)

AutoMapper.Extensions.Microsoft.DependencyInjection版本3.2.0中存在一个错误(可能).(我使用的是.NET Core 2.0)

这是在这个 GitHub问题中解决的.如果您继承AutoMapper的Profile类的类存在于程序集之外的Startup类,那么如果您的AutoMapper注入如下所示,它们可能不会被注册:

services.AddAutoMapper();
Run Code Online (Sandbox Code Playgroud)

除非您明确指定要搜索AutoMapper配置文件的程序集.

它可以在你的Startup.ConfigureServices中这样完成:

services.AddAutoMapper(<assembies> or <type_in_assemblies>);
Run Code Online (Sandbox Code Playgroud)

其中"assemblies""type_in_assemblies"指向指定应用程序中的Profile类的程序集.例如:

services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly));
Run Code Online (Sandbox Code Playgroud)

(并且我强调这个词)是由于实现了无参数overaload(来自GitHub的源代码):

public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
     return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
}
Run Code Online (Sandbox Code Playgroud)

我们依赖于CLR已经包含了包含AutoMapper配置文件的JITed程序集,这些配置文件可能是或者可能不是真的,因为它们只在需要时被jitted(在这个 StackOverflow问题中更多的deatils ).

  • 这是最新版本的AutoMapper和AspNetCore的正确答案 (4认同)

Arv*_*tad 27

theutz'这里的答案非常好,我只想补充一点:

如果你让你的映射配置文件继承MapperConfigurationExpression而不是Profile,你可以简单地添加一个测试来验证你的映射设置,这总是很方便:

[Fact]
public void MappingProfile_VerifyMappings()
{
    var mappingProfile = new MappingProfile();

    var config = new MapperConfiguration(mappingProfile);
    var mapper = new Mapper(config);

    (mapper as IMapper).ConfigurationProvider.AssertConfigurationIsValid();
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您不希望映射属性,请使用.Ignore()进行设置。这样,它将迫使您积极考虑处理每种情况-确保在进行更改时不会错过任何内容。实际上超级实用。因此,是的,验证测试是比许多人意识到的更大的安全网。它不是万无一失的,但是它会处理前90%的问题。 (2认同)

mar*_*tcs 16

在最新版本的 asp.net core 中,您应该使用以下初始化:

services.AddAutoMapper(typeof(YourMappingProfileClass));
Run Code Online (Sandbox Code Playgroud)


Vic*_*Vic 14

我喜欢很多答案,尤其是@saineshwar 的答案。我正在使用 .net Core 3.0 和 AutoMapper 9.0,所以我觉得是时候更新它的答案了。

对我有用的是 Startup.ConfigureServices(...) 以这种方式注册服务:

    services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>(), 
                               AppDomain.CurrentDomain.GetAssemblies());
Run Code Online (Sandbox Code Playgroud)

我认为@saineshwar 的其余回答保持完美。但如果有人感兴趣,我的控制器代码是:

[HttpGet("{id}")]
public async Task<ActionResult> GetIic(int id)
{
    // _context is a DB provider
    var Iic = await _context.Find(id).ConfigureAwait(false);

    if (Iic == null)
    {
        return NotFound();
    }

    var map = _mapper.Map<IicVM>(Iic);

    return Ok(map);
}
Run Code Online (Sandbox Code Playgroud)

我的映射类:

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Iic, IicVM>()
            .ForMember(dest => dest.DepartmentName, o => o.MapFrom(src => src.Department.Name))
            .ForMember(dest => dest.PortfolioTypeName, o => o.MapFrom(src => src.PortfolioType.Name));
            //.ReverseMap();
    }
}
Run Code Online (Sandbox Code Playgroud)

- - - 编辑 - - -

在阅读了 Lucian Bargaoanu 评论中链接的文档后,我认为最好稍微改变一下这个答案。

无参数services.AddAutoMapper()(有@saineshwar 答案)不再起作用(至少对我而言)。但是,如果您使用 NuGet 程序集 AutoMapper.Extensions.Microsoft.DependencyInjection,则该框架能够检查所有扩展 AutoMapper.Profile 的类(如我的 MappingProfile)。

因此,在我的情况下,类属于同一个执行程序集,服务注册可以缩短为services.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(更优雅的方法可能是使用这种编码的无参数扩展)。

谢谢,卢西安!

  • http://docs.automapper.org/en/latest/Dependency-injection.html#asp-net-core (2认同)

小智 13

我通过.NET Core 2.2 / Automapper 8.1.1 w / Extensions.DI 6.1.1的这种方式(类似于上面的方式解决了,但我觉得这是一个更干净的解决方案)。

创建MappingProfile.cs类并使用Maps填充构造函数(我计划使用一个类来保存我的所有映射)

    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            CreateMap<Source, Dest>().ReverseMap();
        }
    }
Run Code Online (Sandbox Code Playgroud)

在Startup.cs中,添加以下内容以添加到DI(程序集arg用于保存您的映射配置的类,在我的情况下,它是MappingProfile类)。

//add automapper DI
services.AddAutoMapper(typeof(MappingProfile));

Run Code Online (Sandbox Code Playgroud)

在Controller中,像使用其他任何DI对象一样使用它

    [Route("api/[controller]")]
    [ApiController]
    public class AnyController : ControllerBase
    {
        private readonly IMapper _mapper;

        public AnyController(IMapper mapper)
        {
            _mapper = mapper;
        }

        public IActionResult Get(int id)
        {
            var entity = repository.Get(id);
            var dto = _mapper.Map<Dest>(entity);

            return Ok(dto);
        }
    }


Run Code Online (Sandbox Code Playgroud)

  • 我喜欢你的回答。我认为用“new Type[]{}”包装“MappingProfiles”,如[此答案](/sf/answers/3956316941/)所示,是不必要的。 (2认同)

Bri*_*ice 10

在我的Startup.cs(Core 2.2,Automapper 8.1.1)中

services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });            
Run Code Online (Sandbox Code Playgroud)

在我的数据访问项目中

namespace DAL
{
    public class MapperProfile : Profile
    {
        // place holder for AddAutoMapper (to bring in the DAL assembly)
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的模型定义中

namespace DAL.Models
{
    public class PositionProfile : Profile
    {
        public PositionProfile()
        {
            CreateMap<Position, PositionDto_v1>();
        }
    }

    public class Position
    {
        ...
    }
Run Code Online (Sandbox Code Playgroud)


Nic*_*pei 9

对于 AutoMapper 9.0.0:

public static IEnumerable<Type> GetAutoMapperProfilesFromAllAssemblies()
    {
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            foreach (var aType in assembly.GetTypes())
            {
                if (aType.IsClass && !aType.IsAbstract && aType.IsSubclassOf(typeof(Profile)))
                    yield return aType;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

映射器配置文件:

public class OrganizationProfile : Profile
{
  public OrganizationProfile()
  {
    CreateMap<Foo, FooDto>();
    // Use CreateMap... Etc.. here (Profile methods are the same as configuration methods)
  }
}
Run Code Online (Sandbox Code Playgroud)

在您的启动中:

services.AddAutoMapper(GetAutoMapperProfilesFromAllAssemblies()
            .ToArray());
Run Code Online (Sandbox Code Playgroud)

在控制器或服务中:注入映射器:

private readonly IMapper _mapper;
Run Code Online (Sandbox Code Playgroud)

用法:

var obj = _mapper.Map<TDest>(sourceObject);
Run Code Online (Sandbox Code Playgroud)


Ama*_*har 9

需要安装一个包来设置自动映射器。

dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection

之后 AddAutoMapper 将在服务中可用。

public void ConfigureServices(IServiceCollection services)
{
     services.AddAutoMapper(typeof(Startup));
}
Run Code Online (Sandbox Code Playgroud)

创建从 Employee 类到 EmployeeDTO 的映射器。

using AutoMapper;

public class AutomapperProfile: Profile
{
    public AutomapperProfile()
    {
        //Source to destination.
        CreateMap<Employee,EmployeeDTO>();
    }
}
Run Code Online (Sandbox Code Playgroud)

EmployeeController 从 Employee 映射到 EmployeeDTo

using System.Collections.Generic;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[ApiController()]
public class EmployeeController : ControllerBase
{
    private readonly IMapper _mapper;

    public EmployeeController(IMapper mapper)
    {
        _mapper = mapper;
    }

    [HttpGet]
    public IEnumerable<EmployeeDTO> GetEmployees()
    {
        /* 
        Assume it to be a  service call/database call
        it returns a list of employee, and now we will map it to EmployeeDTO
        */
        var employees = Employee.SetupEmployee();
        var employeeDTO = _mapper.Map<IEnumerable<EmployeeDTO>>(employees);
        return employeeDTO;

    }
}
Run Code Online (Sandbox Code Playgroud)

Employee.cs 供参考

using System.Collections.Generic;

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public int Salary { get; set; }

    public static IEnumerable<Employee> SetupEmployee()
    {
        return new List<Employee>()
        {
            new Employee(){EmployeeId = 1, EmployeeName ="First", Salary=10000},
            new Employee(){EmployeeId = 2, EmployeeName ="Second", Salary=20000},
            new Employee(){EmployeeId = 3, EmployeeName ="Third", Salary=30000},
            new Employee(){EmployeeId = 4, EmployeeName ="Fourth", Salary=40000},
            new Employee(){EmployeeId = 5, EmployeeName ="Fifth", Salary=50000}
        };
    }

}
Run Code Online (Sandbox Code Playgroud)

EmployeeDTO.cs 供参考

public class EmployeeDTO
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)


Aam*_*mir 6

我使用的是AutoMapper 6.1.1和asp.net Core 1.1.2.

首先,定义Automapper的Profile Class继承的Profile类.我创建了IProfile接口,它是空的,目的只是找到这种类的类.

 public class UserProfile : Profile, IProfile
    {
        public UserProfile()
        {
            CreateMap<User, UserModel>();
            CreateMap<UserModel, User>();
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在创建一个单独的类,例如Mappings

 public class Mappings
    {
     public static void RegisterMappings()
     {            
       var all =
       Assembly
          .GetEntryAssembly()
          .GetReferencedAssemblies()
          .Select(Assembly.Load)
          .SelectMany(x => x.DefinedTypes)
          .Where(type => typeof(IProfile).GetTypeInfo().IsAssignableFrom(type.AsType()));

            foreach (var ti in all)
            {
                var t = ti.AsType();
                if (t.Equals(typeof(IProfile)))
                {
                    Mapper.Initialize(cfg =>
                    {
                        cfg.AddProfiles(t); // Initialise each Profile classe
                    });
                }
            }         
        }

    }
Run Code Online (Sandbox Code Playgroud)

现在在Startup.cs文件中的MVC Core web Project中,在构造函数中,调用Mapping类,它将在应用程序加载时初始化所有映射.

Mappings.RegisterMappings();
Run Code Online (Sandbox Code Playgroud)


Tac*_*yon 6

在 .NET 6 中,您需要将以下内容添加到Program.cs文件中:

builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
Run Code Online (Sandbox Code Playgroud)


dal*_*cam 5

对于 ASP.NET Core(使用 2.0+ 和 3.0 测试),如果您更喜欢阅读源文档:https : //github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README.md

否则按照这 4 个步骤工作:

  1. 从 nuget 安装 AutoMapper.Extensions.Microsoft.DependancyInjection。

  2. 只需添加一些配置文件类。

  3. 然后将下面添加到您的 startup.cs 类。 services.AddAutoMapper(OneOfYourProfileClassNamesHere)

  4. 然后只需在您的控制器或您需要的任何地方注入 IMapper:

public class EmployeesController {

    private readonly IMapper _mapper;

    public EmployeesController(IMapper mapper){

        _mapper = mapper;
    }
Run Code Online (Sandbox Code Playgroud)

如果您想现在简单地使用 ProjectTo:

var customers = await dbContext.Customers.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider).ToListAsync()
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

128533 次

最近记录:

5 年,10 月 前