0

I exactly followed this tutorial but when I run my code I am getting this error message.

 <Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace/>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Type 'System.Data.Entity.DynamicProxies.Player_B392F8ACFF7986B6E577FBE0EA4EC58EB44F1C4138CB96BE272A810004835B21' with data contract name 'Player_B392F8ACFF7986B6E577FBE0EA4EC58EB44F1C4138CB96BE272A810004835B21:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.
</ExceptionMessage>
<ExceptionType>
System.Runtime.Serialization.SerializationException
</ExceptionType>
<StackTrace>
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType) at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiTypeAtTopLevel(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle originalDeclaredTypeHandle, Type graphType) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.WriteObject(XmlWriter writer, Object graph) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content) at System.Net.Http.Formatting.XmlMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__22.MoveNext()
</StackTrace>
</InnerException>
</Error>

I do not understand where my code fails because it is the same as the tutorial.

A controller for example looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using UEFA_APIDataAcces;

namespace UEFA_API.Controllers
{
    [RoutePrefix("api/Match")]
    public class MatchController : ApiController
    {
        [Route("")]
        public IEnumerable<Match> Get()
        {
            using(UEFAEntities entities = new UEFAEntities())
            {
                return entities.Match.ToList();
            }
        }
        [Route("{id:int}")]
        public Match Get(int id)
        {
            using (UEFAEntities entities = new UEFAEntities())
            {
                return entities.Match.FirstOrDefault(e => e.ID == id);
            }
        }
    }

}

I also saw this solution but that is not working for me. I am still getting the error message.

Any help/ tips are welcome.

Thank you in advance.

J.vee
  • 623
  • 1
  • 7
  • 26

2 Answers2

1

Earlier Entity Framework versions (i.e. before Core 2.1) use Proxy classes for the data models by default when it knows it can lazily load data. For example if you had a class Parent with a collection of class Children, by default when you load the Parent object via something like this

var parent = entities.Parents.FirstOrDefault(p=>p.Id==pid)

Then EF will - by default - not bother to load the related childred until you first attempt to reference them

e.g. only at the point where you write

var child = parent.Children.Where(c=>c.SomeProperty==true)

will a fresh SQL query be sent to fetch the children. This is enabled by there being a (transparent to you) proxy class generated at runtime for the Parent object which detects that you want the access the Children collection and issues the SQL, does the mapping, etc.

Unfortunately, these Proxy classes do not lend themselves well - if at all - to serialisation, for various reasons. Hence the error message you are getting. EF Core 2.1 changed things so that lazy loading is off by default and you have to enable it. But if you are using any earlier version (including the non-core EFs) then it's on by default.

This would also explain why you creating a new database without Foreign Keys worked, because EF will not be able to infer relationships to child objects and so it won't create proxies, meaning the class you are dealing with is now what we call a POCO (Plain Old CLR Object). But you're robbing yourself (and EF) of the ability to have related objects in a relational database which is probably not a good thing in the long run :)

In terms of a better solution there are several options you can you can turn off proxy creation, or pull your entire object graph before serialisation:

var parent = entities.Parents.Include("Children").FirstOrDefault(p=>SomeCondition);

This will load the entire Parent entity and all of its Children in one go, and avoid the problem as well; however this is not always ideal because you might not actually want the Children entities every time.

But better yet, don't expose your EF models directly but use mapping to a DTO (Data Transfer Object)

I recommend DTOs; the biggest advantage of using DTOs is that you don't need to expose your EF Entities to the outside world, because for example there may be parts of them that are not relevant to the consumer, or you may want to do aggregation on some child collections before returning, etc.

There is a great guide here which talks about these topics in more depth.

Stephen Byrne
  • 7,400
  • 1
  • 31
  • 51
0

Apparently it was a problem with my foreign keys in the database. I made a new database with the same data but without foreign keys and now my application is working fine.

I hope I can help someone else with this answer as well.

J.vee
  • 623
  • 1
  • 7
  • 26