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

时间:2015-03-25 16:16:30

标签: javascript ajax wcf post

首先,我是一名新开发者,所以如果我错过了一些明显的东西,我会提前道歉。

我正在开发一个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之后。

提前感谢任何帮助,反馈,批评等。

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

}

然后我更改了contract方法以接受我创建的对象而不是字符串。 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);