【问题标题】:Bad Request Errors when trying to Post large JSON data尝试发布大型 JSON 数据时出现错误的请求错误
【发布时间】:2015-05-29 10:28:54
【问题描述】:

首先,我是一个新开发者,所以如果我遗漏了一些明显的东西,我提前道歉。

我正在开发一个 Web 应用程序来离线处理 IndexedDB 中的大量数据。当用户访问 webapp 时,客户端从服务器抓取整个数据库并将其存储在 indexeddb 中以供使用。这很好用,但是当我尝试使用 post 方法将数据(再次多条记录)发送回 WCF 时,当我尝试发送 ajax 正文参数时,我得到方法不允许或错误请求,当我使用uri 参数,它会到达服务器,但并非所有数据都已发送。我认为无效字符可能是一个因素,所以我使用 javascript 中的 encodeURIComponent 方法将无效字符转换为在 uri 参数中有效。我还尝试使用名为 LZString 的 javascript 压缩 api 压缩数据。我试过使用 XMLHttpRequest(我不完全理解)。这个 web 应用程序必须离线工作,所以除了在客户端首次打开时最初获取数据并将数据同步回服务器之外,我无法进行服务器调用,这就是为什么我必须一次发送大量数据的原因。

我还在使用名为 Dexie.js 的 IndexedDB 包装器。

我的代码示例如下。一些代码被注释了,但留下来展示我已经尝试过的内容。

这是我在服务器上的..

    [OperationContract]
    [WebInvoke(Method = "POST",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        UriTemplate = "REST_SendCompletedServiceOrders",
        BodyStyle = WebMessageBodyStyle.Wrapped)]
    [FaultContract(typeof (Exception))]
    bool REST_SendCompletedServiceOrders(string compressedWebData);

这是客户端上用于同步回来的点击事件..

$('#syncCompletedData').on('click', function() {

    db.ServiceOrder

        .toArray(function(so) {
            var completedServiceOrders = [];
            for (var i = 0; i < so.length; i++) {
                if (so[i].IsCompleted) {
                    completedServiceOrders.push(so[i]);
                };
            }
            var customerId = sessionStorage.getItem("customerId");
            var companyId = sessionStorage.getItem("companyId");
            var computerId = sessionStorage.getItem("computerId");
            var webData = JSON.stringify({ webCustomerId: customerId, webCompanyId: companyId, webComputerId: computerId, webServiceOrder: completedServiceOrders });
            alert(webData);

            alert("before compression is " + webData.length);

            var URIEncodedWebData = encodeURIComponent(webData);
            var JSONWebData = JSON.stringify(URIEncodedWebData);

        var compressedWebData = LZString.compressToUTF16(JSONWebData);

            alert("after compression is " + compressedWebData.length);
            debugger;

            try {
                $.ajax({
                    type: "POST",
                    url: "MFSRemoteDataService/REST_SendCompletedServiceOrders",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    data: { compressedWebData: compressedWebData },
                    success: function(data) { alert(JSON.stringify(data)); },
                    failure: function(errMsg) {
                        alert(errMsg);
                    }
                });
            } catch (e) {
                alert(e);
            }

        });
});

压缩前数据长度为7707。 压缩后数据长度为1831。

提前感谢您的任何帮助、反馈、批评等。

【问题讨论】:

  • 只是想一想,您是否尝试过在 WCF 的 web.config 中增加 MaxJSONLength 属性?
  • 是的,我试过
  • 问题不在于你发送的数据,而在于WCF能摄入多少。见Similar

标签: javascript ajax wcf post


【解决方案1】:

在所示的 sn-p 中,您正在编写用于 get 的 ajax 数据,这通常意味着您准备了一个 uri。但是,由于他同时使用 post 和 ajax,因此信息将在 post 请求正文中发送,因此不需要编码。

编码使字符串化的 json 膨胀。您可以在 webdata 上停下来并自行发布,删除 ajax 选项中的 dataType 参数,切换到在 ajax 选项中使用traditional:true,它应该都正确地模型绑定。

很难说你的服务器端视图模型是什么样的,但如果接受参数命名为compressedWebData(名称必须准确,结构相同),那么它可能会像这样工作

//code as shown in OP
//replace var webData = with the following
var compressedWebData = { webCustomerId: customerId, webCompanyId: companyId, webComputerId: computerId, webServiceOrder: completedServiceOrders };

try {
     $.ajax({
         type: "POST",
         url: "MFSRemoteDataService/REST_SendCompletedServiceOrders",
         contentType: "application/json",
         data: JSON.stringify(compressedWebData),
         traditional:true,
         success: function(data) { alert(JSON.stringify(data)); },
         failure: function(errMsg) {
             alert(errMsg);
         }
    });
} catch (e) {
   alert(e);
}

【讨论】:

  • 感谢您的回答。我最初试图使用 body 参数,但服务器上似乎没有发生任何事情(没有遇到断点)并且我收到了 400 错误。由于我使用 uri 参数到达服务器,我认为这是要采用的路线,这就是我使用 uri 编码器的原因,因为我发送的数据在服务器上被截断。我需要弄清楚为什么会收到 400 错误,因为我确实需要通过正文发送数据。
  • @JasonClark - 如果您在其中一个过滤器上设置断点,它是否会被 ajax 请求命中?
  • @JasonClark - 您的 completedServiceOrders 中是否有无效字符?你能发布一种淡化的 json 版本吗?
  • 这是一个 JSON 示例,其中确实有 #,这是一个无效的 uri 字符 {"webCustomerId":"10020","webCompanyId":"1","webComputerId": "2","webServiceOrder":[{"AccountID":3828,"AccountName":"Fred's Store #3706","City":"AnyTown",
  • 另外,改成使用body参数后,我现在打到服务器了,但是服务器端的参数是null
【解决方案2】:

我发现了我的问题。我一直在尝试将字符串传递给合同方法,并且不断收到错误的请求错误。相反,我包装了 Json 字符串并将其发送到一个对象,而不是我在服务器上创建的字符串。

我包装了 JSON 并将其发送到 ajax 请求的正文中..

var rawWebData = {
            WebCustomerID: customerId,
            WebCompanyID: companyId,
            WebComputerID: computerId,
            WebServiceOrders: completedServiceOrders
        };
        var rawData = { webData: rawWebData };
        var webData = JSON.stringify(rawData);
            try {
                $.ajax({
                    type: "POST",
                    url: "MFSRemoteDataService/REST_SendCompletedServiceOrders",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    traditional: true,
                    data: webData,
                    success: function (data) {
                        alert(JSON.stringify(data));
                    },
                    failure: function (errMsg) {
                        alert(errMsg);
                    }
                });
            } catch (e) {
                alert(e);
            }

        });

然后我创建了一个类来收集数据...

[DataContract]
public class WebServiceOrder
{
    [DataMember]
    public Int32 WebCustomerID { get; set; }

    [DataMember]
    public Int32 WebCompanyID { get; set; }

    [DataMember]
    public Int32 WebComputerID { get; set; }

    [DataMember]
    public virtual List<ServiceOrder> WebServiceOrders { get; set; }

}

然后我更改了合同方法以接受我创建的对象而不是字符串。 WCF 反序列化了 JSON 字符串。

        [OperationContract]
    [WebInvoke(Method = "POST",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        UriTemplate = "REST_SendCompletedServiceOrders",
        BodyStyle = WebMessageBodyStyle.WrappedRequest)]
    [FaultContract(typeof (Exception))]
    bool REST_SendCompletedServiceOrders(WebServiceOrder webData);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-10
    • 1970-01-01
    • 2019-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-19
    相关资源
    最近更新 更多