I'm building a .NET Web API using Entity Framework 6 with AutoMapper to map entities to DTOs. When I try to introduce an TPH (table per hierarchy) with an abstract base class, I get a very long and very useless (to me at least) error. The error is below, I'm not sure what the actual error is. I've tried Googling various sections of it to no avail.
This is my mapping:
Mapper.CreateMap<ParentClass, ParentClassDTO>()
.Include<ClassA, ClassADTO>()
.Include<ClassB, ClassBDTO>();
Mapper.CreateMap<ClassA, ClassADTO>();
Mapper.CreateMap<ClassB, ClassBDTO>();
If I remove abstract
from the ParentClass
, the error goes away but then AutoMapper does not use the child DTO classes, it only uses the ParentClassDTO. If I remove the mapping all together and just return the entities through the API, there are no errors and everything works as expected.
I don't even know where to start with the error below, how to start debugging it (web API running in debug mode still just outputs this error to screen), or what is responsible for the error. I've simplified my code as much as possible and tried other various things, but can't seem to get around this issue.
This specific mapping is a collection within another DTO class, which I am creating to return a IQueryable<AnotherClassDTO>
from a Web API:
return db.AnotherClass.Project().To<AnotherClassDTO>();
The AnotherClassDTO (a separate class which contains the abstract collection) is setup like this:
public class AnotherClassDTO
{
public IEnumerable<ParentClassDTO> Elements;
}
Error Message:
> {"message":"An error has occurred.","exceptionMessage":"The
> 'ObjectContent`1' type failed to serialize the response body for
> content type 'text/html;
> charset=utf-8'.","exceptionType":"System.InvalidOperationException","stackTrace":null,"innerException":{"message":"An
> error has occurred.","exceptionMessage":"Exception has been thrown by
> the target of an
> invocation.","exceptionType":"System.Reflection.TargetInvocationException","stackTrace":"
> at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[]
> arguments, Signature sig, Boolean constructor)\r\n at
> System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,
> Object[] parameters, Object[] arguments)\r\n at
> System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags
> invokeAttr, Binder binder, Object[] parameters, CultureInfo
> culture)\r\n at System.Reflection.MethodBase.Invoke(Object obj,
> Object[] parameters)\r\n at
> System.Data.Entity.Core.Common.Internal.Materialization.Translator.TranslateColumnMap(Translator
> translator, Type elementType, ColumnMap columnMap, MetadataWorkspace
> workspace, SpanIndex spanIndex, MergeOption mergeOption, Boolean
> streaming, Boolean valueLayer)\r\n at
> System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.Prepare(ObjectContext
> context, DbQueryCommandTree tree, Type elementType, MergeOption
> mergeOption, Boolean streaming, Span span, IEnumerable`1
> compiledQueryParameters, AliasGenerator aliasGenerator)\r\n at
> System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1
> forMergeOption)\r\n at
> System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.b__6()\r\n
> at
> System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1
> func, IDbExecutionStrategy executionStrategy, Boolean
> startLocalTransaction, Boolean releaseConnectionOnSuccess)\r\n at
> System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.b__5()\r\n
> at
> System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1
> operation)\r\n at
> System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1
> forMergeOption)\r\n at
> System.Data.Entity.Core.Objects.ObjectQuery`1..GetEnumerator>b__0()\r\n
> at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()\r\n at
> Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter
> writer, IEnumerable values, JsonArrayContract contract, JsonProperty
> member, JsonContainerContract collectionContract, JsonProperty
> containerProperty)\r\n at
> Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter
> writer, Object value, JsonContract valueContract, JsonProperty member,
> JsonContainerContract containerContract, JsonProperty
> containerProperty)\r\n at
> Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter
> jsonWriter, Object value, Type objectType)\r\n at
> Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter
> jsonWriter, Object value, Type objectType)\r\n at
> Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object
> value)\r\n at
> System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type
> type, Object value, Stream writeStream, Encoding
> effectiveEncoding)\r\n at
> System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type
> type, Object value, Stream writeStream, Encoding
> effectiveEncoding)\r\n at
> System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type
> type, Object value, Stream writeStream, HttpContent content)\r\n at
> System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type
> type, Object value, Stream writeStream, HttpContent content,
> TransportContext transportContext, CancellationToken
> cancellationToken)\r\n--- End of stack trace from previous location
> where exception was thrown ---\r\n at
> System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
> task)\r\n at
> System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
> task)\r\n at
> System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n at
> System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()","innerException":{"message":"An
> error has occurred.","exceptionMessage":"Exception has been thrown by
> the target of an
> invocation.","exceptionType":"System.Reflection.TargetInvocationException","stackTrace":"
> at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[]
> arguments, Signature sig, Boolean constructor)\r\n at
> System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags
> invokeAttr, Binder binder, Object[] parameters, CultureInfo
> culture)\r\n at System.RuntimeType.CreateInstanceImpl(BindingFlags
> bindingAttr, Binder binder, Object[] args, CultureInfo culture,
> Object[] activationAttributes, StackCrawlMark& stackMark)\r\n at
> System.Activator.CreateInstance(Type type, BindingFlags bindingAttr,
> Binder binder, Object[] args, CultureInfo culture, Object[]
> activationAttributes)\r\n at System.Activator.CreateInstance(Type
> type, Object[] args)\r\n at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorScratchpad.Compile()\r\n
> at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorScratchpad.Compile()\r\n
> at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorScratchpad.Compile()\r\n
> at
> System.Data.Entity.Core.Common.Internal.Materialization.Translator.TranslateColumnMap[T](ColumnMap
> columnMap, MetadataWorkspace workspace, SpanIndex spanIndex,
> MergeOption mergeOption, Boolean streaming, Boolean
> valueLayer)","innerException":{"message":"An error has
> occurred.","exceptionMessage":"Instances of abstract classes cannot be
> created.","exceptionType":"System.InvalidOperationException","stackTrace":"
> at
> System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(IRuntimeMethodInfo
> method)\r\n at
> System.Reflection.Emit.DynamicMethod.CreateDelegate(Type delegateType,
> Object target)\r\n at
> System.Linq.Expressions.Compiler.LambdaCompiler.CreateDelegate()\r\n
> at
> System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression
> lambda, DebugInfoGenerator debugInfoGenerator)\r\n at
> System.Linq.Expressions.Expression`1.Compile()\r\n at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorFactory`1..ctor(Int32
> depth, Int32 stateSlot, Expression`1 hasData, Expression`1 setKeys,
> Expression`1 checkKeys, CoordinatorFactory[] nestedCoordinators,
> Expression`1 element, Expression`1 wrappedElement, Expression`1
> elementWithErrorHandling, Expression`1 initializeCollection,
> RecordStateFactory[] recordStateFactories)\r\n at
> System.Data.Entity.Core.Common.Internal.Materialization.CoordinatorFactory`1..ctor(Int32
> depth, Int32 stateSlot, Expression hasData, Expression setKeys,
> Expression checkKeys, CoordinatorFactory[] nestedCoordinators,
> Expression element, Expression elementWithErrorHandling, Expression
> initializeCollection, RecordStateFactory[] recordStateFactories)"}}}}