web-dev-qa-db-fra.com

"Primitive JSON non valide" dans le traitement Ajax

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 s'il vous plaît ce qui ne va pas dans mon code?

Je reçois 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"
}
90
Radhi

Devinez ce que la variable json contient après

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

Si c'est un objet json valide comme {'foo':'foovalue', 'bar':'barvalue'} alors jQuery pourrait ne pas l'envoyer sous forme de données json, mais plutôt le sérialiser à foor=foovalue&bar=barvalue ainsi vous obtenez l'erreur "Invalid JSON primitive: foo"

Essayez plutôt de définir les données en tant que chaîne

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

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

124
jitter

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

98
Andrew

Comme indiqué par la gigue, la fonction $.ajax Sérialise tout objet/tableau utilisé comme paramètre data dans un format codé par URL. Curieusement, le paramètre dataType ne s'applique qu'à 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 coder correctement les données de la demande dans ScriptService. Ensuite, utilisez la fonction $.toJSON Pour coder les arguments que vous souhaitez envoyer au serveur:

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

ça marche quelque chose comme ça

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

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 ne soit définie sur false, auquel cas elle sera envoyée en tant qu'objet au serveur.

  • L'option contentType concerne le serveur dans lequel le format a été envoyé par le client.

  • L'option dataType concerne le serveur. Elle indique le type de client de données attendu par le 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 (objet) pour que le serveur puisse désérialiser JSON de chaîne.

11
T Gupta

Je suppose que @ jitter avait raison, mais sa solution ne m'a pas aidé.

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, il devrait ressembler à ceci:

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

Je faisais face 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 chaîne, j'ai utilisé le caractère de séquence d'échappement (\ ') pour la désigner comme valeur de chaîne.

2
Sohel Pathan

Si vous formatez JSON manuellement, 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"
}
1
Daniel de Zwaan

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
Ioannis Suarez