"Primitive JSON non valide" dans le traitement Ajax


101

Je reçois une erreur dans un appel ajax de jQuery.

Voici ma fonction 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");
        }
    });
}

et voici mon 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";
}

Quelqu'un peut-il me dire ce qui ne va pas dans mon code?

J'obtiens cette erreur:

{
    "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"
}

Ce que je ne comprends pas, c'est. Le javascript concerne AddAlbumToMyProfile tandis que le WebMethod s'appelle DeleteRecord. Êtes-vous sûr de nous montrer les bons morceaux de code?
jitter

Y a-t-il une chance que vous puissiez également capturer à quoi ressemble le POST (en utilisant Firebug ou autre) et l'ajouter à la question? Je ne sais pas si c'est la façon dont vous encodez les données avant de les envoyer, mais vous pouvez également essayer de les sérialiser en utilisant ceci ( json.org/json2.js ).
R0MANARMY

Réponses:


136

Juste une idée de ce que contient la variable jsonaprès

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

S'il s'agit d'un objet json valide comme {'foo':'foovalue', 'bar':'barvalue'}jQuery, il se peut que jQuery ne l'envoie pas en tant que données json mais le sérialise à la place pour foor=foovalue&bar=barvalueobtenir l'erreur"Invalid JSON primitive: foo"

Essayez plutôt de définir les données sous forme de chaîne

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

De cette façon, jQuery doit laisser les données seules et envoyer la chaîne telle quelle au serveur, ce qui doit permettre à ASP.NET d'analyser le côté serveur json.


5
merci pour la clarification, ajoutez un autre commentaire, vous pouvez toujours faire comme JSON.stringify ({foo: 'foovalue', bar: 'barvalue'}) pour une vie plus facile
Elaine

Une décennie de retard à la fête, mais toujours d'actualité: ce n'est pas du JSON valide. Les chaînes (y compris les noms de propriété) dans JSON doivent utiliser des guillemets doubles , donc cela devrait l'être {"foo": "foovalue", "bar": "barvalue"}. L'utilisation de guillemets simples est une erreur de syntaxe.
Mike 'Pomax' Kamermans

108

En utilisant

data : JSON.stringify(obj)

dans la situation ci-dessus aurait fonctionné, je crois.

Remarque: vous devez ajouter la bibliothèque json2.js. Tous les navigateurs ne prennent pas en charge cet objet JSON (IE7-) Différence entre json.js et json2.js


3
Merci! Lorsque vous utilisez des classes JS simples, cela fonctionne. J'ai changé data: { JSON.stringify(obj) }pour data: JSON.stringify(obj)(Ma classe javascript / JSON à sérialiser est du style var myObj = { title: "x", subclass = someVar, ... } )
lko

1
Notez qu'il s'agit de la solution à condition que vous ayez réellement besoin d'envoyer du JSON ( ce que vous pourriez faire avec les services Web asp.net ). Dans d'autres cas, il peut être plus facile de simplement supprimer lecontentType et de laisser jQuery transmettre les données codées par formulaire.
GSerg

19

Comme indiqué par la gigue, la $.ajaxfonction sérialise tout objet / tableau utilisé comme dataparamètre dans un format encodé en URL. Curieusement, le dataTypeparamètre s'applique uniquement à la réponse du serveur - et non aux données de la requête.

Après avoir rencontré le même problème, j'ai téléchargé et utilisé le plugin jquery-json pour encoder correctement les données de la demande dans ScriptService. Ensuite, utilisé la $.toJSONfonction pour encoder les arguments souhaités à envoyer au serveur:

$.ajax({
    type: "POST",
    url: "EditUserProfile.aspx/DeleteRecord",
    data: $.toJSON(obj),
    contentType: "application/json; charset=utf-8",
    dataType: "json"
    ....
});

2
merci de souligner que le dataparamètre est ignoré par l'appel.
Noel Abrahams

