我正在尝试使用JSON序列化数据。但我面临例外情况。
OutOfMemoryException未被用户代码处理 类型' System.OutOfMemoryException'的例外情况发生在Newtonsoft.Json.dll但未在用户代码中处理
下面我定义了我的代码:
主控制器:
public class TrackingController : BaseAngularController
{
var lstDetails = _services.GetTrackingDetailsByAWBIds(awbids, awbType);
if (lstDetails != null)
{
return AngularJson(lstDetails);
}
}
基本控制器:
public abstract class BaseAngularController : Controller
{
public AngularJsonResult<T> AngularJson<T>(T model)
{
return new AngularJsonResult<T>() { Data = model };
}
}
Angular JSON结果类:
public class AngularJsonResult<T> :AngularJsonResult
{
public new T Data
{
get { return (T)base.Data; }
set { base.Data = value; }
}
}
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());
}
}
将对象序列化为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);
}
}
这里我定义了传递对象的AngularJson
方法,并覆盖了将对象转换为JSON的ExecuteResult
方法。
因此我的SerializeData
方法正在传递Response
并转换为JSON中的Objet,例如Data.ToJson()
请告诉我你的建议。
答案 0 :(得分:1)
您的问题是您将大数据序列化到服务器内存中的字符串,然后将整个字符串写入HttpResponseBase
(默认情况下也会缓存所有内容),并且在过程中的某个地方耗尽了内存,可能超过了maximum c# string length。
减少内存使用的一种方法是使用HttpResponseBase.OutputStream
直接序列化为JsonSerializer.Serialize()
。这避免了中间字符串表示。
您可能还需要设置HttpResponseBase.Buffer = false
,如果是,请按照Unbuffered Output Very Slow中给出的建议将输出流包装在BufferedStream
中。< / p>
可以使用以下扩展方法:
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());