为什么我的ajax帖子会被截断?

时间:2017-01-27 16:35:30

标签: c# jquery ajax iis knockout.js

我刚刚更新了我的mvc服务,以包含更大的错误和日志记录。我现在有几次这个确切的错误。但无法复制。

Unterminated string. Expected delimiter: ". Path 'Breadcrumbs[18].Params', line 1, position 59740. at Newtonsoft.Json.JsonTextReader.ReadStringIntoBuffer(Char quote) at 

每次路径都不同,具体取决于用户发送到服务器的内容。

我的ajax请求通常如下所示:

$.ajax(myURL("SendBreadcrumbs"), {
            type: "POST",
            cache: false,
            data: { telemetry: telemetry.JSONify(), userID: currentUser, isMyVI: isMyVI }
        })

在这些情况下,userID和isMyVI(布尔值)不存在,遥测字符串被截断。

JSONify方法如下:

self.JSONify = function () {
    var data = ko.mapping.toJSON(self, TelemetryMapping);
    return data;
}

这是knockoutJSs序列化器。

服务器端:

public void SendBreadcrumbs(string telemetry, string userID = null, bool isMyVI = true)
{
    MyServiceAudit audit;
    Guid UserID;
    if (Guid.TryParse(userID, out UserID))
        audit = InsertAudit(UserID);
    else
        audit = InsertAudit(null);
    try
    {
        Models.Telemetry data = JsonConvert.DeserializeObject<Models.Telemetry>(telemetry);
        Controllers.Telemetry.UpdateTelemetry(data, isMyVI);
    }
    catch (Exception ex)
    {
         MyServiceAuditDB.FailAudit(audit.ID, ex.Message + " " + ex.StackTrace);
    }
}

我完全难过了,我尝试在服务器上更新了更大的maxvalues等的web.config,看看它在那边截断。

我在ajax中唯一的另一个区别是全局超时3分钟。

这是否像在客户端没有处理的特殊字符或服务器端限制一样简单,或者数据是如此之大以至于它被分块并且服务器端不知道等待下一个块?

4 个答案:

答案 0 :(得分:1)

我建议您使用提琴手来粗略了解实际发送的数据。这肯定是反序列化的问题,你的代码看起来完全没问题。数据的大小不应该是一个问题,获得一些数据的原始视图,你应该没事。

同时查看JSONify()是否正确返回格式化数据而不转义字符序列。

答案 1 :(得分:1)

尝试将encodeURIComponent用于用户输入的内容。

答案 2 :(得分:0)

您没有指定您正在使用的jQuery版本,但是当我们假设稳定版本时,我们可以确保在$.ajax()的下线中进行必要的编码和转义是完美的。

如果请求长度是原因,我们会在客户端看到http错误,并且没有调用服务器端函数(&#34;超出最大请求长度&#34;)。您的观察结果支持这一点,即具有较长字符串的请求可以成功,而较短字符串可能会失败。

我建议采取两项行动:

1)为了减少碎片,分层和可能的误导性诊断,请不要仅仅对遥测进行JSON化。用遥测,userID和isMyVi构建你的对象,然后整个JSONify (这意味着,如果可能的话,在TelemetryMapping描述中包含元数据)

2)在运行时客户端检查telemetry.JSONify()的值。如果您发现截断是由此引起的,请关注knockoutJS版本和完整性,或者替换。正如@Destrif在评论中指出的那样,https://stackoverflow.com/a/21565447/1132334表明它可能不属于knockoutJS的任务,以逃避双引号,反斜杠和斜杠 -

可能就像将呼叫包裹在另一个escape()中一样简单:

self.JSONify = function () {
    var data = escape(ko.mapping.toJSON(self, TelemetryMapping));
    return data;
}

答案 3 :(得分:0)

在一些评论,答案和最终获得实时失败的数据的帮助下,我能够解决这个问题。

事实证明,用户不仅使用了特殊字符,而且还发送了一些静态数据(GIGO - 无法相信我们某些数据的状态)。

客户端解决方案:

encodeURIComponent()函数对URI组件进行编码。 此功能对特殊字符进行编码。另外,它编码以下字符:,/? :@&amp; = + $#

$.ajax(myURL("SendBreadcrumbs"), {
        type: "POST",
        cache: false,
        data: { telemetry: encodeURIComponent(telemetry.JSONify()), userID: currentUser, isMyVI: isMyVI }
    })

服务器端解决方案:

将字符串转换为未转义的表示形式。 Uri.UnescapeDataString()

public void SendBreadcrumbs(string telemetry, string userID = null, bool isMyVI = true)
{
    MyServiceAudit audit;
    Guid UserID;
    if (Guid.TryParse(userID, out UserID))
        audit = InsertAudit(UserID);
    else
        audit = InsertAudit(null);
    try
    {
        Models.Telemetry data = JsonConvert.DeserializeObject<Models.Telemetry>(Uri.UnescapeDataString(telemetry));
        Controllers.Telemetry.UpdateTelemetry(data, isMyVI);
    }
    catch (Exception ex)
    {
         MyServiceAuditDB.FailAudit(audit.ID, ex.Message + " " + ex.StackTrace);
    }
}

网络应用程序配置:

由于尝试发送了20封电子邮件,我的用户收到了500错误。我更新了配置,包括最大请求长度(以千字节为单位,例如1GB)和最大内容长度(以字节为单位,例如1GB)。电子邮件没有问题。无法相信!

<appSettings>
    <add key="aspnet:MaxJsonDeserializerMembers" value="150000" />
</appSettings>
<system.web>
    <httpRuntime targetFramework="4.5" maxQueryStringLength="32768" maxUrlLength="65536" maxRequestLength="1048576" />
</system.web>
<system.webServer>
    <security>
        <requestFiltering>
            <requestLimits maxQueryString="32768" maxAllowedContentLength="1073741824"  />
        </requestFiltering>
    </security>
</system.webServer>
<system.web.extensions>
    <scripting>
        <webServices>
            <jsonSerialization maxJsonLength="2147483647" />
        </webServices>
    </scripting>
</system.web.extensions>