"Ungültiges JSON-Grundelement" in der Ajax-Verarbeitung

101

Ich erhalte eine Fehlermeldung bei einem Ajax-Aufruf von jQuery.

Hier ist meine jQuery-Funktion:

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

und das ist mein 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";
}

Kann mir bitte jemand sagen, was in meinem Code falsch ist?

Ich erhalte diesen Fehler:

{
    "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"
}
Radhi
quelle
Was ich nicht verstehe ist. Das Javascript handelt von AddAlbumToMyProfile, während die WebMethod DeleteRecord heißt. Sind Sie sicher, dass Sie uns die richtigen Codeteile zeigen?
Jitter
Gibt es eine Chance, dass Sie auch erfassen können, wie der POST aussieht (mit Firebug oder so weiter) und ihn der Frage hinzufügen können? Ich bin mir nicht sicher, ob Sie die Daten vor dem Senden so codieren, aber Sie können auch versuchen, sie mithilfe dieser zu serialisieren ( json.org/json2.js ).
R0MANARMY

Antworten:

135

Nur eine Vermutung, was die Variable danach jsonenthält

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

Wenn es sich um ein gültiges JSON-Objekt handelt, {'foo':'foovalue', 'bar':'barvalue'}sendet jQuery es möglicherweise nicht als JSON-Daten, sondern serialisiert es, foor=foovalue&bar=barvalueum den Fehler zu erhalten"Invalid JSON primitive: foo"

Versuchen Sie stattdessen, die Daten als Zeichenfolge festzulegen

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

Auf diese Weise sollte jQuery die Daten in Ruhe lassen und die Zeichenfolge unverändert an den Server senden, damit ASP.NET die json-Serverseite analysieren kann.

Jitter
quelle
5
danke für die Klarstellung, füge noch einen Kommentar hinzu, du kannst immer JSON.stringify ({foo: 'foovalue', bar: 'barvalue'}) für ein einfacheres Leben
Elaine
Ein Jahrzehnt zu spät zur Party, aber immer noch relevant: Das ist kein gültiger JSON. Zeichenfolgen (einschließlich Eigenschaftsnamen) in JSON müssen doppelte Anführungszeichen verwenden , daher muss dies der Fall sein {"foo": "foovalue", "bar": "barvalue"}. Die Verwendung von einfachen Anführungszeichen ist ein Syntaxfehler.
Mike 'Pomax' Kamermans
108

Verwenden von

data : JSON.stringify(obj)

in der oben genannten Situation hätte es meiner Meinung nach funktioniert.

Hinweis: Sie sollten die Bibliothek json2.js hinzufügen. Alle Browser unterstützen dieses JSON-Objekt nicht (IE7-). Unterschied zwischen json.js und json2.js

Andrew
quelle
3
Vielen Dank! Bei Verwendung einfacher JS-Klassen funktioniert dies. Ich wechselte data: { JSON.stringify(obj) }zu data: JSON.stringify(obj)(Meine zu serialisierende Javascript / JSON-Klasse hat den Stil var myObj = { title: "x", subclass = someVar, ... } )
lko
1
Beachten Sie, dass dies die Lösung ist, sofern Sie tatsächlich JSON senden müssen ( möglicherweise mit asp.net-Webdiensten ). In anderen Fällen ist es möglicherweise einfacher , diecontentType formularcodierten Daten zu entfernen und jQuery weiterzuleiten.
GSerg
19

Wie durch Jitter festgestellt, $.ajaxserialisiert die Funktion jedes Objekt / Array, das als dataParameter verwendet wird, in ein URL-codiertes Format. Seltsamerweise gilt der dataTypeParameter nur für die Antwort vom Server - und nicht für Daten in der Anforderung.

Nachdem ich auf dasselbe Problem gestoßen war, habe ich das jquery-json-Plugin heruntergeladen und verwendet , um die Anforderungsdaten korrekt in den ScriptService zu codieren. Verwenden Sie dann die $.toJSONFunktion, um die gewünschten Argumente zu codieren, die an den Server gesendet werden sollen:

$.ajax({
    type: "POST",
    url: "EditUserProfile.aspx/DeleteRecord",
    data: $.toJSON(obj),
    contentType: "application/json; charset=utf-8",
    dataType: "json"
    ....
});
Leepowers
quelle
2
Vielen Dank für den Hinweis, dass der dataParameter vom Aufruf ignoriert wird.
Noel Abrahams
3
Dies funktioniert, aber data: { JSON.stringify(obj) }es hat data: JSON.stringify(obj)sich für mich geändert, wenn Ihre Javascript-Klasse var myObj = { title: "x", subclass = someVar, ... } dank des Punkts über die Datencodierung den Stil hat .
lko
19

