1

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.

5
  • jQuery forms does not have a contentType option (see malsup.com/jquery/form/#options-object) so I doubt you can use it to send JSON data via AJAX. Commented Jan 2, 2013 at 4:18
  • Yes, I saw there is no contentTyep option. However, at the botton of the page it says "Note that the Options Object can also be used to pass values to jQuery's $.ajax method. If you are familiar with the options supported by $.ajax you may use them in the Options Object passed to ajaxForm and ajaxSubmit.". So, contenType should work as per this definition. If it's not working it must be either an issue or that I have to do something else to get it working? Commented Jan 2, 2013 at 16:57
  • I guess I missed that, and from your discussion with charlietfl it seems it is treating your string as an array, sending each index and its respective character as key/value pairs. This is the data unescaped 0={&1="&2=u&3=s&4=e&5=r&6=N&7=a&8=m&9=e&10="&11=:&12="&13=a&14=b&15=c&‌​16="&17=,&18="&19=p&20=a&21=s&22=s&23=w&24=o&25=r&26=d&27="&28=:&29="‌​&30=1&31=2&32=3&33="&34=} Commented Jan 2, 2013 at 17:09
  • Thanks, Musa. Can yo please see the Edit 4 I've just added? Commented Jan 2, 2013 at 18:32
  • Can't you just change the code in jquery.form.js to be like in jQuery.ajax Commented Jan 2, 2013 at 18:48

3 Answers 3

2

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

Sign up to request clarification or add additional context in comments.

10 Comments

Thanks. Had already tried that, but have just tried again and still getting the same error...
is error in server code? doesn't look like a browser or jQuery error. Not sure which JSON is the problem, data sent or response
I don't think the error is in the server side because my WebMethod doesn't get hit so I belive the error is during the request only.
inspect the request in a browser console to see status, what is sent and returned etc. Will help isolate which end is the problem
Can you please guide me with that? I've trying to use fiddler, but don't really know how to use it. Is there any other easier way?
|
0

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.

2 Comments

.serialize() returns a query string not a JSON string.
This doesn't work either. And Musa is correct, .serialize() returns a query string.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.