Link to home
Start Free TrialLog in
Avatar of Babak Sekandari
Babak SekandariFlag for United States of America

asked on

Serialization Exception in .NET WEB API.

I have an ASP.NET WEB API project in Framework 7 using Entity Framework.
(I would have preferred .NET Core but my manager chose this.)

I'm able to make a successful call if I make my Get verb like this:

public string Get(int id)
{
    User sr = new DataAccess.User();
    using (var ent = new DevDataEntities())
    {
        sr = ent.Users.FirstOrDefault(x => x.UserId == id);
        return sr.DisplayName;            
    }
}

But I get an error when I try any of these methods I get an error:

1.
public User Get(int id)
{
    User sr = new ACH_DataAccess.User();
    using (var entities = new ACH_DevDataEntities())
    {
        sr = entities.Users.FirstOrDefault(x => x.UserId == id);
        return sr;
    }
}

2.
public User Get(int id)
{
    User sr = new ACH_DataAccess.User();
    using (var entities = new ACH_DevDataEntities())
    {
        sr = entities.Users.FirstOrDefault(x => x.UserId == id);              
    }
    return sr;
}

3.public User Get(int id)
{    
    using (var entities = new ACH_DevDataEntities())
    {
        var sr = entities.Users.FirstOrDefault(x => x.UserId == id);
        return sr;
    }
}


Here is the page I get:
<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.User_9A7F08A3597175E07FDCEE95052760F3C97BAD33B600B22C35ACEF344C52B7D2' with data contract name 'User_9A7F08A3597175E07FDCEE95052760F3C97BAD33B600B22C35ACEF344C52B7D2: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>

When I call it through Postman, I get a "Satus: 400 Bad Request. The request cannot be fullfilled due to bad syntax."

When I step through the debugger, I see that data is returned; but getting it to the browser or to Postman fails.

One of the User properties in the database is varbinary(max) but that comes back as null.
Oddly, when I remove it from the EF model, it continues to appear in the debugger.

I got this to work:

public Dictionary<string, string> Get(int id)
{
    User sr = new ACH_DataAccess.User();
    StringBuilder sb = new StringBuilder();
    using (var entities = new ACH_DevDataEntities())
    {
        sr = entities.Users.FirstOrDefault(x => x.UserId == id);
    }
    sr.AvatarImg = new byte[] { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 };

    Dictionary<string, string> dctUser = new Dictionary<string, string>();
    dctUser.Add("Display Name", sr.DisplayName);
    dctUser.Add("Email", sr.Email);
    return dctUser;
}

But that seems like a lot of work if the User class has many properties.

The DataContractResolver example here seemed unrealisticly complex for what seems like what should be an easy solution:
https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/datacontractresolver
Avatar of Babak Sekandari
Babak Sekandari
Flag of United States of America image

ASKER

Thank you Mohit,
re: "You can either pass the namespace"
In which file and how is that passed in?

re: "Or switch to XmlSerializer in your Web API configuration"
Is that in the Web.config file? The WebAPIConfig file? Where in there?

Avatar of Prakash Samariya
Type 'System.Data.Entity.DynamicProxies.User_9A7F08A3597175E07FDCEE95052760F3C97BAD33B600B22C35ACEF344C52B7D2' with data contract name 'User_9A7F08A3597175E07FDCEE95052760F3C97BAD33B600B22C35ACEF344C52B7D2 

EF generated proxy version of model so it tracks when the object is changed when you save changes.

You can turn off Proxy object creation in DbConext for all model.

DbContext.Configuration.ProxyCreationEnabled = false;

Open in new window


or you can disable tracking for each model/query:
entities.Users.AsNoTracking().FirstOrDefault(x => x.UserId == id);

Open in new window

Thank you Prakash,
In what file do I put the code you showed for turning off Proxy object creation in DbConext?
ASKER CERTIFIED SOLUTION
Avatar of Prakash Samariya
Prakash Samariya
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial