尝试 Post 大 JSON 数据时出现错误请求错误

Bad Request Errors when trying to Post large JSON data

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

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

我还在使用名为 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.

在此先感谢您的帮助、反馈、批评等。

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

编码使字符串化 json 膨胀。您可以停在 webdata 和 post 本身,删除 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);
}

我想通了我的问题。我一直在尝试将字符串传递给合同方法,但我一直收到错误的请求错误。相反,我包装了 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);
            }

        });

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

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