Cesar Vinas
Cesar Vinas

Reputation: 417

Invalid JSON primitive with jquery, jquery form plugin and ASP.Net WebMethod

I'm having a problem with sending JSON data via jquery to a WebMethod in my ASPX page. The jquery code is:

<script type="text/javascript">
    $(document).ready(function () {
        $("#frmLogin").validate({
            errorClass: "errorBox",
            onfocusout: false,
            rules: { 
                txtUsername: "required",
                txtPassword: "required"
            },
            messages: { 
                txtUsername: "Enter username.",
                txtPassword: "Enter password." 
            },
            submitHandler: function (form) {
                $(this).ajaxSubmit({
                    type: "POST",
                    url: "Default.aspx/Login",
                    data: '{userName: \abc\',password:\'123\'}',
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (data, textStatus, jqXHR) {
                        if (data.d) {
                            alert("OK");
                        }
                        else {
                            alert("NO");
                        }
                    },
                    error: function (jqXHR, textStatus, errorThrown) {
                        alert(jqXHR.responseText);
                    },
                    complete: function (jqXHR, textStatus) {
                        alert("SUCCESS");
                    }
                });
            }
        });
    });
</script>

The error I keep getting is "Invalid JSON primitive". I've been searching a lot and the problem seems to be in the way the data is formatted. When I replace:

data: '{userName: \abc\',password:\'123\'}',

with:

data: {},

then everything works. I've been trying with a lot of different variations (as seen in a lot of forums and blogs) such as:

data: "{userName: '" + 'abc' + "', password: '" + '123' + "'}",

data: "{userName:'abc', password:'123'}",

data: '{userName:"abc", password:"123"}',

data: '{"userName":"abc","password":"123"}',

data: '{"userName": "abc","password":"123"}',

but nothing has worked so far.

The WebMethod I'm calling is:

[WebMethod, ScriptMethod]
public static bool Login(string userName, string password)
{
    return SecurityManager.Instance.Login(userName: userName, password: password);
}

Also, I'm using the jquery.form.js library (http://www.malsup.com/jquery/form/#getting-started). If use a separate $.ajax() as below then, it works so I don't know if there is something special I have to use when using the jquery.form.js.

$("#frmLogin").submit(function (event) {
    //stop form from submitting normally
    event.preventDefault();

    //Get form values
    var strUsername = $("#txtUsername").val(),
    strPassword = $("#txtPassword").val();

    //Call the login function
    $.ajax({
        type: "POST",
        url: "Default.aspx/Login",
        data: "{userName: '" + strUsername + "', password: '" + strPassword + "'}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (data, textStatus, jqXHR) {
            if (data.d) {
                alert("OK");
            }
            else {
                alert("NO");
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            alert(errorThrown);
        },
    });
});

EDIT 1: The complete error message I get is:

{"Message":"Invalid JSON primitive: %7B\u00261=%22\u00262=u\u00263=s\u00264=e\u00265=r\u00266=N\u00267=a\u00268=m\u00269=e\u002610=%22\u002611=%3A\u002612=%22\u002613=a\u002614=b\u002615=c\u002616=%22\u002617=%2C\u002618=%22\u002619=p\u002620=a\u002621=s\u002622=s\u002623=w\u002624=o\u002625=r\u002626=d\u002627=%22\u002628=%3A\u002629=%22\u002630=1\u002631=2\u002632=3\u002633=%22\u002634=%7D.","StackTrace":" at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n at System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer)\r\n at System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext context)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.ArgumentException"}

EDIT 2: Using Firebug I've seen that the JSON data I'm passing is being URLEnconded. This is what Firebug shows is in the request:

0=%7B&1=%22&2=u&3=s&4=e&5=r&6=N&7=a&8=m&9=e&10=%22&11=%3A&12=%22&13=a&14=b&15=c&‌​16=%22&17=%2C&18=%22&19=p&20=a&21=s&22=s&23=w&24=o&25=r&26=d&27=%22&28=%3A&29=%22‌​&30=1&31=2&32=3&33=%22&34=%7D

EDIT 3: I've being reviewing more and it definitely seems the error is with the form plugin. If I set the data as:

data: { userName: 'abc', password: '123' },

the firebug shows: "userName=abc&password=123". So it seems that even though I'm setting the type parameter to POST, the parameters are transformed into a querystring. And if I do this:

data: $.toJSON({ userName: 'abc', password: '123' }),

then the data gets URLEncoded. How do I do to make the form plugin to send the data as JSON object?

