111 votes

"Invalid JSON primitive" dans le traitement Ajax

Je reçois une erreur dans un appel ajax depuis 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("une erreur s'est produite lors de la suppression");
        }
    });
}

et ceci est 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";
}

Est-ce que quelqu'un peut me dire ce qui ne va pas dans mon code ?

Je reçois cette erreur :

{
    "Message":"Primitive JSON invalide : 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"
}

0 votes

Ce que je ne comprends pas, c'est que le JavaScript concerne AddAlbumToMyProfile alors que le WebMethod est appelé DeleteRecord. Êtes-vous sûr de nous avoir montré les bons morceaux de code ?

0 votes

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 suis pas certain si c'est la façon dont vous encodez les données avant de les envoyer, mais vous pourriez également essayer de les sérialiser en utilisant ceci (json.org/json2.js).

145voto

jitter Points 35805

Juste une supposition que contient la variable json après

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

S'il s'agit d'un objet json valide comme {"foo":"valeurfoo", "bar":"valeurbar"} alors jQuery pourrait ne pas l'envoyer en tant que données json mais plutôt le sérialiser en foo=valeurfoo&bar=valeurbar ce qui vous donne l'erreur "Primitive JSON non valide : foo"

Essayez plutôt de définir les données comme une chaîne

$.ajax({
    ...
    data: '{"foo":"valeurfoo", "bar":"valeurbar"}', //notez les guillemets supplémentaires
    ...
})

De cette façon, jQuery devrait laisser les données telles quelles et envoyer la chaîne telle quelle au serveur, ce qui devrait permettre à ASP.NET de parser le json côté serveur.

8 votes

Merci pour la clarification, ajoutez un autre commentaire, vous pouvez toujours faire comme JSON.stringify({foo:'valeurfoo', bar:'valeurbar'}) pour faciliter la vie

1 votes

Une décennie en retard pour la fête, mais toujours pertinente: cela n'est pas un JSON valide. Les chaînes (y compris les noms de propriété) dans le JSON doivent utiliser des guillemets doubles, donc cela serait {"foo": "valeurfoo", "bar": "valeurbar"}. Utiliser des apostrophes est une erreur de syntaxe.

116voto

Andrew Points 940

Utiliser

data : JSON.stringify(obj)

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

Note : Vous devriez ajouter la bibliothèque json2.js car tous les navigateurs ne prennent pas en charge cet objet JSON (IE7-) Différence entre json.js et json2.js

3 votes

Merci! Lors de l'utilisation de simples classes JS, ceci fonctionne. J'ai changé data: { JSON.stringify(obj) } en data: JSON.stringify(obj) (Ma classe JavaScript/JSON pour la sérialisation est du style var myObj = { title: "x", subclass = someVar, ... } )

1 votes

Notez que c'est la solution fournie si vous avez réellement besoin d'envoyer du JSON (ce qui pourrait être le cas avec les services web asp.net). Dans d'autres cas, il pourrait être plus facile de simplement supprimer le contentType et laisser jQuery passer les données encodées en formulaire.

19voto

leepowers Points 16420

Comme l'a noté jitter, la fonction $.ajax sérialise tout objet/tableau utilisé comme paramètre data dans un format encodé en url. Curieusement, le paramètre dataType s'applique uniquement à la réponse du serveur - et non à des données quelconques dans 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 requête vers le ScriptService. Ensuite, j'ai utilisé la fonction $.toJSON pour encoder les arguments désirés à envoyer vers le serveur:

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

2 votes

Merci d'avoir signalé que le paramètre data est ignoré par l'appel.

3 votes

Cela fonctionne, mais le changement de data: { JSON.stringify(obj) } en data: JSON.stringify(obj) a 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.

14voto

T Gupta Points 209

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

RecordId=456&UserId=123

à moins que l'option processData soit définie sur false, auquel cas elle sera envoyée sous forme d'objet au serveur.

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

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

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

OU

Utilisez contentType comme 'application/json; charset=utf-8' et utilisez JSON.stringify(objet) afin que le serveur puisse désérialiser le json à partir de la chaîne.

6voto

Diego Points 5577

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

Voici ce qui a fonctionné:

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

Je n'ai pas essayé mais je pense que si le paramètre est une chaîne de caractères, cela devrait être comme ceci:

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

9 votes

Si je devais écrire du code comme ça (concaténation de chaînes) pour créer des objets JSON, je me tuerais (au sens figuré). Il doit y avoir un meilleur moyen.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X