ASP.NET MVC layered application: where to place Automapper initialization?

I am creating a tiered application that has the asp.net mvc application as the highest level.

The architecture is as follows (---> means links):

Presentation level ---> Service level ---> Business level ----> Data access level ----> Database

In addition, there is a layer called "Infrastracture" that all layers refer to.

Each layer has its own objects. For example: at the presentation level, we could have a UserViewModel, in the ServiceDTO user layer, in the UserBDO business layer and, finally, at the User data access level.

Automapper is used to automate the conversion between different types.

I read that some developers offer to place the creation of mappings in Global.asax, but it is obvious that if you have a multilayer application, you cannot create all mappings there. You cannot map a user to UserBDO at presentation level.

So, I am asking for the simplest way to manage the centralization of mapping in a multitasking application. You can even suggest changes in architecture.

+5
source share
2 answers

I suggest you already have the answer — if you cannot access all of your types in one place — simply split the mapping configurations into several parts. This solution is more convenient in large projects (just imagine 100 or 1000 comparisons in one configuration). For example, we use a specific mapper to convert third-party WCF contracts to custom DTOs. This cartographer is in a separate project with the WCF client. Thus, contracts and mappings are not accessible from the outside.

+1
source

I am trying to answer my question: do not hesitate to correct me if there is something that does not suit you.

I will use the following words:

  • layer: in this context, a layer is an application module in the vertical sense (from the database to the user interface).

  • module: the area of ​​your application in the horizontal sense, for example, "CRM", "Product", Accounting ", ... each of which has code in different layers.

If you have an application divided into n layers and n modules, this can be an example for a specific class of a certain module and level.

public static class ProductMapper { static ProductMapper() { MapProductBDOToDTO(); MapProductDTOToBDO(); MapProductCategoryBDOToDTO(); MapProductCategoryDTOToBDO(); MapIvaBDOToDTO(); MapIvaDTOToBDO(); MapProductSupplierBDOToDTO(); MapProductSupplierDTOToBDO(); MapProductPictureBDOToDTO(); MapProductPictureDTOToBDO(); MapProductNoteBDOToDTO(); MapProductNoteDTOToBDO(); MapStockProductBDOToDTO(); MapStockProductDTOToBDO(); MapTagBDOToDTO(); MapTagDTOToBDO(); } public static TTargetType Convert<TToConvert, TTargetType>(TToConvert toConvert) { return Mapper.Map<TTargetType>(toConvert); } private static void MapProductDTOToBDO() { Mapper.CreateMap<ProductDTO, ProductBDO>(); } private static void MapProductBDOToDTO() { Mapper.CreateMap<ProductDTO, ProductBDO>().ReverseMap(); } private static void MapProductCategoryDTOToBDO() { Mapper.CreateMap<ProductCategoryDTO, ProductCategoryBDO>(); } private static void MapProductCategoryBDOToDTO() { Mapper.CreateMap<ProductCategoryBDO, ProductCategoryDTO>(); } private static void MapIvaDTOToBDO() { Mapper.CreateMap<IvaDTO, IvaBDO>(); } private static void MapIvaBDOToDTO() { Mapper.CreateMap<IvaBDO, IvaDTO>(); } private static void MapProductSupplierDTOToBDO() { Mapper.CreateMap<ProductSupplierDTO, ProductSupplierBDO>(); } private static void MapProductSupplierBDOToDTO() { Mapper.CreateMap<ProductSupplierDTO, ProductSupplierBDO>().ReverseMap(); } private static void MapProductPictureDTOToBDO() { Mapper.CreateMap<ProductPictureDTO, ProductPictureBDO>(); } private static void MapProductPictureBDOToDTO() { Mapper.CreateMap<ProductPictureDTO, ProductPictureBDO>().ReverseMap(); } private static void MapProductNoteDTOToBDO() { Mapper.CreateMap<ProductNoteDTO, ProductNoteBDO>(); } private static void MapProductNoteBDOToDTO() { Mapper.CreateMap<ProductNoteDTO, ProductNoteBDO>().ReverseMap(); } private static void MapStockProductDTOToBDO() { Mapper.CreateMap<StockProductDTO, StockProductBDO>(); } private static void MapStockProductBDOToDTO() { Mapper.CreateMap<StockProductDTO, StockProductBDO>().ReverseMap(); } private static void MapTagDTOToBDO() { Mapper.CreateMap<TagDTO, TagBDO>(); } private static void MapTagBDOToDTO() { Mapper.CreateMap<TagDTO, TagBDO>().ReverseMap(); } 

As you can see this is a static class with a static constructor, this means that the constructor will be called no more than ONCE during the life of the application. When you first call the Convert method, the constructor is called and all mappings are created. The second, third, fourth ... time, when you roll the Convert method during the same session, the constructor will not be called.

Benefits:

  • Unable to create a specific display more than once
  • Mappings are only created when you need them (in this case, when you work with Products). You do not create 1000 mappings when you run the application, and then use only 5 or 6 of them.

Disadvantages:

  • The developer can call the general Convert method with all types that he / she wants, types are not checked. By the way, when using the general method, less code is required, and if no mappings have yet been created, an exception will be thrown by AutoMapper.
0
source

Source: https://habr.com/ru/post/1232434/


All Articles