簡體   English   中英

如何在 ASP.NET MVC 中使用 Automapper 10.1.1

[英]How do I use Automapper 10.1.1 in ASP.NET MVC Web API controller?

我正在嘗試重新制作我不久前使用 ASP.NET MVC 制作的應用程序,但我遇到的問題是由使用最新版本的Automapper引起的。 我第一次制作應用程序時遵循了一個教程,在本教程中,我使用的Automapper版本是 4.1.0。

然而,這個版本是在 2016 年左右發布的——教程已經很老了——從那時起Automapper發生了很多變化,即很多東西現在已經過時了。

在以前的版本中,您可以使用Mapper class 中的 static CreateMap方法,但現在已過時。

這是我使用舊方法的方法。 首先,我創建了一個派生自Profile的 class 來存儲我的配置。

public class MappingProfile : Profile
{
    public MappingProfile()
    {
       // Domain to DTO
       Mapper.CreateMap<Customer, CustomerDto>();
       Mapper.CreateMap<Movie, MovieDto>();
       Mapper.CreateMap<MembershipType, MembershipTypeDto>();
       Mapper.CreateMap<MembershipTypeDto, MembershipType>();
       Mapper.CreateMap<Genre, GenreDto>();
       Mapper.CreateMap<GenreDto, Genre>();

       // Dto to Domain 
       Mapper.CreateMap<CustomerDto, Customer>()
          .ForMember(c => c.Id, opt => opt.Ignore());

       Mapper.CreateMap<MovieDto, Movie>()
          .ForMember(c => c.Id, opt => opt.Ignore());
     }
}

接下來,我初始化了Mapper class 並在Global.asax.cs中添加了配置文件。

public class MvcApplication : System.Web.HttpApplication
{
     protected void Application_Start()
     {
       // Here's the line of code I added
       Mapper.Initialize(c => c.AddProfile<MappingProfile>());

       GlobalConfiguration.Configure(WebApiConfig.Register);
       AreaRegistration.RegisterAllAreas();
       FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
       RouteConfig.RegisterRoutes(RouteTable.Routes);
       BundleConfig.RegisterBundles(BundleTable.Bundles);
     }
}

最后,我使用 static Map方法從Mapper到 map 我的域對象到 DTO 對象,反之亦然在我的 Z163442387148ACA8 控制器中。 順便說一句,這一切都很好。

public IHttpActionResult CreateCustomer(CustomerDto customerDto)
{
     if (!ModelState.IsValid)
        {
           BadRequest();
        }

     var customer = Mapper.Map<CustomerDto, Customer>(customerDto);

     _context.Customers.Add(customer);
     _context.SaveChanges();

     customerDto.Id = customer.Id;

     return Created(new Uri(Request.RequestUri + "/" + customer.Id ), customerDto);
}

最新的 Automapper 文檔建議您使用MapperConfigurationCreateMap為域和 DTO 對象創建 map,並且每個 AppDomain 只需要一個MapperConfiguration實例,該實例應在啟動期間實例化。

我繼續並再次創建了一個MappingProfile來存儲我的配置(按照文檔的建議) ,並將這個配置包含在Global.asax.csApplication_Start()中,這是 MVC 應用程序的啟動。

public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            CreateMap<Customer, CustomerDto>();
            CreateMap<CustomerDto, Customer>();
        }
    }
public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            // This is the new way of creating a MapperConfiguration 
            var configuration = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile<MappingProfile>();
            });

            IMapper mapper = configuration.CreateMapper();

            GlobalConfiguration.Configure(WebApiConfig.Register);
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            UnityConfig.RegisterComponents();
        }
    }

此時,文檔說您可以使用依賴注入來注入創建的IMapper實例。 這就是我卡住並遇到錯誤的地方。

The documentation covers ASP.NET Core very well in explaining how to use dependency injection, so I tried using this approach with UnityConfig in which I created the MapperConfiguration there and registered the instance of IMapper then tried to inject this in my web API controller like so:

public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = new UnityContainer();

            var configuration = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile<MappingProfile>();
            });

            IMapper mapper = configuration.CreateMapper();

            container.RegisterInstance(mapper);
            // register all your components with the container here
            // it is NOT necessary to register your controllers
            
            // e.g. container.RegisterType<ITestService, TestService>();
            
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
        }
    }
 public class MvcApplication : System.Web.HttpApplication
    {
        
        protected void Application_Start()
        {            
            GlobalConfiguration.Configure(WebApiConfig.Register);
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            // I registered the components here inside Global.asax.cs
            UnityConfig.RegisterComponents();
        }
    }

這是我嘗試通過依賴注入使用實例的地方。

public class CustomersController : ApiController
    {
        private ApplicationDbContext _context;

        private readonly IMapper _mapper;

        public CustomersController()
        {
            _context = new ApplicationDbContext();
        }

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

        // GET /api/customers
        public IHttpActionResult GetCustomers()
        {
            var customersDto = _context.Customers
                .Include(c => c.MembershipType)
                .ToList()
                .Select(_mapper.Map<Customer, CustomerDto>);

            return Ok(customersDto);
        }
        // Remaining code omitted because it's unnecessary

調試時出現的錯誤是NullReferenceException 在 Watch window 中,我注意到_mapper是 null,但是,這些對象確實是從數據庫中加載的。 問題是_mapper即使在使用 DI 之后仍然是 null。

Could someone kindly explain why it's null and potential fixes/tips to using this version of Automapper this way in an ASP.NET MVC Web API controller?

經過大量的閱讀和研究,我終於弄清楚了哪里出錯了。 我相信Unity.Mvc5適用於常規控制器,而不是 API 控制器。

出於這個原因,我添加了一個單獨的 package Unity.AspNet.WebApi ,它帶有不同的Unity.Config.cs 添加 package 時出現提示,詢問我是否要覆蓋以前的Unity.Config.cs (來自Unity.Mvc5 ),我選擇了是。

從這里,我將我的配置添加到這個文件中,注冊了實例,我對 go 很好。

這個視頻很好地解釋了整個事情: https://youtu.be/c38krTX0jeo

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM