How Do I Send A Complex Json Object From An Html Form Using Synchronous Page Post?
Solution 1:
While Mythz suggestion of posting JSV values would work, it can sometimes be cumbersome to build and maintain complex JSV in JavaScript. For example, you may have to deal with escaping user inputted data, and syntax issues can be hard to track
This solution looks complex but it's really not, and is highly re-usable and only requires that you can send encoded JSON, which from jQuery is very easy.
Full Demo Source Code Here
Process - How it works:
- Your jQuery creates the DTO using the form data on submit
- The DTO is encoded as JSON, simply using
JSON.stringify(data)
- The JSON is sent in a hidden form as the value of
Data
field - A server DTO attribute filter deserializes the JSON value of
Data
field into your DTO - Your service see the DTO populated as normal.
Filter Attribute:
My solution sends the DTO object encoded as JSON in a form post to the service. Then a simple filter intercepts the request and populates the DTO from the JSON payload.
publicclassGetFromJsonVariableAttribute : Attribute, IHasRequestFilter
{
string _variableName;
publicGetFromJsonVariableAttribute(string variableName = "Data")
{
_variableName = variableName;
}
publicvoidRequestFilter(IRequest req, IResponse res, object requestDto)
{
// Convert the JSON payload to DTO formatvar payload = req.GetParam(_variableName);
if(payload != null)
requestDto = JsonSerializer.DeserializeFromString(payload, requestDto.GetType());
}
publicint Priority { get { returnint.MinValue; } }
IHasRequestFilter IHasRequestFilter.Copy() { returnthis; }
}
Usage
Then to use you simply add the attribute to your DTO. Data
is the name of the form variable that will hold the JSON payload. You can choose any name you want here.
[GetFromJsonVariable("Data")]
[Route("/Customers","POST")]
publicclassCreateCustomerRequest : IReturnVoid
{
public Customer Customer { get; set; }
public Name Name { get; set; }
}
Client Side (jQuery):
- Get your form values
- Build the required DTO structure as a JavaScript object
- Convert that DTO to a JSON string
- Set your hidden form value to the DTO string & submit
$("#CreateCustomer").on("submit", function(){
// Get the form values into simple key value arrayvar values = {};
$.each($(this).serializeArray(), function(){ values[this.name] = this.value; });
// Prepare the DTOvar data = {
Customer: {
Company: values["Company"],
RegionCode: values["RegionCode"]
},
Name: {
First: values["First"],
Last: values["Last"]
}
};
// Convert it to JSON
$('#PayloadForm [name="Data"]').val(JSON.stringify(data));
$('#PayloadForm').submit();
returnfalse;
});
With the HTML create the form your user will interact with, with no action, but is linked to the jQuery submit event code; And a hidden form that will actually perform the synchronous POST. Note the attribute Data
matches that of the attribute the payload should be received on
<formid="CreateCustomer"><inputtype="text"name="Company"value="TheCompany" /><br/><inputtype="text"name="RegionCode"value="AU_NSW" /><br/><inputtype="text"name="First"value="Jimi" /><br/><inputtype="text"name="Last"value="Hendrix" /><br/><inputtype="submit"value="Submit" /></form><!-- This form is hidden --><formaction="/Customers"method="POST"id="PayloadForm"><inputtype="hidden"name="Data"value=""></form>
Solution 2:
ServiceStack can POST complex types using the JSV Format, e.g:
<input name="Customer" value="{Company:TheCompany,RegionCode:AU_NSW}" />
<input name="Name" value="{First:Jimi,Last:Hendrix}" />
Otherwise you can send complex types using JSON, e.g. with jQuery's $.ajax:
$.ajax({
type: 'POST',
contentType: 'application/json; charset=utf-8',
url: "http://host/myservice",
dataType: 'json',
data: JSON.stringify({Customer:{Company:'x',RegionCode:'x'}}),
success: function(response){ ... }
});
Although for maximum interoperability you should strive to keep your Request DTO's flat, e.g:
<formid="theForm"...><inputname="Company"value="TheCompany" /><inputname="RegionCode"value="AU_NSW" /><inputname="FirstName"value="Jimi" /><inputname="LastName"value="Hendrix" /></form>
Which you can then POST as-is which the browser will do using the x-www-form-urlencoded
Content-Type, or even ajaxify using ServiceStack's ss-utils.js bindForm method, e.g:
$("#theForm").bindForm();
Solution 3:
Attach a submit handler to the form which places the JSON as the value of a pre-created hidden input field within the form.
$(form_to_submit).on('submit', function() {
$(form_to_submit).find(hidden_input).val(json_value);
});
To submit a form using jQuery you use:
$(form_to_submit).submit();
Solution 4:
I ran into the same thing here where I was using NodeJS and an Express Server. I wanted to post a complex JSON object that I had built as the user made selections client side. I then attached an onClick event to a button that called my SubmitForm function.
Your data can be any JSON object. Just be sure to parse it server side.
functionParam(name, value){
var hiddenField = document.createElement('input');
hiddenField.setAttribute('type', 'hidden');
hiddenField.setAttribute('name', name);
hiddenField.setAttribute('value', value);
return hiddenField;
}
functionSubmitForm(data){
var form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', '/route');
form.appendChild(Param('data', JSON.stringify(data)));
document.body.appendChild(form);
form.submit();
}
Additionally, this is pure javascript. No hidden HTML or jQuery here for those of you who prefer to remove the overhead.
Post a Comment for "How Do I Send A Complex Json Object From An Html Form Using Synchronous Page Post?"