2016-08-01 19 views
2

JSONでデータをシリアル化しようとしています。しかし、私は例外の下で直面している。JSONオブジェクトが巨大なデータに対してシリアル化されない

OutOfMemoryExceptionがユーザーコードによって処理されませんでした。

メインコントローラ:

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

型 'System.OutOfMemoryExceptionに' の例外は、私は私のコードを定義し

下Newtonsoft.Json.dllで発生したが、ユーザーコードで処理されませんでした

ベースコントローラ:

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

角度JSON結果クラス:

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

JSON結果クラス:JSONにオブジェクトをシリアライズ

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()); 
    } 
} 

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); 
    } 
} 

彼女私はAngularJsonオブジェクトを渡すメソッドを定義し、オブジェクトをJSONに変換するメソッドExecuteResultをオーバーライドしました。

だから私のSerializeData方法はResponseを渡し、私はあなたの提案をお聞かせくださいData.ToJson()

のように、JSONでオブジェに変換しました。

+0

の代わりに拡張メソッドを使用して、このコードは、テストサーバー上で、展開されている、またはあなたがANを通してそれをテストしていますIDE?どのIDEを使用していますか? –

+0

はい、このコードはテストサーバーにデプロイされています。 –

+0

これはJVMのメモリの問題かもしれません - これは、シリアル化しようとしているものを処理するのに十分なメモリを割り当てていないように思えます。データの量はどれくらいですか? –

答えて

1

あなたの問題は、あなたが(また、デフォルトではすべてのものをバッファリングする)、その後HttpResponseBaseに文字列全体を書いて、サーバー上のメモリ内の文字列にご膨大なデータをシリアライズし、どこかでメモリが不足しているということです可能であればmaximum c# string lengthを超過します。

HttpResponseBase.OutputStreamに直接JsonSerializer.Serialize()を使用してシリアル化する方法があります。これにより、中間の文字列表現が回避されます。

あなたHttpResponseBase.Buffer = falseを設定する必要があり、そうであれば、Unbuffered Output Very Slowに与えられたアドバイスに従うと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(); 
    } 
} 

その後response.Write(Data.ToJson());

関連する問題