wake-up-neo.net

So richten Sie Automapper in ASP.NET Core ein

Ich bin bei .NET relativ neu, und ich entschied mich für .NET Core, anstatt die "alten Wege" zu lernen. Ich habe hier einen ausführlichen Artikel zum Einrichten von AutoMapper für .NET Core gefunden , aber gibt es eine einfachere Lösung für einen Neuling?

154
theutz

Ich habe es herausgefunden! Hier sind die Details:

  1. Fügen Sie Ihrer Lösung das Haupt-AutoMapper-Paket über NuGet hinzu.
  2. Fügen Sie Ihrer Lösung das AutoMapper Dependency Injection Package über NuGet hinzu.

  3. Erstellen Sie eine neue Klasse für ein Mapping-Profil. (Ich habe im Hauptlösungsverzeichnis eine Klasse mit dem Namen MappingProfile.cs erstellt und den folgenden Code hinzugefügt.) Ich verwende ein User- und ein UserDto-Objekt.

    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>();
        }
    }
    
  4. Fügen Sie dann die AutoMapperConfiguration wie folgt in den Startup.cs hinzu:

    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();
    
    }
    
  5. Gehen Sie wie folgt vor, um das zugeordnete Objekt im Code aufzurufen:

    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!
        }
    }
    

Ich hoffe, das hilft jemandem, der neu mit ASP.NET Core beginnt! Ich freue mich über Feedback oder Kritik, da ich in der .NET-Welt noch neu bin!

391
theutz

Ich möchte die Antworten von @ theutz erweitern - nämlich diese Zeile:

// services.AddAutoMapper(typeof(Startup));  // <-- newer automapper version uses this signature.

Es gibt einen Fehler ( wahrscheinlich) in AutoMapper.Extensions.Microsoft.DependencyInjection Version 3.2.0. (Ich benutze .NET Core 2.0)

Dies wird in der this GitHub-Ausgabe behoben. Wenn Ihre Klassen, die die AutoMapper-Klasse Profile erben, außerhalb der Assembly vorhanden sind, in der sich Ihre Startup-Klasse befindet, werden sie wahrscheinlich nicht registriert, wenn Ihre AutoMapper-Injection folgendermaßen aussieht:

services.AddAutoMapper();

es sei denn, Sie geben ausdrücklich an, nach welchen Assemblys AutoMapper-Profile durchsucht werden sollen.

Dies kann in Ihrem Startup.ConfigureServices folgendermaßen erfolgen:

services.AddAutoMapper(<assembies> or <type_in_assemblies>);

dabei verweisen "Assemblys" und "type_in_assemblies" auf die Assembly, in der Profilklassen in Ihrer Anwendung angegeben sind. Z.B:

services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly));

Ich nehme an (und betone dieses Wort), dass aufgrund der folgenden Implementierung der parameterlosen Überladung (Quellcode von GitHub ) :

public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
     return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
}

wir verlassen uns darauf, dass CLR bereits JITed Assembly enthält, das AutoMapper-Profile enthält, die möglicherweise der Wahrheit entsprechen oder nicht, da sie nur bei Bedarf ausgegeben werden (weitere Details in this StackOverflow question).

27
GrayCat

theutz 'Antwort hier ist sehr gut, ich möchte nur folgendes hinzufügen:

Wenn Sie Ihr Mapping-Profil von MapperConfigurationExpression anstelle von Profile erben lassen, können Sie ganz einfach einen Test hinzufügen, um Ihre Mapping-Einstellungen zu überprüfen.

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

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

    (mapper as IMapper).ConfigurationProvider.AssertConfigurationIsValid();
}
23
Arve Systad

Schritt So verwenden Sie AutoMapper mit ASP.NET Core.

Schritt 1. Installieren von AutoMapper.Extensions.Microsoft.DependencyInjection aus dem NuGet-Paket.

 enter image description here

Schritt 2. Erstellen Sie einen Ordner in Lösung, um Zuordnungen mit dem Namen "Zuordnungen" beizubehalten.

 enter image description here

Schritt 3. Nach dem Hinzufügen des Mapping-Ordners haben wir eine Klasse mit dem Namen "MappingProfile" hinzugefügt. Dieser Name kann eindeutig und gut verständlich sein.

In dieser Klasse werden alle Zuordnungen verwaltet. 

 enter image description here

Schritt 4. Initialisieren von Mapper im Start "ConfigureServices"}

In der Startup-Klasse müssen wir das von uns erstellte Profil initialisieren und auch den AutoMapper-Service registrieren.

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

  services.AddAutoMapper();

Code-Snippet, um die ConfigureServices-Methode anzuzeigen, wo der AutoMapper initialisiert und registriert werden muss.

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);

    }}

Schritt 5. Ausgabe abrufen.

Um ein zugeordnetes Ergebnis zu erhalten, müssen wir AutoMapper.Mapper.Map aufrufen und das richtige Ziel und die richtige Quelle übergeben.

AutoMapper.Mapper.Map<Destination>(source);

Code-Auszug

    [HttpPost]
    public void Post([FromBody] SchemeMasterViewModel schemeMaster)
    {
        if (ModelState.IsValid)
        {
            var mappedresult = AutoMapper.Mapper.Map<SchemeMaster>(schemeMaster);
        }
    }
