2017-01-27 5 views
14

Я только что обновил свой сервис mvc, чтобы включить большую ошибку и протоколирование. Я получил эту точную ошибку несколько раз. Но не может реплицироваться.Почему мой пост ajax усечен?

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 } 
     }) 

В этих случаях, ID_пользователь и 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); 
    } 
} 

Я полностью тупик, я попытался обновить web.config на сервере с большим maxvalues ​​и т.д., чтобы увидеть его усечения на той стороне.

Единственное отличие, которое у меня есть в моем ajax, - это глобальный тайм-аут в 3 минуты.

Является ли это так же просто, как специальные символы, которые не обрабатываются на стороне клиента или ограничения на стороне сервера, или данные настолько велики, что их обрывают, а серверная сторона не знает, ждать следующего фрагмента?

+0

Насколько велики ** данные **? – stuartd

+0

Его до тех пор, как кусок строки tbh. Я записываю параметры http перед десериализацией и т. Д. (HttpContext.Request.Params.ToString()). Итак, одна из неудачных запросов - 117 454 символов? –

+0

Также только что проверили, у меня есть параметры этого размера 3,119,214. Который не подвел? Могу ли я исключить усечение из-за размера? –

ответ

0

С помощью нескольких комментариев, ответов и, наконец, полученных данных с ошибкой, я смог это разрешить.

Оказалось, что пользователь не только использовал специальные символы, но и некоторые из статических данных, отправленных вниз, включили это (GIGO - не мог поверить в состояние некоторых наших данных).

стороне клиента Решение:

Функция encodeURIComponent() кодирует компонент URI. Эта функция кодирует специальные символы. Кроме того, он кодирует следующие символы:, /? : @ & = + $ #

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

Server Side Решение:

Преобразует строку в немаскированном представлении. 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); 
    } 
} 

Web Конфигурация приложения:

У меня был пользователь, получая ошибку 500, из-за пытается отправить 20 писем. Я обновил конфигурацию, чтобы включить максимальную длину запроса (в килобайтах, пример - 1 ГБ) и максимальную длину содержимого (в байтах, пример - 1 ГБ). Письма не возникли. Не мог поверить!

<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> 
0

Вы не указали, какую версию jQuery вы используете, но когда мы предполагаем стабильную версию, мы можем быть уверены, что необходимая кодировка и экранирование в нижнем ряду $.ajax() безупречны.

Если причиной была длина запроса, мы увидим ошибку http на стороне клиента и отсутствие вызова функции на стороне сервера («максимальная длина запроса превышена»). Это подтверждается вашим наблюдением, что запросы с более длинными строками могут преуспеть, а короткие - сбой.

Я хотел бы предложить два действия:

1) Для уменьшения фрагментации, отводками и возможные диагнозы в заблуждение, не стоит JSONify только телеметрия. Построить свой объект из телеметрических, ID_пользователя и isMyVi, затем JSONify , что в целом (это означает, что, включают в себя метаданные в TelemetryMapping описания, если это возможно)

2) Проверить значение telemetry.JSONify() во время выполнения на стороне клиента , Если вы обнаружите, что это усечение вызвано этим, сосредоточьтесь на версии и целостности нокаутаJS или замените. Как @Destrif отмечает в своем комментарии, https://stackoverflow.com/a/21565447/1132334 предполагает, что она не может быть частью задач knockoutJS, чтобы избежать двойных кавычек, обратной косой черты и хлещет -

, которые могут быть столь же просто, как обертывание вызов в другой escape():

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

Функция escape() устарела в JavaScript версии 1.5. Вместо этого используйте encodeURI() или encodeURIComponent(). –

1

Предлагаю вам использовать скрипач для получения приблизительного представления о том, какие данные действительно отправлены. Несомненно, проблема де-сериализации и ваш код выглядит полностью. Размер данных не должен быть проблемой здесь, получить некоторое представление данных, и вы должны быть в порядке.

Также проверьте, правильно ли отформатированы данные в формате JSONify(), не выходя из последовательности символов.

1

Попробуйте использовать encodeURIComponent для содержимого, введенного пользователем.