【问题标题】:Error during serialization using the JSON JavaScriptSerializer. Should be using the JSON.NET JsonSerializer使用 JSON JavaScriptSerializer 进行序列化时出错。应该使用 JSON.NET JsonSerializer
【发布时间】:2013-12-03 23:46:08
【问题描述】:

我已将 Newton Soft 添加到组合中,并使用此博客作为模板:http://wingkaiwan.com/2012/12/28/replacing-mvc-javascriptserializer-with-json-net-jsonserializer/

我现在有:

public class BaseJsonController : BaseController
{
    protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        return new JsonNetResult
        {
            Data = data,
            ContentType = contentType,
            ContentEncoding = contentEncoding,
            JsonRequestBehavior = behavior
        };
    }
}

public class JsonNetResult : JsonResult
{
    public JsonNetResult()
    {
        Settings = new JsonSerializerSettings
        {
            ReferenceLoopHandling = ReferenceLoopHandling.Error
        };
    }

    public JsonSerializerSettings Settings { get; private set; }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");
        if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            throw new InvalidOperationException("JSON GET is not allowed");

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

        if (this.ContentEncoding != null)
            response.ContentEncoding = this.ContentEncoding;
        if (this.Data == null)
            return;

        var scriptSerializer = JsonSerializer.Create(this.Settings);

        using (var sw = new StringWriter())
        {
            scriptSerializer.Serialize(sw, this.Data);
            response.Write(sw.ToString());
        }
    }
}

现在,在我的控制器中,我这样做了:

[HandleError]
public class ProcurementActionsController : BaseJsonController
{
    ...

    [GridAction]
    [AcceptVerbs(HttpVerbs.Post)]
    public JsonResult AjaxGetAll(string pageFilter = null, string searchTerm = null)
    {
        var rawData = GetProcurementActions(pageFilter);
        return new JsonNetResult 
        {
            Data = new GridModel { Data = rawData },
            JsonRequestBehavior = JsonRequestBehavior.AllowGet,
            Settings = { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }
        };
    }

    ...

}

但是,我仍然遇到同样的错误!根据堆栈跟踪,它仍在尝试使用 JavaScriptSerializer 而不是 JsonSerializer

[InvalidOperationException: Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.]
   System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, StringBuilder output, SerializationFormat serializationFormat) +188
   System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj) +56
   System.Web.Mvc.JsonResult.ExecuteResult(ControllerContext context) +418
   System.Web.Mvc.<>c__DisplayClass14.<InvokeActionResultWithFilters>b__11() +31
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +656883
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +656883
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +254
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +658100
   System.Web.Mvc.Controller.ExecuteCore() +125
   System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__4() +48
   System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
   System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +15
   System.Web.Mvc.Async.WrappedAsyncResult`1.End() +85
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +51
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +454
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +263

是因为异步调用吗?如果是这样,我需要在我的 BaseJsonController 中覆盖什么才能让它调用正确的 ExecuteResult(...) 方法?

【问题讨论】:

    标签: asp.net-mvc json.net jsonresult actionmethod


    【解决方案1】:

    在 MVC 4 和 5 中,这应该可以通过 web 配置文件中的参数轻松修复。

    我在 MVC3 中遇到了同样的问题,只是通过在 app_start 中替换 ValueProviderFactories 来解决它,遵循这个线程:

    http://forums.asp.net/t/1751116.aspx

    【讨论】:

    • 我确实将此代码添加到我们的代码库中。但是,这是针对入站 JSON 的,我正在尝试解决出站 JSON 问题。我找到了另一种方法来完成它(请参阅下面的答案)...
    【解决方案2】:
        [GridAction]
        [AcceptVerbs(HttpVerbs.Post)]
        public JsonResult AjaxGetAll(string pageFilter = null, string searchTerm = null)
        {
            var rawData = GetProcurementActions(pageFilter);
            var gridData = new GridModel { Data = rawData };
            var json = JsonConvert.SerializeObject(gridData).Replace("\"Total\":0,\"Aggregates\":null", String.Format("\"Total\":{0},\"Aggregates\":null", rawData.Count));
    
            return new ContentResult { Content = json, ContentType = "application/json" };
        }
    
    1. 从数据库中获取数据。
    2. 需要将 ViewModel(列表)转换为 Telerik 的 GridModel 对象。
    3. 使用 Newton Soft 的 JsonSerializer 将 GridModel 转换为 JSON 字符串(这里没有长度限制!) Telerik Grid 需要知道总记录,但由于某种原因它不在 JSON 中。通过 Replace() 方法更新它。
    4. 使用 ContentResult 对象而不是 ActionResult 或 JsonResult。有了它,您可以定义自己的数据负载。

    这个精确解决方案的唯一缺点是它最终会达到 4GB 左右。到那时,它可能会使大多数浏览器崩溃,除非您有办法对返回进行分块。我会添加一个最大长度检查并抛出一个错误。

    【讨论】:

      猜你喜欢
      • 2021-09-02
      • 2015-01-11
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-07
      • 1970-01-01
      相关资源
      最近更新 更多