10
Saineshwar

Ich verwende AutoMapper 6.1.1 und asp.net Core 1.1.2.

Definieren Sie zunächst Profilklassen, die von der Profilklasse des Automappers geerbt werden. Ich habe eine IProfile-Schnittstelle erstellt, die leer ist. Der Zweck besteht nur darin, die Klassen dieses Typs zu finden.

 public class UserProfile : Profile, IProfile
    {
        public UserProfile()
        {
            CreateMap<User, UserModel>();
            CreateMap<UserModel, User>();
        }
    }

Erstellen Sie jetzt eine separate Klasse, z. B. 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
                    });
                }
            }         
        }

    }

Rufen Sie jetzt im MVC Core-Webprojekt in der Datei Startup.cs im Konstruktor die Mapping-Klasse auf, die alle Mappings zum Zeitpunkt der Anwendung Lädt.

Mappings.RegisterMappings();
5
Aamir

Ich habe es auf diese Weise gelöst (ähnlich wie oben, aber ich glaube, es ist eine sauberere Lösung) für .NET Core 2.2/Automapper 8.1.1 mit Extensions.DI 6.1.1.

Erstellen Sie die MappingProfile.cs-Klasse und füllen Sie den Konstruktor mit Maps (ich plane, alle Zuordnungen mit einer einzigen Klasse zu speichern).

    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            CreateMap<Source, Dest>().ReverseMap();
        }
    }

Fügen Sie in Startup.cs Folgendes hinzu, um DI hinzuzufügen (das Assembly-Argument ist für die Klasse, die Ihre Zuordnungskonfigurationen enthält, in meinem Fall die MappingProfile-Klasse).

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

Verwenden Sie es in Controller wie jedes andere DI-Objekt

    [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);
        }
    }


4
Coy Meeks

services.AddAutoMapper (); funktionierte nicht für mich (Ich verwende Asp.Net Core 2.0)

Nach der Konfiguration wie folgt

   var config = new AutoMapper.MapperConfiguration(cfg =>
   {                 
       cfg.CreateMap<ClientCustomer, Models.Customer>();
   });

initialisieren Sie den Mapper IMapper mapper = config.CreateMapper ();

und fügen Sie das Mapper-Objekt Services als Singleton hinzu services.AddSingleton (Mapper);

auf diese Weise kann ich dem Controller ein DI hinzufügen

  private IMapper autoMapper = null;

  public VerifyController(IMapper mapper)
  {              
   autoMapper = mapper;  
  }

und ich habe wie unten in meinen Aktionsmethoden verwendet

  ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);
2
Venkat pv

Für ASP.NET Core ist Folgendes direkt von Automapper und eine Zeile in Ihrer Startklasse: https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README. md

Fügen Sie einfach einige Profilklassen hinzu. Dann fügen Sie unten zu Ihrer startup.cs-Klasse .services.AddAutoMapper(OneOfYourProfileClassNamesHereSoItCanFindYourProfileAssembly) hinzu.

Dann einfach Inject IMapper in Ihre Controller oder wo immer Sie es benötigen:

public class EmployeesController {

    private readonly IMapper _mapper;

    public EmployeesController(IMapper mapper){

        _mapper = mapper;
    }

Und wenn Sie ProjectTo verwenden möchten, ist es jetzt einfach:

var customers = await dbContext.Customers.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider).ToListAsync()
1
user1191559

Über die Antwort, Es ist nicht erforderlich, den IMapper-Mapperparrameter im Controller-Konstruktor anzugeben.

sie können den Mapper verwenden, da er an jeder Stelle des Codes statisch ist.

public class UserController : Controller {
   public someMethod()
   {
      Mapper.Map<User, UserDto>(user);
   }
}
0
yaronmil

Hinzufügen zu dem, was Arve Systad zum Testen erwähnt hat. Wenn Sie aus irgendeinem Grund wie ich sind und die in der Lutz-Lösung bereitgestellte Vererbungsstruktur beibehalten möchten, können Sie MapperConfiguration wie folgt einrichten:

var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(cfg =>
{
    cfg.AddProfile(mappingProfile);
});
var mapper = new Mapper(config);

Ich habe das in NUnit gemacht.

0
LandSharks

In meiner Startup.cs (Core 2.2, Automapper 8.1.1)

services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });            

In meinem Datenzugriffsprojekt

namespace DAL
{
    public class MapperProfile : Profile
    {
        // place holder for AddAutoMapper (to bring in the DAL Assembly)
    }
}

In meiner Modelldefinition

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

    public class Position
    {
        ...
    }
0
Brian Rice

Ich habe es als schwierig empfunden, mit Automapper anzufangen. Als ich es in den Konstruktor meiner Testklasse nicht einschleusen konnte, habe ich es ganz fallen lassen. Stattdessen verwende ich ModelBindings für Eigenschaften, die nicht bearbeitet werden können, und Data Transfer Classes für Eigenschaften, die ausgeblendet werden sollen und die Zuordnung selbst übernehmen.

0
Metonymy