【问题标题】:Sending large JSON data from C# Web API to Javascript Client将大型 JSON 数据从 C# Web API 发送到 Javascript 客户端
【发布时间】:2017-03-23 17:29:17
【问题描述】:

我对服务器的调用是按以下方式构建的:

  • 我在客户端上有一个 callServer 函数,可以将数据发送到我的 API;
  • 然后我的 API 从它的控制器接收数据并将其传递给调用数据库的函数;
  • 控制器将响应发送回客户端。

这就是我的做法(这些只是代码的重要部分,并非所有内容都在这里):

API (Context.cs):

public static IEnumerable<Dictionary<string, object>> Proc_example(int? value)
    {
        using (NpgsqlConnection conn = new NpgsqlConnection(ConnStr))
        {
            try
            {
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
                    cmd.CommandText = "proc_example";
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;
                    cmd.Parameters.Add(new NpgsqlParameter("value", convertNullValue(value)));

                    var reader = cmd.ExecuteReader();
                    return new DrToDictionary().Serialize(reader);

                }
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                conn.Close();
            }
        }
    }

API (Controller.cs):

[Authorize]

    public JsonResult example(int? value)
    {
        try
        {
            var data = Context.Proc_example(value);

            return Json(new AppServerResult()
            {
                Result = new { list = data }
            }, JsonRequestBehavior.AllowGet);


        }
        catch (Exception e)
        {
            return Json(new AppServerResult()
            {
                HasError = true,
                ErrorMessage = "Houve um erro ao consultar, tente novamente."

            });
        }
    }

客户端(callServer):

app.callServer = function (options, sucessCallback, httpErrCallback, serverErrCallback, operationErrorCallback) {
if (options.source == undefined)
    options.headers = { "Authorization": $.cookie('Token') }

options.success = function (result) {
    try {
        var _result = result;

        if (typeof _result == "string") {
            _result = jQuery.parseJSON(_result);
        }

        if (typeof _result.HasError != "undefined" && _result.HasError) {

            if (!_result.IsValidationError) {
                if (typeof __apiCallerErrorCallback == "function") 
                    __apiCallerErrorCallback(_result.ErrorMessage);

                if (typeof serverErrCallback == "function") {
                    serverErrCallback(_result.ErrorMessage);
                }
            } else {
                app.notifyValidationException(_result.ErrorMessage);                   
            }

        } else {

            if (typeof sucessCallback == "function") {
                if (_result.Result != undefined) sucessCallback(_result.Result);
                else sucessCallback(_result);
            }
        }
    } catch (ex) {

        throw ex;

    }
};

options.error = function (result) {

    if (typeof httpErrCallback == "function") {
        httpErrCallback();
        }
    if (typeof __apiCallerErrorCallback == "function")
        __apiCallerErrorCallback("HTTP Error");
    }

};

jQuery.ajax(options);

};

调用示例:

callingTheServerExample = function (callback, value) {
app.callServer({
    type: "POST",
    url: app.webAPIRootPath + "Controller/example",
    data: "{ 'value':" + JSON.stringify(ko.toJS(value)) + " }",
    contentType: "application/json; charset=utf-8",
    dataType: "json"
}, function (result) {
    if (typeof callback == "function")
        callback(result);
});
}

我的问题是,当我的 JSON 变得太大时,我的 API 在将数据发送回客户端时给了我一个 JsonMaxLength 异常(异常发生在控制器类上)。我不想将我的 maxJsonLength 设置为更高的值。相反,我想找到一种方法从 API 中以块的形式发送我的 JSON,并通过 javascript 将其安装在客户端上。

有办法吗?

编辑:

我忘了添加一个细节:我使用的是 REST API。正如下面的 cmets 所述,分页是一种解决方案,但我需要的是让整个记录集立即可用。可以使用分页来做到这一点,但它似乎更慢并且会导致更多的 API 调用。 Streaming 似乎是一个解决方案,但我以前从未这样做过,我不知道如何实现它。

编辑 2:

我已经这样实现了我的分页:

         public JsonResult example(int? value, int page)
    {
        try
        {
            var data = Context.Proc_example(value, page);

            if (pPage > 0)
            {
                var pagedResult = data.Skip((page - 1) * 20).Take(20).ToList();

                return Json(new AppServerResult()
                {
                    Result = new { list = data}
                }, JsonRequestBehavior.AllowGet);
            }
            else
            {
                return Json(new AppServerResult()
                {
                    Result = new { list = data}
                }, JsonRequestBehavior.AllowGet);
            }

        }
        catch (Exception e)
        {
            return Json(new AppServerResult()
            {
                HasError = true,
                ErrorMessage = "Houve um erro ao consultar, tente novamente."

            });
        }
    }

但我仍然没有达到我想要的。有人会想出更好的方法吗?

【问题讨论】:

  • 在不设置 maxJsonLength 的情况下执行此操作的一种方法是对数据进行分页并将其与一些标识符一起发送到客户端以获得下一组结果。客户端可以进行另一个 API 调用以获取下一组结果并重复此操作,直到获得整个记录集。
  • @VidhyardhiGorrepati 分页我的结果需要多次调用服务器。只保持一个连接不是更好吗?我正在研究它并找到了这个答案:stackoverflow.com/a/26281258/6882194,但我没有找到任何方法来适应我当前的代码。可能是因为我使用的是 REST API?
  • 有趣的文章。每天学习新东西...

标签: javascript c# json api server


【解决方案1】:

对于 JsonMaxLength 异常

试试

写入 web.config

<system.web.extensions>
<scripting>
  <webServices>
    <jsonSerialization maxJsonLength="1000000">
    </jsonSerialization>
  </webServices>
</scripting>
</system.web.extensions>

默认 maxJsonLength 为 102400。

【讨论】:

    猜你喜欢
    • 2015-04-06
    • 2015-04-05
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-22
    • 2021-10-07
    相关资源
    最近更新 更多