views:

162

answers:

2

I have a ASP.NET web service decorated with System.Web.Script.Services.ScriptService() so it can return json formatted data. This much is working for me, but ASP.Net has a requirement that parameters to the web service must be in json in order to get json out.

I'm using jquery to run my ajax calls and there doesn't seem to be an easy way to create a nice javascript object from the form elements. I have looked at serialiseArray in the json2 library but it doesn't encode the field names as property name in the object.

If you have 2 form elements like this

 <input type="text" name="namefirst" id="namefirst" value="John"/>
 <input type="text" name="namelast" id="namelast" value="Doe"/>

calling $("form").serialize() will get you the standard query string

namefirst=John&namelast=Doe

calling JSON.stringify($("form").serializeArray()) will get you the (bulky) json representation

[{"name":"namefirst","value":"John"},{"name":"namelast","value":"Doe"}]

This will work when passing to the web service but its ugly as you have to have code like this to read it in:

Public Class NameValuePair
    Public name As String
    Public value As String
End Class
<WebMethod()> _
Public Function GetQuote(ByVal nvp As NameValuePair()) As String

End Function

You would also have to wrap that json text inside another object nameed nvp to make the web service happy. Then its more work as all you have is an array of NameValuePair when you want an associative array.

I might be kidding myself but i imagined something more elegant when i started this project - more like this

Public Class Person
    Public namefirst As String
    Public namelast As String
End Class

which would require the json to look something like this:

 {"namefirst":"John","namelast":"Doe"}

Is there an easy way to do this? Obviously it is simple for a form with two parameters but when you have a very large form concatenating strings gets ugly. Having nested objects would also complicate things

The cludge I have settled on for the moment is to use the standard name value pair format stuffed inside a json object. This is compact and fast

{"q":"namefirst=John&namelast=Doe"}

then have a web method like this on the server that parses the query string into an associate array.

<WebMethod()> _
Public Function AjaxForm(ByVal q As String) as string
    Dim params As NameValueCollection = HttpUtility.ParseQueryString(q)
    'do stuff
    return "Hello"
End Sub

As far a cludges go this one seems reasonably elegant in terms of amount of code, but my question is: is there a better way? Is there a generally accepted way of passing form data to asp.net web/script services?

+1  A: 

You are just having a formatting crisis.

To properly call this code:

Public Class NameValuePair
    Public name As String
    Public value As String
End Class
<WebMethod()> _
Public Function GetQuote(ByVal nvp As NameValuePair()) As String

End Function

You need to send a json string that looks like this:

'{"nvp": {"name": "john", "value": "foo"}}'

Do not use jQuery to serialize ScriptService arguments. Use the standard json2.js.

Try this: Form

...
 <input type="text" name="name" id="name" value="John"/>
 <input type="text" name="value" id="value" value="Foo"/>
...

Script:

var myNvp = {name: $('#name').val(), value:$('#value').val()};
var data = JSON.stringify({nvp: myNvp});
// data is what you post to the service.

I just wrote this off the top of my head but it looks right to me.

Let me know if you have any other questions.

Sky Sanders
thanks for your answer - I do mention that it would need to be wrapped with a object "nvp", i probably should have put it in to the code block.
Will D
What i am trying to avoid is this line:var myNvp = {name: $('#name').val(), value:$('#value').val()};imagine this with 30 form elements, it gets ugly quickly especially from a maintenance perspective. You have to maintain both the form input controls and the javascript that makes the object, which purely there to aide in the call to the webservice, it adds no value. Adding new input controls is more involved as there is no *direct* link between form and post data, you have to form the javascript object manually, which i think is a bigger cludge than the one i started with
Will D
@Will - use a data plugin. There are several that will read your form into any JSOB shape that you like. The bottom line is, there is a right way and a wrong way to do what you are trying to do. One way works and the other doesn't. The choice is yours. ;-)
Sky Sanders
A: 

I havn't found anything better than what i was already thinking with passing the serialized string as a parameter.

input:

  {"q":"namefirst=John&namelast=Doe"}

webservice:

<WebMethod()> _
Public Function AjaxForm(ByVal q As String) as string
    Dim params As NameValueCollection = HttpUtility.ParseQueryString(q)
    'do stuff
    return "Hello"
End Sub

This seems the cleanest and simplest option

Will D