es funktioniert so etwas

data: JSON.stringify({'id':x}),
Jessica Saenz
quelle
3
Diese Antwort wurde in der Überprüfungswarteschlange mit geringer Qualität angezeigt, vermutlich weil Sie keine Erklärung für den Code angeben. Wenn dieser Code die Frage beantwortet, sollten Sie Text hinzufügen, der den Code in Ihrer Antwort erläutert. Auf diese Weise erhalten Sie mit größerer Wahrscheinlichkeit mehr positive Stimmen - und helfen dem Fragesteller, etwas Neues zu lernen.
lmo
Ich möchte zwei Parameter übergeben: ein Array komplexer Objekte und eine Ganzzahl. Ich mache es: data: {items: JSON.stringify (myarray), myId: value}.
A.Dara
Vielen Dank für die Antwort. das hat bei mir funktioniert.
ZMAX
13

Jquery Ajax sendet die Daten standardmäßig als Abfragezeichenfolgenparameter wie folgt:

RecordId=456&UserId=123

es sei denn, die processDataOption ist auf false gesetzt. In diesem Fall wird sie als Objekt an den Server gesendet.

  • contentType Option ist für den Server, in welchem ​​Format der Client die Daten gesendet hat.

  • dataType Die Option gilt für den Server, der angibt, welche Art von Datenclient vom Server zurück erwartet.

Geben Sie contentType nicht an, damit der Server sie als Abfragezeichenfolgenparameter und nicht als json analysiert.

ODER

Verwenden Sie contentType als 'application / json; charset = utf-8 'und verwenden Sie JSON.stringify (Objekt), damit der Server json aus dem String deserialisieren kann.

T Gupta
quelle
5

Ich denke, @jitter hatte Recht mit seiner Vermutung, aber seine Lösung hat bei mir nicht funktioniert.

Folgendes hat funktioniert:

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

Ich habe es nicht versucht, aber ich denke, wenn der Parameter eine Zeichenfolge ist, sollte es so sein:

$.ajax({
    ...
    data: "{ intFoo: " + intFoo + ", strBar: '" + strBar + "' }",
    ...
});
Diego
quelle
9
Wenn ich solchen Code schreiben müsste (string concat), um JSON-Objekte zu erstellen, würde ich mich selbst töten (im übertragenen Sinne). Es muss einen besseren Weg geben.
PandaWood
3

Ich hatte das gleiche Problem. Was ich mit einer guten Lösung gefunden habe, ist wie folgt:

Versuche dies...

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

Bitte beachten Sie hier für den String-Typ-Parameter, dass ich (\ ') Escape-Sequenz-Zeichen verwendet habe, um ihn als String-Wert zu kennzeichnen.

Sohel Pathan
quelle
Daten: "{Notizen:" + $ ('# txtNotes'). val () + ""}
bestinamir
1

Wenn Sie JSON manuell formatieren, gibt es hier einen sehr praktischen Validator: jsonlint.com

Verwenden Sie doppelte Anführungszeichen anstelle von einfachen Anführungszeichen:

Ungültig:

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

Gültig:

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

Auf dem Server können Sie json für benutzerdefinierte Objekte serialisieren / deserialisieren:

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;
}
Ioannis Suarez
quelle
0

Ich hatte das gleiche Problem. Ich habe die übergeordnete Seite "Speichern" aus dem Popup-Fenster "Schließen" aufgerufen. Es wurde festgestellt, dass ich ClientIDMode="Static"sowohl auf der übergeordneten als auch auf der Popup-Seite dieselbe Steuerelement-ID verwendet habe. Das Entfernen ClientIDMode="Static"von einer der Seiten löste das Problem.

Mintu Goyal
quelle
0

Hier ist dataTpe "json", daher muss data / reqParam beim Aufrufen der API die Form einer Zeichenfolge haben, viele so viele Objekte wie Sie möchten, aber schließlich innerhalb der Daten von $ .ajax das Objekt stringifizieren.

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

ODER,

       $.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);
        }
    });
Gaurav Basnet
quelle
-2

Diese Antworten ließen mich nur zwischen ungültigem Parameter und fehlendem Parameter hin und her springen.

das hat bei mir funktioniert, nur String-Variablen in Anführungszeichen setzen ...

data: { RecordId: RecordId,
            UserId: UId,
            UserProfileId: UserProfileId,
            ItemType: '"' +  ItemType + '"',
            FileName: '"' +  XmlName + '"'
    }
vernmic
quelle