«Недопустимый примитив JSON» при обработке Ajax

101

Я получаю сообщение об ошибке при вызове ajax из jQuery.

Вот моя функция jQuery:

function DeleteItem(RecordId, UId, XmlName, ItemType, UserProfileId) {
    var obj = {
        RecordId: RecordId,
        UserId: UId,
        UserProfileId: UserProfileId,
        ItemType: ItemType,
        FileName: XmlName
    };
    var json = Sys.Serialization.JavaScriptSerializer.serialize(obj);

    $.ajax({
        type: "POST",
        url: "EditUserProfile.aspx/DeleteRecord",
        data: json,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        async: true,
        cache: false,
        success: function(msg) {
            if (msg.d != null) {
                RefreshData(ItemType, msg.d);
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert("error occured during deleting");
        }
    });
}

а это мой WebMethod:

[WebMethod]
public static string DeleteRecord(Int64 RecordId, Int64 UserId, Int64 UserProfileId, string ItemType, string FileName) {
    try {
        string FilePath = HttpContext.Current.Server.MapPath(FileName);

        XDocument xmldoc = XDocument.Load(FilePath);
        XElement Xelm = xmldoc.Element("UserProfile");
        XElement parentElement = Xelm.XPathSelectElement(ItemType + "/Fields");

        (from BO in parentElement.Descendants("Record")
         where BO.Element("Id").Attribute("value").Value == RecordId.ToString()
         select BO).Remove();
        XDocument xdoc = XDocument.Parse(Xelm.ToString(), LoadOptions.PreserveWhitespace);
        xdoc.Save(FilePath);

        UserInfoHandler obj = new UserInfoHandler();
        return obj.GetHTML(UserId, UserProfileId, FileName, ItemType, RecordId, Xelm).ToString();
    } catch (Exception ex) {
        HandleException.LogError(ex, "EditUserProfile.aspx", "DeleteRecord");
    }
    return "success";
}

Кто-нибудь может сказать мне, что не так в моем коде?

Я получаю эту ошибку:

{
    "Message":"Invalid JSON primitive: RecordId.",
    "StackTrace":"
       at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializePrimitiveObject()
       at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)
       at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)
       at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)
       at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)
       at System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer)
       at System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext context)
       at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)",
    "ExceptionType":"System.ArgumentException"
}
Радхи
источник
Я не понимаю. Javascript посвящен AddAlbumToMyProfile, а WebMethod называется DeleteRecord. Вы уверены, что показываете нам правильные фрагменты кода?
jitter
Есть ли шанс, что вы также можете записать, как выглядит POST (с помощью firebug или еще чего), и добавить его к вопросу? Я не уверен, так ли вы кодируете данные перед их отправкой, но вы также можете попробовать сериализовать его с помощью этого ( json.org/json2.js ).
R0MANARMY

Ответы:

136

Просто угадайте, что jsonсодержит переменная после

var json = Sys.Serialization.JavaScriptSerializer.serialize(obj);?

Если это действительный объект json, например, {'foo':'foovalue', 'bar':'barvalue'}jQuery может не отправлять его как данные json, а вместо этого сериализовать его, чтобы foor=foovalue&bar=barvalueвы получили ошибку"Invalid JSON primitive: foo"

Вместо этого попробуйте установить данные как строку

$.ajax({
    ...
    data: "{'foo':'foovalue', 'bar':'barvalue'}", //note the additional quotation marks
    ...
})

Таким образом, jQuery должен оставить данные в покое и отправить строку как есть на сервер, что должно позволить ASP.NET анализировать серверную часть json.

дрожь
источник
5
спасибо за разъяснения, добавьте еще один комментарий, вы всегда можете сделать как JSON.stringify ({foo: 'foovalue', bar: 'barvalue'}) для облегчения жизни
Элейн
На десять лет позже вечеринки, но все еще актуально: это недопустимый JSON. Строки (включая имена свойств) в JSON должны использовать двойные кавычки , так что это должно быть {"foo": "foovalue", "bar": "barvalue"}. Использование одинарных кавычек является синтаксической ошибкой.
Майк Камерманс «Pomax»,
108

