2016-08-01 13 views
2

Ich versuche, Daten in JSON zu serialisieren. Aber ich sehe unter Ausnahme aus.JSON Objekt wird nicht für große Daten serialisiert

OutOfMemoryException wurde vom Benutzercode nicht behandelt.
Eine Ausnahme des Typs 'System.OutOfMemoryException' aufgetreten in Newtonsoft.Json.dll wurde aber in Benutzercode

Below i definiert meinen Code nicht behandelt:

Hauptregler:

public class TrackingController : BaseAngularController 
{ 
    var lstDetails = _services.GetTrackingDetailsByAWBIds(awbids, awbType); 
    if (lstDetails != null) 
    { 
     return AngularJson(lstDetails); 
    } 
} 

Basis Controller:

public abstract class BaseAngularController : Controller 
{ 
    public AngularJsonResult<T> AngularJson<T>(T model) 
    { 
     return new AngularJsonResult<T>() { Data = model }; 
    } 
} 

Angular JSON Ergebnis Klasse:

public class AngularJsonResult<T> :AngularJsonResult 
{ 
    public new T Data 
    { 
     get { return (T)base.Data; } 
     set { base.Data = value; } 
    } 
} 

JSON Ergebnis Klasse:

public class AngularJsonResult : JsonResult 
{ 
    public override void ExecuteResult(ControllerContext context) 
    { 
     DoUninterestingBaseClassStuff(context); 

     SerializeData(context.HttpContext.Response); 
    } 

    private void DoUninterestingBaseClassStuff(ControllerContext context) 
    { 
     if (context == null) 
     { 
      throw new ArgumentNullException("context"); 
     } 

     var response = context.HttpContext.Response; 
     response.ContentType = string.IsNullOrEmpty(ContentType) ? "application/json" : ContentType; 

     if (ContentEncoding != null) 
     { 
      response.ContentEncoding = ContentEncoding; 
     } 
    } 

    protected virtual void SerializeData(HttpResponseBase response) 
    { 
     if (ErrorMessages.Any()) 
     { 
      Data = new 
      { 
       ErrorMessage = string.Join("\n", ErrorMessages), 
       ErrorMessages = ErrorMessages.ToArray() 
      }; 

      response.StatusCode = 400; 
     } 

     if (Data == null) return; 

     response.Write(Data.ToJson()); 
    } 
} 

Serialisierung Objekt JSON:

public static class JsonExtensions 
{ 
    public static string ToJson<T>(this T obj, bool includeNull = true) 
    { 
     var settings = new JsonSerializerSettings 
     { 
      ContractResolver = new CamelCasePropertyNamesContractResolver(), 
      Converters = new JsonConverter[] { new StringEnumConverter() }, 
      ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore,//newly added 
      //PreserveReferencesHandling =Newtonsoft.Json.PreserveReferencesHandling.Objects, 
      NullValueHandling = includeNull ? NullValueHandling.Include : NullValueHandling.Ignore 
     }; 
     return JsonConvert.SerializeObject(obj, settings); 
    } 
} 

Her e ich definierte AngularJson Methode zum Übergeben von Objekt und überschreiben ExecuteResult Methode zum Konvertieren von Objekt in JSON.

Also meine SerializeData Methode vorging Response und Objet in JSON konvertieren, wie Data.ToJson()

Bitte teilen Sie mir Ihre Anregungen wissen.

+0

Ist dieser Code implementiert, auf einem Testserver die Erweiterungsmethode anstelle von response.Write(Data.ToJson()); verwenden oder testen Sie es durch ein:

Die folgende Erweiterungsmethode kann dafür verwendet werden IDE? Welche IDE verwendest du? –

+0

Ja, dieser Code wird auf dem Testserver bereitgestellt. –

+0

Das könnte also ein JVM-Speicherproblem sein - das klingt so, als hätten Sie nicht genügend Speicher zugewiesen, um das zu verarbeiten, was Sie gerade serialisieren wollen. Wie groß sind die Daten? –

Antwort

1

Ihr Problem ist, dass Sie auf dem Server Ihre großen Daten in einen String im Speicher Serialisierung, dann die gesamte Zeichenfolge schriftlich an die HttpResponseBase (das auch alles durch Standardpuffer), und irgendwo aus dem Speicher laufen in der Prozess, möglicherweise durch Überschreiten der maximum c# string length.

Eine Möglichkeit, die Speicherbelegung zu reduzieren, besteht darin, die Seriennummer direkt zu HttpResponseBase.OutputStream unter Verwendung von JsonSerializer.Serialize() zu serialisieren. Dies vermeidet die Zwischenzeichenkettedarstellung.

Sie kann müssen auch HttpResponseBase.Buffer = false setzen, und wenn ja, folgen Sie den gegebenen Rat in Unbuffered Output Very Slow und wickeln Sie den Ausgangsstrom in einem BufferedStream.

public static class HttpResponseBaseExtensions 
{ 
    public static void WriteJson<T>(this HttpResponseBase response, T obj, bool useResponseBuffering = true, bool includeNull = true) 
    { 
     var contentEncoding = response.ContentEncoding ?? Encoding.UTF8; 
     if (!useResponseBuffering) 
     { 
      response.Buffer = false; 

      // use a BufferedStream as suggested in //https://stackoverflow.com/questions/26010915/unbuffered-output-very-slow 
      var bufferedStream = new BufferedStream(response.OutputStream, 256 * 1024); 
      bufferedStream.WriteJson(obj, contentEncoding, includeNull); 
      bufferedStream.Flush(); 
     } 
     else 
     { 
      response.OutputStream.WriteJson(obj, contentEncoding, includeNull); 
     } 
    } 

    static void WriteJson<T>(this Stream stream, T obj, Encoding contentEncoding, bool includeNull) 
    { 
     var settings = new JsonSerializerSettings 
     { 
      ContractResolver = new CamelCasePropertyNamesContractResolver(), 
      Converters = new JsonConverter[] { new StringEnumConverter() }, 
      ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore,//newly added 
      //PreserveReferencesHandling =Newtonsoft.Json.PreserveReferencesHandling.Objects, 
      NullValueHandling = includeNull ? NullValueHandling.Include : NullValueHandling.Ignore 
     }; 
     var serializer = JsonSerializer.CreateDefault(settings); 
     var textWriter = new StreamWriter(stream, contentEncoding); 
     serializer.Serialize(textWriter, obj); 
     textWriter.Flush(); 
    } 
} 

Dann