Showing posts with label AutoMapper. Show all posts
Showing posts with label AutoMapper. Show all posts
Sunday, June 3, 2012
Using AutoMapper to copy Metadata from Entities to ViewModels
On my crusade to eliminate common mistakes causing bugs in my projects I found was that my metadata on my entities didn’t always match my viewmodels. I wrote 2 fairly simple providers to copy the metadata from the entity to the ViewModel at runtime which leverages my AutoMapper configuration so it supports field names that are renamed.
I use the approach below to automatically copy data annotations from my entities to my view model. This ensures that things like StringLength and Required values are always the same for entity/viewmodel.
It works using the Automapper configuration, so works if the properties are named differently on the viewmodel as long as AutoMapper is setup correctly.
You need to create a custom ModelValidatorProvider and custom ModelMetadataProvider to get this to work. My memory on why is a little foggy, but I believe it's so both server and client side validation work, as well as any other formatting you do based on the metadata (eg an asterix next to required fields).
Note: I have simplified my code slightly as I added it below, so there may be a few small issues.
Metadata Provider
Validator Provivder
Helper Method Referenced in above 2 classes
Other Notes
If you're using dependency injection, make sure your container isn't already replacing the built in metadata provider or validator provider. In my case I was using the Ninject.MVC3 package which bound one of them after creating the kernel, I then had to rebind it afterwards so my class was actually used. I was getting exceptions about Required only being allowed to be added once, took most of a day to track it down.
My StackOverflow Post: http://stackoverflow.com/questions/9989785/technique-for-carrying-metadata-to-view-models-with-automapper/10100042#10100042
Labels:
AutoMapper,
Metadata,
MVC,
Stackoverflow
Pagination with AutoMapper
I recently posted a method of using AutoMapper in an ActionResult (http://bzbetty.blogspot.co.nz/2012/06/thoughts-on-actionfilters.html). This became an issue when I was trying to return a paginated model to the view, as I wanted to do pagination in the database (on the entities) but AutoMapper had no idea how to map the IPagination result to the ViewModel.
Result - Build a custom IObjectMapper to do the mapping
Resulting Action
IObjectMapper
Result - Build a custom IObjectMapper to do the mapping
Resulting Action
IObjectMapper
Labels:
AutoMapper,
MVC,
MVCContrib
Updating collections using AutoMapper
By default AutoMapper replaces child lists with a completely new instance only containing the items in the original list. Because of the way EF works you need to change the existing items in the list for it to track changes as updates instead of adds. This method also means deletes can be tracked succesfully.
Basic steps were
Ensure the destination collection is loaded from db and attached to the object graph for change tracking
.ForMember(dest => dest.Categories, opt => opt.UseDestinationValue())
Then create a custom IObjectMapper for mapping IList<> to IList<T> where T : Entity
The custom IObject mapper used some code from http://groups.google.com/group/automapper-users/browse_thread/thread/8c7896fbc3f72514
Finally one last piece of logic to check all Id's in targetCollection exist in sourceCollection and delete them if they don't.
It wasn't all that much code in the end and is reusable in other actions.
My Stackoverflow Post: http://stackoverflow.com/questions/9739568/when-using-dtos-automapper-nhibernate-reflecting-changes-in-child-collections/9856360#9856360
Recently found a library that does just this - https://github.com/TylerCarlson1/Automapper.Collection My Stackoverflow Post: http://stackoverflow.com/questions/9739568/when-using-dtos-automapper-nhibernate-reflecting-changes-in-child-collections/9856360#9856360
Labels:
AutoMapper,
EF,
Stackoverflow
Subscribe to:
Posts (Atom)