С помощью

data : JSON.stringify(obj)

Я считаю, что в вышеуказанной ситуации сработало бы.

Примечание. Вам следует добавить библиотеку json2.js, все браузеры не поддерживают этот объект JSON (IE7-). Разница между json.js и json2.js.

Андрей
источник
3
Спасибо! При использовании простых классов JS это работает. Я перешел data: { JSON.stringify(obj) }на data: JSON.stringify(obj)(Мой класс javascript / JSON для сериализации соответствует стилю var myObj = { title: "x", subclass = someVar, ... } )
lko
1
Обратите внимание, что это решение при условии, что вам действительно нужно отправить JSON ( что вы можете с веб-службами asp.net ). В других случаях может быть проще просто удалитьcontentType и позволить jQuery передавать данные в кодировке формы.
GSerg
19

Как было отмечено джиттером, $.ajaxфункция сериализует любой объект / массив, используемый в качестве dataпараметра, в формат с кодировкой URL. Как ни странно, этот dataTypeпараметр применяется только к ответу сервера, а не к каким-либо данным в запросе.

Столкнувшись с той же проблемой, я загрузил и использовал плагин jquery-json для правильного кодирования данных запроса в ScriptService. Затем использовал $.toJSONфункцию для кодирования необходимых аргументов для отправки на сервер:

$.ajax({
    type: "POST",
    url: "EditUserProfile.aspx/DeleteRecord",
    data: $.toJSON(obj),
    contentType: "application/json; charset=utf-8",
    dataType: "json"
    ....
});
leepowers
источник
2
спасибо, что указали, что dataпараметр игнорируется вызовом.
Ноэль Абрахамс
3
Это работает, но изменение data: { JSON.stringify(obj) }на data: JSON.stringify(obj)сработало для меня, если ваш класс javascript соответствует стилю var myObj = { title: "x", subclass = someVar, ... } благодаря пункту о кодировке данных.
lko
19

это работает примерно так

data: JSON.stringify({'id':x}),
Джессика Саенс
источник
3
Этот ответ оказался в очереди на проверку низкого качества, предположительно из-за того, что вы не предоставили никакого объяснения кода. Если этот код отвечает на вопрос, подумайте о добавлении текста, объясняющего код, в свой ответ. Таким образом, у вас гораздо больше шансов получить больше голосов и помочь человеку, задавшему вопрос, узнать что-то новое.
lmo,
Я хочу передать два параметра: массив сложного объекта и целое число. Я делаю это: данные: {items: JSON.stringify (myarray), myId: value}.
A.Dara 01
13

JQuery Ajax по умолчанию отправляет данные в виде параметров строки запроса, например:

RecordId=456&UserId=123

если для processDataпараметра не установлено значение false, и в этом случае он будет отправлен как объект на сервер.

  • contentType Опция предназначена для сервера, в каком формате клиент отправил данные.

  • dataType Параметр предназначен для сервера, который сообщает, какой тип данных клиент ожидает от сервера.

Не указывайте contentType, чтобы сервер анализировал их как параметры строки запроса, а не как json.

ИЛИ

Используйте contentType как application / json; charset = utf-8 'и используйте JSON.stringify (объект), чтобы сервер мог десериализовать json из строки.

Т Гупта
источник
5

Думаю, @jitter был прав в своем предположении, но его решение не сработало для меня.

Вот что это сработало:

$.ajax({
    ...
    data: "{ intFoo: " + intFoo + " }",
    ...
});

Я не пробовал, но думаю, что если параметр является строкой, он должен быть таким:

$.ajax({
    ...
    data: "{ intFoo: " + intFoo + ", strBar: '" + strBar + "' }",
    ...
});
Диего
источник
9
Если бы мне пришлось написать такой код (строковое конкатенирование) для создания объектов JSON, я бы убил себя (образно говоря). Там должен быть лучший способ.
PandaWood
3

