4

I'm trying to create a WebApi to read a data from the DB using Entity Framework.

My data model design looks like this:

enter image description here

I have added a WebApi controller named SportsController like this:

public class SportsController : ApiController
{
    public HttpResponseMessage Get()
    {
        try
        {
            using (MyLeagueDBEntities dbEntity = new MyLeagueDBEntities())
            {
                return Request.CreateResponse(HttpStatusCode.OK, dbEntity.tbl_Sports.ToList());
            }
        }
        catch (Exception ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
        }
    }
}

On invoking a request from browser to my WebApi controller GET method, I'm getting the exception shown below. But in debug mode, I can see that it is able to get the data from database without any error but once the control moves out of the method, it does throw the below exception.

Exception details:

"Message":"An error has occurred.",
"ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
"ExceptionType":"System.InvalidOperationException",
"StackTrace":null,
"InnerException":{"Message":"An error has occurred.",
"ExceptionMessage":"Error getting value from 'tbl_Tournament' on 'System.Data.Entity.DynamicProxies.tbl_Sports_7461105FEAC4FCCBDED534FCE44707AF9C7DFE1E4AD69B1E7E3777FBB953F184'.",
"ExceptionType":"Newtonsoft.Json.JsonSerializationException",
"StackTrace":"
at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)\r\n
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)\r\n
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract 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.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 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

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n
at System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()",

"InnerException":{"Message":"An error has occurred.",
"ExceptionMessage":"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.",
"ExceptionType":"System.ObjectDisposedException",
"StackTrace":"
at System.Data.Entity.Core.Objects.ObjectContext.get_Connection()\r\n
at System.Data.Entity.Core.Objects.ObjectQuery1.GetResults(Nullable1 forMergeOption)\r\n
at System.Data.Entity.Core.Objects.ObjectQuery1.Execute(MergeOption mergeOption)\r\n
at System.Data.Entity.Core.Objects.DataClasses.EntityCollection
1.Load(List1 collection, MergeOption mergeOption)\r\n
at System.Data.Entity.Core.Objects.DataClasses.EntityCollection
1.Load(MergeOption mergeOption)\r\n
at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.DeferredLoad()\r\n
at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.LoadProperty[TItem](TItem propertyValue, String relationshipName, String targetRoleName, Boolean mustBeNull, Object wrapperObject)\r\n
at System.Data.Entity.Core.Objects.Internal.LazyLoadBehavior.<>c__DisplayClass7`2.b__1(TProxy proxy, TItem item)\r\n
at System.Data.Entity.DynamicProxies.tbl_Sports_7461105FEAC4FCCBDED534FCE44707AF9C7DFE1E4AD69B1E7E3777FBB953F184.get_tbl_Tournament()\r\n
at Gettbl_Tournament(Object )\r\n
at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)"}}}

I'm new to Entity Framework and WebApi, requesting one to help me out resolving this issue.

PFB the snapshot with the error message logged on fiddler. Currently getting Http 500 internal server error,

enter image description here

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Manju
  • 2,520
  • 2
  • 14
  • 23

1 Answers1

10

It is because you have lazy loading enabled and you are serializing the object graph after you dispose of the DbContext instance. So what is happening

  • You create a DbContext
  • You retrieve the data from the DbContext for that one type
  • You pass the data to the Result method
  • Your DbContext is closed and disposed
  • Your method exists
  • Asp.Net mvc pipeline now tries to serialize the result's content
  • Relationships in your type are now attempted to be retrieved in the serialization process
  • The relationships are attempted to be retrieved from the DbContext because you have Lazy Loading enabled
  • The DbContext is disposed so access is not possible, an Exception is thrown

To fix it do one of the following

  • Move the DbContext to the class scope and dispose of it in the Disposing method (override the existing method from the ApiController)
  • (Recommended!) Turn off loazy loading and specify which properties you want to retrieve from the returned type using Include. This will enable more fine grained control over what is retrieved and is more performant because everything is retrieved in a single DB call instead of on access.
Igor
  • 60,821
  • 10
  • 100
  • 175
  • 4
    Thanks mate. As suggested, i disabled the lazy load before reading the data from DB using the below line and it did fix me the issue. dbEntity.Configuration.LazyLoadingEnabled = false; – Manju Mar 18 '17 at 12:49
  • Disabling lazyloading did the trick for me. Cheers. – supermeerkat May 23 '19 at 11:45