SolvedAutoMapper Nullable properties on source being cast before conditional function called
CicerosPatience posts at
49 Answers
Share
Original✔️Accepted Answer
You can check against the default value for the value type, but that's not exposed right now through the interface, so you need a cast.
Update : no need for a cast anymore.
cfg.CreateMap<Source, Destination>()
.ForAllOtherMembers(opt =>opt.IgnoreSourceWhenDefault());
public static class Extensions
{
public static void IgnoreSourceWhenDefault<TSource, TDestination>(this IMemberConfigurationExpression<TSource, TDestination, object> opt)
{
var destinationType = opt.DestinationMember.GetMemberType();
object defaultValue = destinationType.GetTypeInfo().IsValueType ? Activator.CreateInstance(destinationType) : null;
opt.Condition((src, dest, srcValue) =>!Equals(srcValue, defaultValue));
}
public static Type GetMemberType(this MemberInfo memberInfo)
{
if (memberInfo is MethodInfo)
return ((MethodInfo)memberInfo).ReturnType;
if (memberInfo is PropertyInfo)
return ((PropertyInfo)memberInfo).PropertyType;
if (memberInfo is FieldInfo)
return ((FieldInfo)memberInfo).FieldType;
return null;
}
}
Other Answers:
I can't check for the default value, because the default value is a legitimate value. That's why the property is Nullable. I need to prevent mapping null values for Nullable properties from the source. Note that this only seems to occur when mapping a Nullable to a non-Nullable (int? to int in my case). Nullable to Nullable works.
Related Issues:
3
AutoMapper Nullable properties on source being cast before conditional function called
You can check against the default value for the value type but that's not exposed right now through ...
I'm writing a restful api and in my use case I am trying to map a nullable type on my source to a non-nullable property on my destination. I want it to ignore mapping properties if the source value is null. I want this because it is a really elegant solution for me to deserialize a partial json request into my object and only update fields on my entity object that were actually passed to my dto. See my code below (note, I've removed all my Entity Framework junk).
These are my source (ScriptDto) and destination (Script) classes.
This is my web api routed method
What I would expect to happen with this, is if the source property is null the condition function evaluates to false and the property mapping is skipped. That is not what is happening for the nullable properties on my source object. After setting a break point inside the conditional function I realized that my source property values were being cast to the destination type (I assume) before they are passed to the conditional function. So where I would expect "srcValue" to be null it was actually already cast to its non-nullable default. If for example, I sent the following json PUT request to my service at api/v1/scripts/somescriptid
then it would deserialize into a DTO object with mostly null properties, with the exception of the ScriptBody property. But when it gets mapped to my destination object, the DateTime? LastExecuted property which is null (for example) has its value cast to a non-nullable DateTime prior to being passed to the conditional function. Which of course causes my conditional function to evaluate to true and thus the destination property is overwritten.
I imagine I am having this issue because I am trying to map a nullable property on my source to a non-nullable property on my destination. When I change the property on my destination object to a nullable type then it works the way I would expect. That said, I do not want nullable types where they aren't required on my entity object. I'm using the latest dev build on myget, 5.2.0-alpha-01223.