3
Cela fonctionne, mais changer data: { JSON.stringify(obj) }en a data: JSON.stringify(obj)fonctionné pour moi si votre classe javascript est du style var myObj = { title: "x", subclass = someVar, ... } grâce au point sur l'encodage des données.
lko le

19

ça marche quelque chose comme ça

data: JSON.stringify({'id':x}),

3
Cette réponse est apparue dans la file d'attente d'examen de faible qualité, probablement parce que vous ne fournissez aucune explication du code. Si ce code répond à la question, pensez à ajouter du texte expliquant le code dans votre réponse. De cette façon, vous êtes beaucoup plus susceptible d'obtenir plus de votes positifs et d'aider le questionneur à apprendre quelque chose de nouveau.
lmo

Je veux passer deux paramètres: un tableau d'objets complexes et un entier. Je le fais: data: {items: JSON.stringify (myarray), myId: value}.
A.Dara

13

Jquery Ajax enverra par défaut les données sous forme de paramètres de chaîne de requête comme:

RecordId=456&UserId=123

sauf si l' processDataoption est définie sur false, auquel cas elle sera envoyée comme objet au serveur.

  • contentType L'option est pour le serveur dans quel format le client a envoyé les données.

  • dataType L'option est pour le serveur qui indique quel type de données le client attend en retour du serveur.

Ne spécifiez pas contentType pour que le serveur les analyse en tant que paramètres de chaîne de requête et non en tant que json.

OU

Utilisez contentType comme 'application / json; charset = utf-8 'et utilisez JSON.stringify (object) pour que le serveur puisse désérialiser json de string.


5

Je suppose que @jitter avait raison dans sa supposition, mais sa solution n'a pas fonctionné pour moi.

Voici ce que cela a fonctionné:

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

Je n'ai pas essayé mais je pense que si le paramètre est une chaîne, cela devrait ressembler à ceci:

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

9
Si je devais écrire du code comme ça (string concat) pour créer des objets JSON, je me tuerais (au sens figuré). Il doit y avoir une meilleure façon.
PandaWood

3

J'étais confronté au même problème, ce que je suis venu avec une bonne solution est comme ci-dessous:

Essaye ça...

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

Veuillez noter ici que pour le paramètre de type de chaîne, j'ai utilisé le caractère de séquence d'échappement (\ ') pour le désigner comme valeur de chaîne.


data: "{Notes: \" "+ $ ('# txtNotes'). val () +" \ "}
bestinamir

1

Si vous formatez manuellement JSON, il existe un validateur très pratique ici: jsonlint.com

Utilisez des guillemets doubles au lieu de guillemets simples:

Invalide:

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

Valide:

{
    "project": "a2ab6ef4-1a8c-40cd-b561-2112b6baffd6",
    "franchise": "18e899f6-dd71-41b7-8c45-5dc0919679ef"
}

0

Sur le serveur, pour sérialiser / désérialiser json en objets personnalisés:

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

J'ai eu le même problème. J'appelais la page parent "Enregistrer" à partir de la fenêtre contextuelle Fermer. J'ai trouvé que j'utilisais ClientIDMode="Static"à la fois sur la page parent et la page contextuelle avec le même ID de contrôle. La suppression ClientIDMode="Static"de l'une des pages a résolu le problème.


0

Ici, dataTpe est "json" donc, data / reqParam doit être sous la forme d'une chaîne lors de l'appel de l'API, autant d'objet que vous le souhaitez, mais enfin dans les données de $ .ajax stringify l'objet.

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

OU,

       $.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

ces réponses m'ont juste fait rebondir entre un paramètre invalide et un paramètre manquant.

cela a fonctionné pour moi, enveloppez simplement les variables de chaîne entre guillemets ...

data: { RecordId: RecordId,
            UserId: UId,
            UserProfileId: UserProfileId,
            ItemType: '"' +  ItemType + '"',
            FileName: '"' +  XmlName + '"'
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.