尝试发布大型JSON数据时出现错误请求错误

Bad Request Errors when trying to Post large JSON data

本文关键字:错误 请求 数据 布大型 JSON      更新时间:2023-09-26

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

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

我还使用了一个名为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。

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

在所示的片段中,您正在编写用于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);
}

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