[英]Given a URL and HTTP verb, how can I resolve the controller/action in ASP.NET MVC/Web API?
[英]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 文檔建議您使用MapperConfiguration
和CreateMap
為域和 DTO 對象創建 map,並且每個 AppDomain 只需要一個MapperConfiguration
實例,該實例應在啟動期間實例化。
我繼續並再次創建了一個MappingProfile
來存儲我的配置(按照文檔的建議) ,並將這個配置包含在Global.asax.cs
的Application_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.