EDIT 4: I've been debuging the jquery.form.js library and found that it's always URLEnconding the data assuming that it's always sent as querystring. In lines from 115 to 120 there is this:

var elements = [];
var qx, a = this.formToArray(options.semantic, elements);
if (options.data) {
    options.extraData = options.data;
    qx = $.param(options.data, traditional);
}

The resulting value of qx is: "0=%7B&1=%22&2=u&3=s&4=e&5=r&6=N&7=a&8=m&9=e&10=%22&11=%3A&12=%22&13=v&14=a&15=l&16=u&17=e&18=1&19=%22&20=%2C&21=%22&22=p&23=a&24=s&25=s&26=w&27=o&28=r&29=d&30=%22&31=%3A&32=%22&33=v&34=a&35=l&36=u&37=e&38=2&39=%22&40=%7D".Then, in lines from 135 to 145 qx is transforment into q and q is assigned to options.data (replacing the JSON object I send as parameters):

var q = $.param(a, traditional);
if (qx) {
    q = (q ? (q + '&' + qx) : qx);
}
if (options.type.toUpperCase() == 'GET') {
    options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
    options.data = null;  // data is null for 'get'
}
else {
    options.data = q; // data is the query string for 'post'
}

If I don't let the library to replace what it is in options.data then everything works fine. Any ideas? Should I just fix this or should I use a different method to achieve what I want?

Edit 5: In the jquery-1.8.3.js library, lines from 7870 to 7872 I've found this:

if ( s.data && s.processData && typeof s.data !== "string" ) {
    s.data = jQuery.param( s.data, s.traditional );
}

this is inside the ajax(method). As you see, the library only encodes the data (via the jQuery.param() method) only if the condition is true. Otherwise, it leaves as it came. However, the jquery.form.js library always calls the jQuery.param() method, as you can see below (and indicated in my Edit 4):

if (options.data) {
    options.extraData = options.data;
    qx = $.param(options.data, traditional);
}

Any ideas of what to do? Does anyone know how to contact the developer of the jquery form plugin? I've tried via Twitter, but no luck.

It's being very frustrating. Any help is appreciated.

Thanks.

Upvotes: 1

Views: 2954

Answers (3)

Cesar Vinas
Cesar Vinas

Reputation: 417

Ok. I think I'll have to answer myself. This is not exactly the solution I was expecting, but I guess until I can get more information from other people or I'm able to contact the developer, this could help others who are facing the same issue. Well, after reviewing the code of the jquery form plugin I found that the library is always URLEncoding the data while the ajax() method in the jquery library is not. So, I've fixed the jquery form as below. I'm not an expert so what I've done may not be the best, but it'll get me going until I figure out a better and permanent solution:

  1. I've replaced the following code in lines from 117 to 120:

    I changed this:

    if (options.data) {
        options.extraData = options.data;
        qx = $.param(options.data, traditional);
    }
    

    to this:

    if (options.data && options.processData && typeof options.data !== "string") {
        options.extraData = options.data;
        qx = $.param(options.data, traditional);
    }
    
  2. I've added an else to the following if in lines from 136 to 138

    I changed this:

    if (qx) {
        q = ( q ? (q + '&' + qx) : qx );
    }
    

    to this:

    if (qx) {
        q = ( q ? (q + '&' + qx) : qx );
    }
    else {
        q = options.data;
    }
    

Thanks.

Upvotes: 0

Bhushan Firake
Bhushan Firake

Reputation: 9448

You should add your field values to the object as below and then pass that object to a function which will be called on your required event.

//make object that will have values from form
var dataToSend = {
                    fieldname: $("FIELDCLASS OR ID").val();
                  };

  function tocall(){
       $.ajax({
                 url: urlForSaving,
                 data: JSON.stringify(dataToSend),
                 cache: false,
                 type: 'POST',
                 dataType: 'json',
                 contentType: "application/json;charset=utf-8",
                 success: function (data, status) {
             },
                 error: function (xhr, ajaxOptions, thrownError) { alert('error') }
             });
                   };

Or you can also serialize the form with serialize() method, google it.

Upvotes: 0

charlietfl
charlietfl

Reputation: 171679

JSON needs to be double quoted. The data being sent is not

data: '{"userName": "abc","password":"123"}',

REFERENCE: http://json.org/

Site looks primitive, but the site initiator developed JSON spec and the methods used in modern browsers that parse JSON

Upvotes: 2

Related Questions