Я столкнулся с той же проблемой, я пришел с хорошим решением, как показано ниже:

Попробуй это...

$.ajax({
    type: "POST",
    url: "EditUserProfile.aspx/DeleteRecord",
    data: '{RecordId: ' + RecordId + ', UserId: ' + UId + ', UserProfileId:' + UserProfileId + ', ItemType: \'' + ItemType + '\', FileName: '\' + XmlName + '\'}',
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    async: true,
    cache: false,
    success: function(msg) {
        if (msg.d != null) {
            RefreshData(ItemType, msg.d);
        }
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        alert("error occured during deleting");
    }
});

Обратите внимание, что здесь для параметра строкового типа я использовал символ escape-последовательности (\ ') для обозначения его как строкового значения.

Соэль Патан
источник
data: "{Notes: \" "+ $ ('# txtNotes'). val () +" \ "}
bestinamir
1

Если вы форматируете JSON вручную, здесь есть очень удобный валидатор: jsonlint.com

Используйте двойные кавычки вместо одинарных:

Недействительным:

{
    'project': 'a2ab6ef4-1a8c-40cd-b561-2112b6baffd6',
    'franchise': '110bcca5-cc74-416a-9e2a-f90a8c5f63a0'
}

Действителен:

{
    "project": "a2ab6ef4-1a8c-40cd-b561-2112b6baffd6",
    "franchise": "18e899f6-dd71-41b7-8c45-5dc0919679ef"
}
Даниэль де Цваан
источник
0

На сервере для сериализации / десериализации json в настраиваемые объекты:

public static string Serialize<T>(T obj)
{
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
    MemoryStream ms = new MemoryStream();
    serializer.WriteObject(ms, obj);
    string retVal = Encoding.UTF8.GetString(ms.ToArray());
    return retVal;
}

public static T Deserialize<T>(string json)
{
    T obj = Activator.CreateInstance<T>();
    MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
    obj = (T)serializer.ReadObject(ms);
    ms.Close();
    return obj;
}
Иоаннис Суарес
источник
0

Я была такая же проблема. Я вызывал родительскую страницу «Сохранить» из всплывающего окна Close. Обнаружено, что я использовал ClientIDMode="Static"как родительскую, так и всплывающую страницу с одним и тем же идентификатором элемента управления. Удаление ClientIDMode="Static"с одной из страниц решило проблему.

Минту Гоял
источник
0

Здесь dataTpe - это "json", поэтому data / reqParam должен быть в форме строки при вызове API, столько же, сколько и объект, но, наконец, внутри данных $ .ajax преобразовать объект в строку.

             let person= {  name: 'john',
                age: 22
            };

           var personStr = JSON.stringify(person); 

            $.ajax({
                url: "@Url.Action("METHOD", "CONTROLLER")",
                type: "POST",
                data: JSON.stringify( { param1: personStr } ),
                contentType: "application/json;charset=utf-8",
                dataType: "json",
        success: function (response) {

            console.log("Success");

        },
        error: function (error) {
            console.log("error found",error);
        }
    });

ИЛИ,

       $.ajax({
                url: "@Url.Action("METHOD", "CONTROLLER")",
                type: "POST",
                data: personStr,
                contentType: "application/json;charset=utf-8",
                dataType: "json",
        success: function (response) {

            console.log("Success");

        },
        error: function (error) {
            console.log("error found",error);
        }
    });
Гаурав Баснет
источник
-2

эти ответы заставили меня подпрыгивать между недопустимым параметром и отсутствующим параметром.

это сработало для меня, просто заключите строковые переменные в кавычки ...

data: { RecordId: RecordId,
            UserId: UId,
            UserProfileId: UserProfileId,
            ItemType: '"' +  ItemType + '"',
            FileName: '"' +  XmlName + '"'
    }
вернмик
источник