I am submiting form using $('#myForm').submit my rest service accepts content-type of application/x-www-form-urlencoded, but when using submit() I can't see the request in XHR tab in browser developer tools and the form parameters doesn't reach the Rest service, I could use AJAX post and specify content-type, but Rest service produces octet stream in other words the response contains a downloadable file csv/pdf, what could be the solution to submit form correctly?
Why you are not using $.ajax() with type:"post" ?. you can set header easily there
// Request with custom header
$.ajax({
url: 'foo/bar',
type: 'post',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: {}, // object of your data
success: function(response){
alert(response)
}
});
IF your api response is in octet stream or downloadable file then you have to create virtual form and post it through jQuery, Because through AJAX it is not possible to download file.. When file is download content of current page will remain same event form is posted.
function autoGenerateAndSubmitForm(method, url, post_data) {
var element = document.getElementById("virtual_form");
if(element != null )
{
element.parentNode.removeChild(element);
}
var form = document.createElement("form");
form.setAttribute("id", "virtual_form");
form.setAttribute("style", "display:none;");
//form.setAttribute("target", "_blank"); // remove comment if you want to open it in new tab
form.method = method;
form.action = url;
for(i in post_data)
{
var element=document.createElement("input");
element.value=post_data[i];
element.name=i;
form.appendChild(element);
}
document.body.appendChild(form);
form.submit();
form.parentNode.removeChild(form);
}
Call below function with your poper arguments
autoGenerateAndSubmitForm('POST','your_url',{your_post_data_object:"Here"});
After reading your modified Question usually if the parameters are empty at the API it could be caused by the following.
Form is Not Properly Serialized
The Content Type Specified Is Not what your API is Accepting
When you are using ajax make sure your form does not specify any action and methods else there might be a problem.
The model the API is expecting doesn't match what the form has submitted
When using Ajax change your button type to "button" instead of "submit".
Related
let me explain you my situation for a pentesting I am doing:
There exist an app on www.victim.com that accept POST request with customized headers (e.g: "Authorization" : "xxxxx"). I have a domain www.attacker.com that when visited (by the "victim") needs to execute a code that forge the aforementioned POST request, send it to www.victim.com and reload the webpage. As you can see, the behavior is what is expected from a classic "form":
Code on attacker site (www.attacker.com):
<form action="www.victim.com" method="POST" id="myForm">
... some hidden input ...
<input type="submit" name="HackIt" value="Hack me!" />
</form>
The main disadvantage of the previous method is that I can not customize the header of the request before the form is submitted. That's why I tried to use AJAX and JQuery to modify header before the form is submitted:
<script>
$(document).ready(function(){
$("#myForm").submit(function(event){
event.preventDefault(); //prevent default action
var post_url = $(this).attr("action");
var request_method = $(this).attr("method");
var form_data = $(this).serialize();
$.ajax({
url : post_url,
headers: {
"Authorization": "xxxxxx",
"Accept-Language":"x_machine"
},
type: request_method,
data : form_data
});
});
});
</script>
This code almost works! However the response is interpreted by www.attacker.com and not by www.victim.com as expected. Classic form previously mentioned reloads the webpage and allows the response to be interpreted by www.victim.com.
Finally, the question is: What is the "magic recipe" to modify the headers of the request and submit it as the classic form to allow the response be interpreted by www.victim.com?
Thanks in advance!
This is doubtless a newbie question but I cannot find one that's similar. I want to pass a model to an action through a JS function. I have the Ajax script:
var modelDataJSON = '#Html.Raw(Json.Encode(Model))';
$.ajax({
url: '#Url.Action("Action1", "Home")',
type: 'POST',
data: modelDataJSON,
dataType: 'json'
});
And I have for the action:
public ActionResult Action1(MyModel modelDataJSON)
{
return Content(modelDataJSON.ToString());
}
It's not doing anything. What have I missed? Again, sorry for the newbie question but I have already been stuck for too long on it.
Perhaps there's a misunderstanding. What I'm asking is how you redirect to the Action1 URL using a JS script. If it runs then it will display the content because it's a content action.
Don't use Ajax if you want to load a new page.
To make a POST request, you need to submit a form.
The best way to approach this is to use a plain, regular HTML form and not involve JS at all.
If you really want to involve JS then you can generate a form.
var f = document.createElement("form");
f.action = myURL;
f.method = "POST";
// append inputs to the form to pass the data in modelDataJSON here
document.body.appendChild(f);
f.submit();
Note that you can't send a JSON payload this way (but despite the variable name being modelDataJSON, your Ajax would have been sending standard form encoded data anyway).
I am trying to export my web page data and download it as excel file. but the download does not start even the response return succeed.
$.ajax({
type: "POST",
url: _url,
contentType: 'multipart/form-data;boundary=SzB12x',
data: json,
});
The responseText something like this:
PK�J;Fxl/theme/theme1.xml�YOo�6����,[r��n;v��i����#-�kJH:�oC{0X7�2��mZ���d��u#�(٦b:M���������{|��^�0t#��*"w$�!0I�[�՚n�i��'����iH� g�,��|�J�!���hRh�h��?r&�L ���߶S��v#���#���"���}��Жt%�hR�t"������+��������u{ނ��0K���oy�9OTWywkAͯ�
���F�� 6*�����[���U���
I think its the file but I cant download it!!
Any help please?
Thanks!
I faced the same issue and successfully solved it. My use-case is this.
Post JSON data to server and receive an excel file.
That excel file is created on the fly and returned as a response to client.
Code:
$("#my-button").on("click", function() {
// Data to post
data = {
ids: [1, 2, 3, 4, 5]
};
// Use XMLHttpRequest instead of Jquery $ajax
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var a;
if (xhttp.readyState === 4 && xhttp.status === 200) {
// Trick for making downloadable link
a = document.createElement('a');
a.href = window.URL.createObjectURL(xhttp.response);
// Give filename you wish to download
a.download = "test-file.xls";
a.style.display = 'none';
document.body.appendChild(a);
a.click();
}
};
// Post data to URL which handles post request
xhttp.open("POST", excelDownloadUrl);
xhttp.setRequestHeader("Content-Type", "application/json");
// You should set responseType as blob for binary responses
xhttp.responseType = 'blob';
xhttp.send(JSON.stringify(data));
});
The above snippet is just doing following
Posting an array as JSON to the server using XMLHttpRequest
After fetching content as a blob(binary), we are creating a downloadable URL and attaching it to invisible "a" link then clicking it.
Here we need to carefully set few things at the server side. I set few headers in Python Django HttpResponse. You need to set them accordingly if you are use other programming languages.
# In python django code
response = HttpResponse(file_content, content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
Since I download xls(excel) here, I adjusted contentType to above one. You need to set it according to your file type.
Try to use a hidden form to submit the request.
When a user submits an HTML form, all the data entered into the form by the user is sent as either a GET or POST request to the URL specified in the “ACTION” attribute of FORM.
<FORM action="http://www.labnol.org/sendmail.php" method="post">
...form contents...
</FORM>
In the above example, an HTTP POST request is issued to the sendmail.php script on form submission. You can add target=”_blank” to the FORM tag to process the request in a new window.
However, if you would like to submit a FORM on the page in the background without directing the browser to another page (document.location.href changes on form submit), you have two options:
Option #1. You can either create an invisible IFRAME inside your HTML page and set that as a target for the Original FORM. This will submit the form but without reloading the parent window.
<FORM action="http://example.com/script.php"
method="POST" target="hidden-form">
...form contents...
</FORM>
<IFRAME style="display:none" name="hidden-form"></IFRAME>
Option #2: There’s another method that allows you create custom payloads before submitting the form. Unlike the IFRAME based form submission, the following code makes a standard form submit request and thus your browser location will change and the current page will get added to the browser history. Credit: Rakesh Pai.
submitFORM('http://example.com/script.php', 'POST',
{'name':'digital+inspiration', 'age':'100', 'sex','M'});
function submitFORM(path, params, method) {
method = method || "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
//Move the submit function to another variable
//so that it doesn't get overwritten.
form._submit_function_ = form.submit;
for(var key in params) {
if(params.hasOwnProperty(key)) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form._submit_function_();
}
In this link you can find the way to create hidden form and submit it.
enjoy!!
The approach here is directly lifted from https://gist.github.com/DavidMah/3533415.
This approach uses <form> and appends the data with a key. This approach works if the server is already expecting the data as an attribute of the request body, as opposed to being the request body itself. If the data to be uploaded is an object, you could iterate over that object's keys. If the data to be uploaded is an array, either modify the server route or [add idea here].
In browser
// Takes a URL, param name, and data string
// Sends to the server... The server can respond with binary data to download
jQuery.download = function(url, key, data) {
// Build a form
var form = $('<form></form>').attr('action', url).attr('method', 'post');
// Add the one key/value
form.append($("<input></input>").attr('type', 'hidden').attr('name', key).attr('value', data));
//send request
form.appendTo('body').submit().remove();
};
On server
# A Tidbit of sinatra code to respond
# Assume 'url' is a set variable
# Assume 'key' is the key of the value used in the javascript
post url do
data = params[:key]
puts request.body.read
headers['Content-Type'] = "application/octet-stream"
body(data)
end
Example
$.download('/path/resource/', 'data', JSON.stringify(data))
If you just want to download a file, you don't need to use ajax to do it. Actually, you cannot download file using ajax.
You can still do it by making a hyperlink Export request to a server page that responses content-type is application/vnd.ms-excel and content-disposition is attachment.
You can achieve this using an iFrame as well. A sample function:
// append the data to URL
var requestData = {
param1 : "value1",
param2 : "value2",
}
// call the function
downloadFile(<your_URL>, requestData);
function downloadFile(requestURL, data) {
// "transData" is just a user defined variable to encapsulate "downloadIFrame". It can be named anything as required.
var downloadIFrame = window.transData.downloadIFrame = window.transData.downloadIFrame || $("#downloadFileiFrame");
downloadIFrame.attr("src", requestURL + $.param(requestData));
}
// define the iFrame in your HTML and hide it.
<iframe id="downloadFileiFrame" style="display:none;"></iframe>"
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: yoururlpath,
success: function (response) {
var file = fileName+".xlsx";
window.location = "someFilePath?file=" + file;
}
});
Here's the thing: I have an array which I must send to another page... not using an AJAX request. I'm trying to redirect my user to this new page, or maybe to open a popup with the new page, but this new page must receive the array data on a POST request.
How do I do this in javascript? I have no problem JSON encoding my array before sending it, I just don't know how to redirect my user to a new page with the data "attached", in javascript.
I'm using ExtJS4, so if there's anything on Ext.util, I have no problem using it.
Thanks.
You can do this (using javascript)
make a new FORM
set the action as the new page
set the method as POST
add a hidden field
set the value of the field to this Value you want to send
Pragmatically submit the form
You can Ajax POST to the target page's url:
Ext.Ajax.request({
url:'/target/url/', async:false, method:'POST',
jsonData: {
jsonArray: yourJsonArray
}
success: function() {
console.log('posted successfully');
}
});
async:false loses the asynchronous functionality; simply remove it if you don't need your POST to be synchronous.
I have two datatables that I am merging together using Javascript and jQuery. I want to POST this data to a Rails controller action, but the results of the action will need to be displayed in another view, and I am a little tired of figuring out how to do a redirect to another action from an AJAX POST (It just refuses to display).
So now my question is, how can I change this code to actually post and do a redirect to another action?
My original code is:
submithash = {}
submithash['standard_id'] = $("#app_standard_id").val()
submithash['apps'] = apps
hash = { type: "POST", url: "create_all", data: submithash }
$.ajax(hash)
This worked GREAT in that it submitted correctly to my Rails controller action, but of course there does not appear to be a clean way to redirect from an Ajax submission and actually physically display an actual page to a user.
I tried:
$form = $("<form>").attr("method", "post").attr("action", "create_all")
$("<input type='hidden'>").attr("name", "standard_id").attr("value", $("#app_standard_id").val()).appendTo($form)
$("<input type='hidden'>").attr("name", "apps").attr("value", apps).appendTo($form)
$form.submit
but of course that refuses to work. It doesn't even do anything, which is a little odd.
If I understand you question correctly you wish to redirect your page to another url when your ajax call to "create_all" completes.
So you can use the success callback function like this:
hash = { type: "POST",
url: "create_all",
data: submithash,
success: function(data){
//Here you can write your redirection code
//this function will be called when ajax completes successfully
window.location = "url"//redirect url;
//or you can also start another ajax
}
};
$.ajax(hash);
Also check out the documentation for jquery.ajax() here
I ended up using this jQuery plugin:
(function($) {
$.extend({
getGo: function(url, params) {
document.location = url + '?' + $.param(params);
},
postGo: function(url, params) {
var $form = $("<form>")
.attr("method", "post")
.attr("action", url);
$.each(params, function(name, value) {
$("<input type='hidden'>")
.attr("name", name)
.attr("value", value)
.appendTo($form);
});
$form.appendTo("body");
$form.submit();
}
});
})(jQuery);
It builds a form on the fly with whatever you pass it, then appends it to the document. Then it does a regular POST (or GET, depending on what you call).