„Nieprawidłowy element podstawowy JSON” w przetwarzaniu Ajax

101

Otrzymuję błąd w wywołaniu Ajax z jQuery.

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

a to jest moje 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";
}

Czy ktoś może mi powiedzieć, co jest nie tak w moim kodzie?

Otrzymuję ten błąd:

{
    "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
źródło
To, czego nie rozumiem, to. JavaScript dotyczy AddAlbumToMyProfile, podczas gdy WebMethod nazywa się DeleteRecord. Czy na pewno pokazujesz nam właściwe fragmenty kodu?
jitter
Jest jakaś szansa, że ​​możesz również uchwycić, jak wygląda POST (używając firebuga lub czegokolwiek) i dodać go do pytania? Nie jestem pewien, czy to sposób, w jaki kodujesz dane przed ich wysłaniem, ale możesz też spróbować serializować je za pomocą tego ( json.org/json2.js ).
R0MANARMY,

Odpowiedzi:

136

Zgadnij, co zawiera zmienna jsonpo

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

Jeśli jest to prawidłowy obiekt json, taki jak {'foo':'foovalue', 'bar':'barvalue'}jQuery, może nie wysłać go jako danych json, ale zamiast tego serializować go, aby foor=foovalue&bar=barvalueuzyskać błąd"Invalid JSON primitive: foo"

Spróbuj zamiast tego ustawić dane jako ciąg

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

W ten sposób jQuery powinno pozostawić dane w spokoju i wysłać ciąg bez zmian do serwera, co powinno pozwolić ASP.NET na przeanalizowanie strony serwera json.

drganie
źródło
5
dzięki za wyjaśnienie, dodaj jeszcze jeden komentarz, zawsze możesz zrobić jak JSON.stringify ({foo: 'foovalue', bar: 'barvalue'}) dla łatwiejszego życia
Elaine
Dziesięć lat spóźniony na imprezę, ale nadal aktualny: to nie jest prawidłowy JSON. Ciągi znaków (w tym nazwy właściwości) w JSON muszą używać podwójnych cudzysłowów , więc musiałoby być {"foo": "foovalue", "bar": "barvalue"}. Używanie apostrofów jest błędem składniowym.
Mike 'Pomax' Kamermans
108

Za pomocą

data : JSON.stringify(obj)

wierzę, że w powyższej sytuacji zadziałałoby.

Uwaga: należy dodać bibliotekę json2.js, wszystkie przeglądarki nie obsługują tego obiektu JSON (IE7-). Różnica między json.js i json2.js

Andrzej
źródło
3
Dzięki! Działa to przy użyciu prostych klas JS. Zmieniłem data: { JSON.stringify(obj) }na data: JSON.stringify(obj)(Moja klasa javascript / JSON do serializacji jest w stylu var myObj = { title: "x", subclass = someVar, ... } )
lko
1
Zauważ, że jest to rozwiązanie, pod warunkiem, że faktycznie musisz wysłać JSON ( co możesz zrobić z usługami sieciowymi asp.net ). W innych przypadkach może być łatwiej po prostu usunąć plikcontentType i pozwolić jQuery przekazać dane zakodowane w formularzu.
GSerg
19

Jak zauważono przez jitter, $.ajaxfunkcja serializuje dowolny obiekt / tablicę używaną jako dataparametr do formatu zakodowanego w postaci adresu URL. Co dziwne, plikdataType parametr dotyczy tylko odpowiedzi z serwera - a nie żadnych danych w żądaniu.

Po napotkaniu tego samego problemu pobrałem i użyłem pobrałem wtyczki jquery-json do poprawnego zakodowania danych żądania do usługi ScriptService. Następnie użyliśmy $.toJSONfunkcji do zakodowania żądanych argumentów do wysłania na serwer:

$.ajax({
    type: "POST",
    url: "EditUserProfile.aspx/DeleteRecord",
    data: $.toJSON(obj),
    contentType: "application/json; charset=utf-8",
    dataType: "json"
    ....
});
leepowers
źródło
2
dzięki za wskazanie, że dataparametr jest ignorowany przez wywołanie.
Noel Abrahams,
3
To działa, ale zmiana data: { JSON.stringify(obj) }na data: JSON.stringify(obj)zadziałała dla mnie, jeśli twoja klasa javascript jest w stylu var myObj = { title: "x", subclass = someVar, ... } dzięki punktowi o kodowaniu danych.
lko,
19

działa coś takiego

data: JSON.stringify({'id':x}),
Jessica Saenz
źródło
3
Ta odpowiedź pojawiła się w kolejce recenzji niskiej jakości, prawdopodobnie dlatego, że nie podajesz żadnego wyjaśnienia kodu. Jeśli ten kod odpowiada na pytanie, rozważ dodanie tekstu wyjaśniającego kod w odpowiedzi. W ten sposób znacznie bardziej prawdopodobne jest, że zdobędziesz więcej głosów za - i pomożesz pytającemu nauczyć się czegoś nowego.
lmo,
Chcę przekazać dwa parametry: tablicę złożonego obiektu i liczbę całkowitą. Robię to: data: {items: JSON.stringify (myarray), myId: value}.
A.Dara
13

Jquery Ajax domyślnie wyśle ​​dane jako parametry ciągu zapytania w postaci:

RecordId=456&UserId=123

chyba że processDataopcja jest ustawiona na false, w takim przypadku zostanie wysłana jako obiekt do serwera.

  • contentType opcja dotyczy serwera, w którym klient wysłał dane w formacie.

  • dataType opcja jest przeznaczona dla serwera, który informuje, jakiego typu dane klient oczekuje z powrotem z serwera.

Nie określaj contentType, aby serwer przeanalizował je jako parametry ciągu zapytania, a nie jako json.

LUB

Użyj contentType jako „application / json; charset = utf-8 'i użyj JSON.stringify (obiekt), aby serwer mógł deserializować json z łańcucha.

T Gupta
źródło
5

Przypuszczam, że @jitter miał rację, ale jego rozwiązanie nie działało dla mnie.

Oto, co zadziałało:

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

Nie próbowałem, ale myślę, że jeśli parametr jest ciągiem, powinien wyglądać tak:

$.ajax({
    ...
    data: "{ intFoo: " + intFoo + ", strBar: '" + strBar + "' }",
    ...
});
Diego
źródło
9
Gdybym musiał napisać taki kod (string concat) do tworzenia obiektów JSON, zabiłbym się (mówiąc w przenośni). Musi być lepszy sposób.
PandaWood
3

Miałem do czynienia z tym samym problemem, co otrzymałem z dobrym rozwiązaniem, jak poniżej:

Spróbuj tego...

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

Proszę zauważyć, że w przypadku parametru typu łańcuchowego użyłem (\ ') znaku sekwencji ucieczki do oznaczenia go jako wartość ciągu.

Sohel Pathan
źródło
data: "{Uwagi: \" "+ $ ('# txtNotes'). val () +" \ "}
bestinamir
1

W przypadku ręcznego formatowania JSON jest tutaj bardzo przydatny walidator: jsonlint.com

Użyj podwójnych cudzysłowów zamiast pojedynczych cudzysłowów:

Nieważny:

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

Ważny:

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

Na serwerze, aby serializować / deserializować json do obiektów niestandardowych:

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
źródło
0

Miałem ten sam problem. Dzwoniłem do strony nadrzędnej „Zapisz” z wyskakującego okienka Zamknij. Odkryłem, że używam ClientIDMode="Static"zarówno strony nadrzędnej, jak i wyskakującej z tym samym identyfikatorem kontroli. Usunięcie ClientIDMode="Static"z jednej ze stron rozwiązało problem.

Mintu Goyal
źródło
0

Tutaj dataTpe to "json", więc data / reqParam musi być w postaci łańcucha podczas wywoływania API, tyle że ile chcesz, ale w końcu wewnątrz danych $ .ajax stringify obiektu.

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

LUB,

       $.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
źródło
-2

te odpowiedzi sprawiły, że odbijałem się od nieprawidłowego parametru i brakującego parametru.

to zadziałało dla mnie, po prostu zawiń zmienne łańcuchowe w cudzysłowy ...

data: { RecordId: RecordId,
            UserId: UId,
            UserProfileId: UserProfileId,
            ItemType: '"' +  ItemType + '"',
            FileName: '"' +  XmlName + '"'
    }
vernmic
źródło