HTML
<form id="MyForm"> <input type="text" name="Text" /> <br/> <input type="checkbox" value="true" name="CheckBox" /> <br/> <input type="radio" value="rdo1" name="Radio" /> <input type="radio" value="rdo2" name="Radio" /> <br/> <select name="SelectOption"> <option value="1">Option 1</option> <option value="2">Option 2</option> </select> <br/> <input type="button" id="btnSubmit" value="Submit" /> </form>I listed 4 widely used HTML controls on this form. Note my controls have names defined and not IDs. Names are unique to controls or, in case of radio buttons, to the group of controls. Also, note that my checkbox has a value attribute defined, which is “true”.
JavaScript
$('#btnSubmit').click(function() { var formVals = $('#MyForm').serializeArray(); var jsonObj = {}; for (i in formVals) jsonObj[formVals[i].name] = formVals[i].value; var submitVals = $.toJSON({ "MyFormData": jsonObj }); $.ajax({ type: "POST", url: "WebService.asmx/SubmitFormData", data: submitVals, contentType: "application/json; charset=utf-8", dataType: "json", success: function(result) { alert($.toJSON(result)); } });
First is the obvious: when btnSubmit is clicked, I’m taking all the values from MyForm and sending them to the web service.
I use jQuery’s serializeArray() function to automatically grab all the values from MyForm. The structure of formVals is as follows:
[{"name":"n1","value":"v1"},{"name":"n2","value":"v2"},{"name":"n3","value":"v3"}]
Where names are the name attributes of the form elements and values are their values. Remember the CheckBox with value of “true”? If a checkbox is checked, serializeArray() would pick it up from the form. If a checkbox is not checked, serializeArray() would not pick it up from the form at all. As for radio buttons, serializeArray() picks up their group name and the value of the one button that is selected. With this being said, the result of serializeArray is not in a JSON format. To create a proper JSON format, I have a simple for loop which turns formVals into a JSON object, jsonObj. (I picked this loop from comments on serializeArray() page) Now, jsonObj is in the following format:
{"n1":"v1","n2":"v2","n3":"v3"}
This is the correct JSON format and this is almost what I want to pass to the service. At last this line:
var submitVals = $.toJSON({ "MyFormData": jsonObj });
MyFormData is the parameter that my WebMethod is expecting in the web service. So, I create a more complex JSON structure:
{"MyFormData" : {"v1","n2":"v2","n3":"v3"}}
At last, this final data structure must be passed in as a JSON string and not as a JSON object. There are several ways to go about “stringifying” a JSON object. Here are some available choices:
I used jquery.json just because I already have jQuery included in the project. I will not explain why I have the $.ajax setup this way. You may find all kinds of info on it all over the wwweb.
ASMX Web Service
Imports System.Web.Services Imports System.Web.Services.Protocols Imports System.ComponentModel Imports System.Web.Script.Services ' To allow this Web Service to be called from script, using ASP.NET AJAX, ' uncomment the following line. <System.Web.Script.Services.ScriptService()> _ <System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _ <System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _ <ToolboxItem(False)> _ Public Class WebService Inherits System.Web.Services.WebService Public Class FormData Public Text As String Public CheckBox As Boolean Public Radio As String Public SelectOption As Integer End Class <WebMethod(EnableSession:=True)> _ <ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _ Public Function SubmitFormData(ByVal MyFormData As FormData) As String Dim result As String result = MyFormData.Text & " " result &= MyFormData.CheckBox & " " result &= MyFormData.Radio & " " result &= MyFormData.SelectOption Return result End Function End Class
Yes, this is, in fact, VB! Converting this to C# should not be a problem. The most important piece here is the FormData class. It must be declared as public. All of its properties must exactly match the names of the form HTML controls. Function SubmitFormData takes FormData MyFormData as a parameter. This is why I had to stick the original JSON object into another array. As long as HTML control names are matching the class’s properties names, the serialization happens automatically. The only thing that I need to be careful about is the value types. The CheckBox property of the class is declared as Boolean. When the checkbox is checked, the client submits its value as “true”, which then serializes into Boolean value of true. If the checkbox is not checked, no value is submitted for it and so the Boolean variable gets a value of false. The rest is just a dummy data processing. The service returns all the values back as one string and the JavaScript alerts {"d":"… values string…"}
You may find out more about the 'd' here: the 'd'
Conclusion
Why this method? Obviously, depending on a problem, we must come up with a certain solution. This approach may not be suiting certain problems. However, here are two things that I absolutely love about it.
- It requires no extra work at all to handle serialization.
- At some point in the future, my users will want another text box on that form. So, the form will be updated, the FormData class will be updated, possibly the DataBase will be updated. But! My JavaScript will remain untouched.