"Primitiva JSON no válida" en el procesamiento Ajax


101

Recibo un error en una llamada ajax de jQuery.

Aquí está mi función 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");
        }
    });
}

y este es mi 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";
}

¿Alguien puede decirme qué está mal en mi código?

Recibo este error:

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

Lo que no entiendo es. El javascript trata sobre AddAlbumToMyProfile, mientras que el WebMethod se llama DeleteRecord. ¿Está seguro de que nos muestra los códigos correctos?
jitter

¿Alguna posibilidad de que también pueda capturar cómo se ve el POST (usando firebug o lo que sea) y agregarlo a la pregunta? No estoy seguro de si es la forma en que está codificando los datos antes de enviarlos, pero también puede intentar serializarlos usando esto ( json.org/json2.js ).
R0MANARMY

Respuestas:


135

Solo una adivina qué contiene la variable jsondespués

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

Si es un objeto json válido, {'foo':'foovalue', 'bar':'barvalue'}entonces jQuery podría no enviarlo como datos json, sino serializarlo para foor=foovalue&bar=barvalueobtener el error"Invalid JSON primitive: foo"

En su lugar, intente configurar los datos como una cadena

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

De esta manera, jQuery debería dejar los datos en paz y enviar la cadena como está al servidor, lo que debería permitir que ASP.NET analice el lado del servidor json.


5
gracias por la aclaración, agregue un comentario más, siempre puede hacer como JSON.stringify ({foo: 'foovalue', bar: 'barvalue'}) para una vida más fácil
Elaine

Una década tarde en la fiesta, pero sigue siendo relevante: no es JSON válido. Las cadenas (incluidos los nombres de propiedad) en JSON deben usar comillas dobles , por lo que debería ser así {"foo": "foovalue", "bar": "barvalue"}. El uso de comillas simples es un error de sintaxis.
Mike 'Pomax' Kamermans

108

Utilizando

data : JSON.stringify(obj)

en la situación anterior habría funcionado, creo.

Nota: Debe agregar la biblioteca json2.js, todos los navegadores no admiten ese objeto JSON (IE7-) Diferencia entre json.js y json2.js


3
¡Gracias! Cuando se utilizan clases JS simples, esto funciona. Cambié data: { JSON.stringify(obj) }a data: JSON.stringify(obj)(Mi clase javascript / JSON para serializar es del estilo var myObj = { title: "x", subclass = someVar, ... } )
lko

1
Tenga en cuenta que esta es la solución siempre que necesite enviar JSON ( lo que podría hacer con los servicios web asp.net ). En otros casos, podría ser más fácil simplemente eliminarcontentType y dejar que jQuery pase los datos codificados por formulario.
GSerg

19

Como indica jitter, la $.ajaxfunción serializa cualquier objeto / matriz utilizado como dataparámetro en un formato codificado en URL. Curiosamente, el dataTypeparámetro solo se aplica a la respuesta del servidor, y no a los datos de la solicitud.

Después de encontrar el mismo problema, descargué y usé el complemento jquery-json para codificar correctamente los datos de la solicitud en ScriptService. Luego, usó la $.toJSONfunción para codificar los argumentos deseados para enviarlos al servidor:

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

2
gracias por señalar que el dataparámetro es ignorado por la llamada.
Noel Abrahams

3
Esto funciona, pero cambiar data: { JSON.stringify(obj) }a data: JSON.stringify(obj)funcionó para mí si su clase de javascript es del estilo var myObj = { title: "x", subclass = someVar, ... } gracias al punto sobre la codificación de datos.
lko

19

está funcionando algo como esto

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

3
Esta respuesta apareció en la cola de revisión de baja calidad, presumiblemente porque no proporciona ninguna explicación del código. Si este código responde a la pregunta, considere agregar algún texto que explique el código en su respuesta. De esta manera, es mucho más probable que obtenga más votos a favor y ayude al interrogador a aprender algo nuevo.
lmo

Quiero pasar dos parámetros: una matriz de objeto complejo y un número entero. Lo hago: datos: {elementos: JSON.stringify (myarray), myId: value}.
A.Dara

gracias por publicar la respuesta. esto funcionó para mí.
ZMAX

13

Jquery Ajax enviará los datos de forma predeterminada como parámetros de cadena de consulta como:

RecordId=456&UserId=123

a menos que la processDataopción esté establecida en false, en cuyo caso se enviará como objeto al servidor.

  • contentType La opción es para el servidor en qué formato el cliente ha enviado los datos.

  • dataType La opción es para el servidor que indica qué tipo de datos del cliente espera recibir del servidor.

No especifique contentType para que el servidor los analice como parámetros de cadena de consulta, no como json.

O

Utilice contentType como 'aplicación / json; charset = utf-8 'y use JSON.stringify (objeto) para que el servidor pueda deserializar json desde la cadena.


5

Supongo que @jitter tenía razón en su suposición, pero su solución no funcionó para mí.

Esto es lo que funcionó:

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

No lo he intentado, pero creo que si el parámetro es una cadena, debería ser así:

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

9
Si tuviera que escribir un código como ese (cadena concat) para crear objetos JSON, me mataría (en sentido figurado). Tiene que haber una mejor manera.
PandaWood

3

Estaba enfrentando el mismo problema, lo que obtuve con una buena solución es la siguiente:

Prueba esto...

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

Tenga en cuenta que aquí para el parámetro de tipo de cadena he utilizado (\ ') carácter de secuencia de escape para denotarlo como valor de cadena.


datos: "{Notas: \" "+ $ ('# txtNotes'). val () +" \ "}
bestinamir

1

Si formatea manualmente JSON, hay un validador muy útil aquí: jsonlint.com

Utilice comillas dobles en lugar de comillas simples:

Inválido:

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

Válido:

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

0

En el servidor, para serializar / deserializar json en objetos personalizados:

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

Tuve el mismo problema. Estaba llamando a la página principal "Guardar" desde la ventana emergente Cerrar. Descubrí que estaba usando ClientIDMode="Static"tanto en la página principal como en la página emergente con la misma identificación de control. Eliminar ClientIDMode="Static"de una de las páginas resolvió el problema.


0

Aquí dataTpe es "json" entonces, data / reqParam debe estar en forma de cadena mientras se llama a la API, tanto como objeto como desee, pero por fin dentro de los datos de $ .ajax, cadena el objeto.

             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

estas respuestas me hicieron rebotar entre el parámetro no válido y el parámetro faltante.

esto funcionó para mí, simplemente envuelva las variables de cadena entre comillas ...

data: { RecordId: RecordId,
            UserId: UId,
            UserProfileId: UserProfileId,
            ItemType: '"' +  ItemType + '"',
            FileName: '"' +  XmlName + '"'
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.