"Недійсний примітив 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. Ви впевнені, що показуєте нам правильні фрагменти коду?
тремтіння

Будь-який шанс ви також можете зафіксувати, як виглядає POST (за допомогою firebug чи що-небудь) та додати це до питання? Я не впевнений, чи це спосіб кодування даних перед надсиланням, але ви також можете спробувати серіалізувати їх за допомогою цього ( json.org/json2.js ).
R0MANARMY

Відповіді:


135

Просто здогадка, що містить змінна 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)(My JavaScript / JSON клас сериализации має стиль var myObj = { title: "x", subclass = someVar, ... } )
тілько

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"
    ....
});

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

Я хочу передати два параметри: масив складного об'єкта і ціле число. Я роблю це: data: {items: JSON.stringify (myarray), myId: value}.
А.Дара

дякую за публікацію відповіді. це працювало для мене.
ZMAX

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
Якби мені довелося написати такий код (string concat), щоб створити 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");
    }
});

Будь ласка, зауважте тут, що для параметра типу рядка я використовував (\ ') символ послідовності відходу для позначення його як значення рядка.


data: "{Примітки: \" "+ $ ('# 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

У мене було те саме питання. Я закликав батьківську сторінку "Зберегти" у вікні спливаючих вікон Закрити. Виявив, що я використовував ClientIDMode="Static"як на батьківській, так і на спливаючій сторінці з однаковим ідентифікатором управління. Видалення ClientIDMode="Static"із однієї зі сторінок вирішило проблему.


0

Тут dataTpe є "json", тож дані / 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 + '"'
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.