Unloaded “eager-loaded” properties causing issues when returning json'd data

心已入冬 提交于 2019-12-12 07:27:06

问题


Hopefully the title makes sense, I'll do my best to describe my problem.

I'm currently developing an ASP.NET Web API. In my "Company" controller I have a GetCompany() action.

    /// <summary>
    /// Gets the 'Authorization-Token' request header and finds the company with the
    /// matching decrypted token from the database, returns it; if null, returns 404
    /// </summary>
    /// <returns>Matching company for token passed in request or 404 if null</returns>
    [HttpGet][ResponseType(typeof(Company))]
    [Route("api/company/")]
    public HttpResponseMessage GetCompany() {
        string token = Request.Headers.GetValues("Authorization-Token").First();

        ICollection<Company> companies;
        Company c;
        using (BaseRepository r = new BaseRepository()) {
            companies = r.Get<Company>(null, null, null);
            c = companies.Where(cm => RSA.Decrypt(cm.Token) == token).FirstOrDefault<Company>();
        }
        if (c == null)
            return Request.CreateResponse(HttpStatusCode.NotFound, c);

        return Request.CreateResponse(HttpStatusCode.OK, c);
    }

This finds it and returns it just fine, however when I'm testing this, the response I see is

{
    "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 'Locations' on 'System.Data.Entity.DynamicProxies.Company_40636FF93138F09772BEA689D3A3D3AB7DBB41AFF7FE3D0BEFF55FC7C1D10E0F'.",
        "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.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.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n   at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext)\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.<WriteBufferedResponseContentAsync>d__14.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.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)\r\n   at System.Data.Entity.Core.Objects.ObjectQuery`1.Execute(MergeOption mergeOption)\r\n   at System.Data.Entity.Core.Objects.DataClasses.EntityCollection`1.Load(List`1 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.Load()\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.<GetInterceptorDelegate>b__1(TProxy proxy, TItem item)\r\n   at System.Data.Entity.DynamicProxies.Company_40636FF93138F09772BEA689D3A3D3AB7DBB41AFF7FE3D0BEFF55FC7C1D10E0F.get_Locations()\r\n   at GetLocations(Object )\r\n   at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)"
        }
    }
}

I understand the problem is that my properties are eager-loaded and they aren't ever loaded. I can tell it to load my navigation properties inside my Company object quite easily. The problem I'm encountering when I do that, is that it's saying the complex objects inside of those aforementioned navigation properties are null as well and I can't so easily eager load them; nor do I want to. So it's attempting to load the whole "object tree" for lack of a better way to say it (that I can think of).

So my question is, what is the best way to get around this?


回答1:


The proxy is causing the serializer to attempt to access navigational properties which are no longer available since the context has been disposed.

Try removing the proxy and eager loading from your context when you are querying for objects that will be serialized

 context.Configuration.ProxyCreationEnabled = false;
 context.Configuration.LazyLoadingEnabled = false;


来源:https://stackoverflow.com/questions/23095393/unloaded-eager-loaded-properties-causing-issues-when-returning-jsond-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!