How to use AutoMapper with Post Action
-
13-12-2019 - |
Question
in my solution I have an ASP.NET MVC3 project, and a WCF project that works with a database.
I use entity framework self tracking
and AutoMapper
to map objects.
My question is: how i can use AutoMapper
with Post Action like crate and delete and Edit methods
i see this Questions but not help me
this give me an error argument type '...' is not assignable to parameter type '...'
[HttpPost]
public ActionResult Create(MUser muser)
{
if (ModelState.IsValid)
{
Mapper.CreateMap<User, MUser>();
var user = Mapper.Map<User, MUser>(muser);
_proxy.SaveUser(user);
return RedirectToAction("Index");
}
return View(muser);
}
Solution
You shouldn't place the Mapper.CreateMap in your controller, you need to perform that action only once, so create a bootstrapper or something like that and call it from your application start method.
I think that's where your error comes from: you can create a mapping only once.
Oh, and you're defining the wrong types. You aren't trying to convert a User to a MUser, but you're doing it the other way around, so it should be:
Mapper.CreateMap<MUser, User>();
Mapper.Map<MUser, User>(muser);
Example of how to do this:
public class MvcApplication : HttpApplication
{
// some methods
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
MappingsBootstrapper.Initialize(); // call the bootstrap class that I created
}
}
Then I've got a project called 'Mappings' and it contains the bootstrap class and some 'configuration' classes (just like Entity Framework has EntityTypeConfiguration classes and Ninject has NinjectModules):
public static class MappingsBootstrapper
{
public static void Initialize()
{
new UserMappings();
new BookcaseItemMappings();
}
}
And the mappings:
class UserMappings
{
public UserMappings()
{
Mapper.CreateMap<User, UserSetupViewModel>();
Mapper.CreateMap<UserSetupViewModel, User>();
}
}
class BookcaseItemMappings
{
public BookcaseItemMappings()
{
Mapper.CreateMap<NewBookViewModel, BookcaseItem>().ForMember(x => x.BookId, opt => opt.Ignore());
Mapper.CreateMap<BookcaseItem, BookcaseItemViewModel>()
.ForMember(x => x.Title, opt => opt.MapFrom(src => src.Book.Title))
.ForMember(x => x.Authors, opt => opt.MapFrom(src => src.Book.Authors.Select(x => x.Name).Aggregate((i, j) => i + ", " + j)))
.ForMember(x => x.Identifiers, opt => opt.MapFrom(src => (!string.IsNullOrEmpty(src.Book.Isbn10) ? ("ISBN10: " + src.Book.Isbn10 + "\r\n") : string.Empty) +
(!string.IsNullOrEmpty(src.Book.Isbn13) ? ("ISBN13: " + src.Book.Isbn13) : string.Empty)))
.ForMember(x => x.Pages, opt => opt.MapFrom(src => src.Book.Pages))
.ForMember(x => x.ImageUri, opt => opt.MapFrom(src => src.Book.ThumbnailUriSmall));
}
}
You can do it any way you like, you could just place all the mappings in your Application_Start() method, but I found this to be a clean and maintainable way.