"Primitiva JSON non valida" nell'elaborazione Ajax


101

Ricevo un errore in una chiamata ajax da jQuery.

Ecco la mia funzione 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");
        }
    });
}

e questo è il mio 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";
}

Qualcuno può dirmi cosa c'è di sbagliato nel mio codice?

Ricevo questo errore:

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

Quello che non capisco è. Il javascript riguarda AddAlbumToMyProfile mentre il WebMethod si chiama DeleteRecord. Sei sicuro di mostrarci i pezzi di codice giusti?
jitter

C'è qualche possibilità che tu possa anche catturare l'aspetto del POST (usando firebug o altro) e aggiungerlo alla domanda? Non sono sicuro che sia il modo in cui codifichi i dati prima di inviarli, ma potresti anche provare a serializzarli usando questo ( json.org/json2.js ).
R0MANARMY

Risposte:


136

Solo una supposizione che cosa fa la variabile jsoncontiene dopo

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

Se si tratta di un oggetto json valido come {'foo':'foovalue', 'bar':'barvalue'}jQuery potrebbe non inviarlo come dati json ma invece serializzarlo in foor=foovalue&bar=barvaluemodo da ottenere l'errore"Invalid JSON primitive: foo"

Prova invece a impostare i dati come stringa

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

In questo modo jQuery dovrebbe lasciare i dati da soli e inviare la stringa così com'è al server che dovrebbe consentire ad ASP.NET di analizzare il lato server json.


5
grazie per il chiarimento, aggiungi un altro commento, puoi sempre fare come JSON.stringify ({foo: 'foovalue', bar: 'barvalue'}) per una vita più facile
Elaine

Un decennio di ritardo per la festa, ma ancora rilevante: non è un JSON valido. Le stringhe (inclusi i nomi delle proprietà) in JSON devono utilizzare virgolette doppie , quindi dovrebbe essere {"foo": "foovalue", "bar": "barvalue"}. L'utilizzo di virgolette singole è un errore di sintassi.
Mike 'Pomax' Kamermans il

108

Utilizzando

data : JSON.stringify(obj)

nella situazione di cui sopra avrebbe funzionato credo.

Nota: dovresti aggiungere la libreria json2.js, tutti i browser non supportano quell'oggetto JSON (IE7-) Differenza tra json.js e json2.js


3
Grazie! Quando si usano semplici classi JS questo funziona. Sono passato data: { JSON.stringify(obj) }a data: JSON.stringify(obj)(La mia classe javascript / JSON da serializzare è dello stile var myObj = { title: "x", subclass = someVar, ... } )
lko

1
Nota che questa è la soluzione fornita che devi effettivamente inviare JSON ( cosa che potresti fare con i servizi web asp.net ). In altri casi potrebbe essere più semplice rimuoverecontentType e lasciare che jQuery passi i dati codificati nel modulo.
GSerg

19

Come notato dal jitter, la $.ajaxfunzione serializza qualsiasi oggetto / array utilizzato come dataparametro in un formato con codifica URL. Stranamente, ildataType parametro si applica solo alla risposta del server e non a tutti i dati nella richiesta.

Dopo aver riscontrato lo stesso problema, ho scaricato e utilizzato il plug-in jquery-json per codificare correttamente i dati della richiesta in ScriptService. Quindi, utilizza la $.toJSONfunzione per codificare gli argomenti desiderati da inviare al server:

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

2
grazie per aver sottolineato che il dataparametro viene ignorato dalla chiamata.
Noel Abrahams

3
Funziona, ma il passaggio data: { JSON.stringify(obj) }a ha data: JSON.stringify(obj)funzionato per me se la tua classe javascript è di stile var myObj = { title: "x", subclass = someVar, ... } grazie al punto sulla codifica dei dati.
lko

19

funziona qualcosa di simile

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

3
Questa risposta è stata trovata nella coda di revisione di bassa qualità, presumibilmente perché non fornisci alcuna spiegazione del codice. Se questo codice risponde alla domanda, prendi in considerazione l'aggiunta di un testo che spieghi il codice nella tua risposta. In questo modo, hai molte più probabilità di ottenere più voti positivi e aiutare l'interlocutore a imparare qualcosa di nuovo.
lmo

Voglio passare due parametri: un array di oggetti complessi e un numero intero. Lo faccio: data: {items: JSON.stringify (myarray), myId: value}.
A.Dara

13

Jquery Ajax invierà per impostazione predefinita i dati come parametri della stringa di query come:

RecordId=456&UserId=123

a meno che l' processDataopzione non sia impostata su false, nel qual caso verrà inviata come oggetto al server.

  • contentType è per il server quello in cui il formato client ha inviato i dati.

  • dataType l'opzione è per il server che indica il tipo di dati che il client si aspetta dal server.

Non specificare contentType in modo che il server li analizzi come parametri della stringa di query e non come json.

O

Usa contentType come 'application / json; charset = utf-8 'e usa JSON.stringify (object) in modo che il server sia in grado di deserializzare json dalla stringa.


5

Immagino che @jitter avesse ragione nella sua ipotesi, ma la sua soluzione non ha funzionato per me.

Ecco cosa ha funzionato:

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

Non ho provato ma penso che se il parametro è una stringa dovrebbe essere così:

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

9
Se dovessi scrivere codice come quello (string concat) per creare oggetti JSON, mi ucciderei (in senso figurato). Deve esserci un modo migliore.
PandaWood

3

Stavo affrontando lo stesso problema, quello che ho fornito con una buona soluzione è il seguente:

Prova questo...

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

Si prega di notare qui per il parametro di tipo stringa che ho usato il carattere di sequenza di escape (\ ') per denotarlo come valore di stringa.


dati: "{Note: \" "+ $ ('# txtNotes'). val () +" \ "}
bestinamir

1

Se si formatta manualmente JSON, qui c'è un validatore molto utile: jsonlint.com

Usa virgolette doppie invece di virgolette singole:

Non valido:

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

Valido:

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

0

Sul server, per serializzare / deserializzare json in oggetti personalizzati:

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

Ho avuto lo stesso problema. Stavo chiamando la pagina genitore "Salva" dalla finestra popup Chiudi. Ho scoperto che stavo usando ClientIDMode="Static"sia la pagina principale che quella popup con lo stesso ID di controllo. La rimozione ClientIDMode="Static"da una delle pagine ha risolto il problema.


0

Qui dataTpe è "json", quindi data / reqParam deve essere sotto forma di stringa durante la chiamata all'API, tanto quanto l'oggetto che vuoi ma alla fine all'interno dei dati di $ .ajax stringi l'oggetto.

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

O,

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

queste risposte mi hanno appena fatto rimbalzare avanti e indietro tra il parametro non valido e il parametro mancante.

questo ha funzionato per me, basta racchiudere le variabili stringa tra virgolette ...

data: { RecordId: RecordId,
            UserId: UId,
            UserProfileId: UserProfileId,
            ItemType: '"' +  ItemType + '"',
            FileName: '"' +  XmlName + '"'
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.