This question already has answers here:
How should I use servlets and Ajax?
(7 answers)
Closed 6 years ago.
i have a username textbox that when a user input a name it takes that name and send to server and the server check if the username has not been taken by anybody else, if so i need to send back somedata and tell the client that the username has been taken else if it is not i need to turn the textbox border color to green, now i can do sending username value to server but i don't know how to send back and how to receive the sent data using jquery ajax.
here is my code:
client:
$(document).ready(function() {
$('#Registeration_Username_box').on('input', function() {
postUsernameToServer();
});
function postUsernameToServer() {
var formData = {
'username': $('input[name=UserName]').val(),
};
// process the form
$.ajax({
type: 'POST', // define the type of HTTP verb we want to use (POST for our form)
url: '../dusernameavailable', // the url where we want to POST
data: formData, // our data object
dataType: 'json', // what type of data do we expect back from the server
encode: true
}).done(function(data) {
console.log(data);
});
}
});
servlet:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
String str = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
System.out.println(str);
}
Add success and error to your ajax
function postUsernameToServer() {
var formData = {
'username': $('input[name=UserName]').val(),
};
// process the form
$.ajax({
type: 'POST', // define the type of HTTP verb we want to use (POST for our form)
url: '../dusernameavailable', // the url where we want to POST
data: formData, // our data object
dataType: 'json', // what type of data do we expect back from the server
encode: true,
success: function(data) {
//TODO make the box green or whatever your requirement is
},
error: function() {
//TODO username already taken
}
});
}
});
In servlet send appropriate response.
You will need to send a response code other than 200 for ajax to consider it as an error from the server.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String str = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
System.out.println(str);
//TODO - check if user name exists or not
if(user name already exists){
response.setProperty(response.HTTP_STATUS_CODE, "500");
PrintWriter out = response.getWriter();
out.println("error");
out.close();
}
else{
PrintWriter out = response.getWriter();
out.println("success");
out.close();
}
}
}
Add a success handler to your ajax call.
You can try something like below; where 'green' and 'red' are css classes you defined in your CSS file .
$.ajax({
type: 'POST', // define the type of HTTP verb we want to use (POST for our form)
url: '../dusernameavailable', // the url where we want to POST
data: formData, // our data object
dataType: 'json', // what type of data do we expect back from the server
encode: true,
success: function(response) {
if(response.isUserNameAvailable == true)
$('input[name=UserName]').addClass('green');
else
$('input[name=UserName]').addClass('red');
}
}).done(function(data) {
console.log(data);
});
Related
This question already has answers here:
How should I use servlets and Ajax?
(7 answers)
Closed 1 year ago.
$("#btnDel").on("click",function(){
var idsarray = [];
$("input:checkbox[name=delbox]:checked").each(function() {
idsarray.push($(this).val());
});
console.log(idsarray);
var idsString = idsarray.join();
console.log(idsString);
$.ajax({
url: 'StudentController',
dataType: 'json',
data: {
"idsToBeDeleted" : idsString
},
type: 'DELETE'
});
});
this is the JS code , im catching the ids of the checkboxes and sending them as a comma separated string to the servlet . thing is when i try to catch the variable on the servlet , and print it out , all i get is null .
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//catching values from recieved ajax request
String idlistString = (String) request.getParameter("idsToBeDeleted");
System.out.println(idlistString);
response.sendRedirect(request.getContextPath());
}
servlet code over here , some explanation on how to usually catch the sent data through an ajax request would be appreciated .
Try with a slash before your url and type: 'POST'. Also notice the small changes I have made.
$.ajax({
url: '/StudentController',
type: 'POST',
dataType: 'json',
data: {
operation: 'remove',
idsToBeDeleted: idsString
},
type: 'DELETE'
});
I'm using ajax to send a delete request but I am getting a NULL value. I cannot figure out what I am doing wrong.
Here is my ajax call
(function() {
$('#btnDelete').bind('click', function() {
$.ajax({
url: '/Project',
type: 'DELETE',
cache: false,
dateType: 'json',
data: {
delProjId: $('#projectId').text(),
nbRandom: Math.random().toString()
},
success: function(data) {
if (data.message[0].error) {
toastr.error(data.message[0].message);
} else {
toastr.success(data.message[0].message);
console.log('success');
}
},
error: function(request, status, error) {
toastr.error(error);
}
});
});
Here is my post request
protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("Content-Type", "application/json");
String delProjId = request.getParameter("delProjId");
System.out.println("Parm:" + delProjId);
}
And the server logs
Parm:null
java.lang.NullPointerException
at com.projectRequest.models.Project.doDelete(Project.java:122)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:210)
It currently is set to span element. I tried putting the value in an input field, even adding a JSON.stringify() around the value as I pass it it. I still get the same results, an empty parameter. I see the value on my client and even when I log it prior to executing the ajax call. I'm not sure what is causing the parameter to clear out.
Only POST request have parameters as an entity in the request body. You must send it as part of the URL.
See RFC 2616: "The DELETE method requests that the origin server delete the resource identified by the Request-URI".
You can pass parameters via URI, for example:
http://localhost/?path=/willbedeleted.txt
I wrote a JQuery script to do a user login POST (tried to do what I have done with C# in the additional information section, see below).
After firing a POST with the JQuery code from my html page, I found the following problems:
1 - I debugged into the server side code, and I know that the POST is received by the server (in ValidateClientAuthentication() function, but not in GrantResourceOwnerCredentials() function).
2 - Also, on the server side, I could not find any sign of the username and password, that should have been posted with postdata. Whereas, with the user-side C# code, when I debugged into the server-side C# code, I could see those values in the context variable. I think, this is the whole source of problems.
3 - The JQuery code calls function getFail().
? - I would like to know, what is this JQuery code doing differently than the C# user side code below, and how do I fix it, so they do the same job?
(My guess: is that JSON.stringify and FormURLEncodedContent do something different)
JQuery/Javascript code:
function logIn() {
var postdata = JSON.stringify(
{
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
});
try {
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: postdata,
dataType: "json",
success: getSuccess,
error: getFail
});
} catch (e) {
alert('Error in logIn');
alert(e);
}
function getSuccess(data, textStatus, jqXHR) {
alert('getSuccess in logIn');
alert(data.Response);
};
function getFail(jqXHR, textStatus, errorThrown) {
alert('getFail in logIn');
alert(jqXHR.status); // prints 0
alert(textStatus); // prints error
alert(errorThrown); // prints empty
};
};
Server-side handling POST (C#):
public override async Task ValidateClientAuthentication(
OAuthValidateClientAuthenticationContext context)
{
// after this line, GrantResourceOwnerCredentials should be called, but it is not.
await Task.FromResult(context.Validated());
}
public override async Task GrantResourceOwnerCredentials(
OAuthGrantResourceOwnerCredentialsContext context)
{
var manager = context.OwinContext.GetUserManager<ApplicationUserManager>();
var user = await manager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError(
"invalid_grant", "The user name or password is incorrect.");
context.Rejected();
return;
}
// Add claims associated with this user to the ClaimsIdentity object:
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
foreach (var userClaim in user.Claims)
{
identity.AddClaim(new Claim(userClaim.ClaimType, userClaim.ClaimValue));
}
context.Validated(identity);
}
Additional information: In a C# client-side test application for my C# Owin web server, I have the following code to do the POST (works correctly):
User-side POST (C#):
//...
HttpResponseMessage response;
var pairs = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>( "grant_type", "password"),
new KeyValuePair<string, string>( "username", userName ),
new KeyValuePair<string, string> ( "password", password )
};
var content = new FormUrlEncodedContent(pairs);
using (var client = new HttpClient())
{
var tokenEndpoint = new Uri(new Uri(_hostUri), "Token"); //_hostUri = http://localhost:8080/Token
response = await client.PostAsync(tokenEndpoint, content);
}
//...
Unfortunately, dataType controls what jQuery expects the returned data to be, not what data is. To set the content type of the request data (data), you use contentType: "json" instead. (More in the documentation.)
var postdata = JSON.stringify(
{
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
});
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: postdata,
dataType: "json",
contentType: "json", // <=== Added
success: getSuccess,
error: getFail
});
If you weren't trying to send JSON, but instead wanted to send the usual URI-encoded form data, you wouldn't use JSON.stringify at all and would just give the object to jQuery's ajax directly; jQuery will then create the URI-encoded form.
try {
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/Token",
cache: false,
data: {
"username": document.getElementById("username").value,
"password": document.getElementById("password").value
},
dataType: "json",
success: getSuccess,
error: getFail
});
// ...
To add to T.J.'s answer just a bit, another reason that sending JSON to the /token endpoint didn't work is simply that it does not support JSON.
Even if you set $.ajax's contentType option to application/json, like you would to send JSON data to MVC or Web API, /token won't accept that payload. It only supports form URLencoded pairs (e.g. username=dave&password=hunter2). $.ajax does that encoding for you automatically if you pass an object to its data option, like your postdata variable if it hadn't been JSON stringified.
Also, you must remember to include the grant_type=password parameter along with your request (as your PostAsync() code does). The /token endpoint will respond with an "invalid grant type" error otherwise, even if the username and password are actually correct.
You should use jquery's $.param to urlencode the data when sending the form data . AngularJs' $http method currently does not do this.
Like
var loginData = {
grant_type: 'password',
username: $scope.loginForm.email,
password: $scope.loginForm.password
};
$auth.submitLogin($.param(loginData))
.then(function (resp) {
alert("Login Success"); // handle success response
})
.catch(function (resp) {
alert("Login Failed"); // handle error response
});
Since angularjs 1.4 this is pretty trivial with the $httpParamSerializerJQLike:
.controller('myCtrl', function($http, $httpParamSerializerJQLike) {
$http({
method: 'POST',
url: baseUrl,
data: $httpParamSerializerJQLike({
"user":{
"email":"wahxxx#gmail.com",
"password":"123456"
}
}),
headers:
'Content-Type': 'application/x-www-form-urlencoded'
})
})
I try to download a file. The action is triggered by ajax() POST request. The request sends data in JSON format to the controller. The controller generates the file (bytes) and sends it back.
JavaScript:
function getLicenseFile() {
$.ajax({
type: 'POST',
url: '<%=request.getContextPath()%>/licenses/rest/downloadLicenseFile',
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: ko.mapping.toJSON(licenseModel),
success: function (data) {
console.log("in sucess")
},
error:function (xhr, ajaxOptions, thrownError){
console.log("in error")
}
});
}
Controller:
#RequestMapping(value = "/licenses/rest/downloadLicenseFile", method = RequestMethod.POST)
#ResponseStatus(value=HttpStatus.OK)
#ResponseBody
public void createLicenseFile(#Valid #RequestBody License license, HttpServletResponse response) throws Exception {
logger.debug("Contoller License in: "+ license);
byte[] licensedata = licenseEncodeDefaultService.createLicenseFile(license);
logger.debug("licenseData: " + new String(licensedata));
response.setHeader("Content-Disposition", "attachment; filename=\"" + license.getCustomer() + ".license\"");
response.getOutputStream().write(licensedata);
response.flushBuffer();
}
Problem
The Browser should open a download box, but it does not happen
The response is handled in the error: section of ajax function (but the HTTP Status is OK)
So what do I do wrong or what is the proper way to do this?
Just send a URL of file in response and then "visit" it in your success callback.
function getLicenseFile() {
$.ajax({
type: 'POST',
url: '<%=request.getContextPath()%>/licenses/rest/downloadLicenseFile',
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: ko.mapping.toJSON(licenseModel),
success: function (data) {
window.open(data.fileUrl);
// or window.location.href = data.fileUrl;
},
error:function (xhr, ajaxOptions, thrownError) {
console.log("in error");
}
});
}
data.fileUrl should be set in response by server to say client where to get the file.
So your server will send a response with JSON like
{
"fileUrl": "http://mysite.com/files/0123456789"
}
#will824 As you ask I'll post my own solution.
I used a workaround in controller and save the file temporarily in the files ystem (/tmp). I split up the function in 2 steps. Creating and downloading.
This is not very nice but good enough for me.
Controller (creates a file, will be saved on the server file system):
#RequestMapping(value = "/licenses/rest", method = RequestMethod.PUT)
#ResponseStatus(value=HttpStatus.OK)
#ResponseBody
public String createLicenseFile(#Valid #RequestBody License license) throws Exception {
// create encrypted license file and send the name back to view
String fileName = licenseEncodeDefaultService.createLicenseFile(license);
return fileName;
}
Controller (downloads a file):
#RequestMapping(value = "/licenses/downloadFile/{file}", method = RequestMethod.GET)
public void downloadLicenseFile(#PathVariable("file") String file, HttpServletResponse response) throws Exception {
// create full filename and get input stream
File licenseFile = new File ("/tmp/" + file);
InputStream is = new FileInputStream(licenseFile);
// set file as attached data and copy file data to response output stream
response.setHeader("Content-Disposition", "attachment; filename=\"" + file + ".license\"");
FileCopyUtils.copy(is, response.getOutputStream());
// delete file on server file system
licenseFile.delete();
// close stream and return to view
response.flushBuffer();
}
JavaScript:
function getLicenseFile() {
//console.log(ko.mapping.toJSON(licenseModel));
$.ajax({
type : 'PUT',
url : '${pageContext.request.contextPath}/licenses/rest',
dataType : 'text',
contentType : 'application/json;charset=UTF-8',
data : ko.mapping.toJSON(licenseModel),
success : function(data) {
window.location.href = '${pageContext.request.contextPath}/licenses/downloadFile/'
+ data;
},
error : function(xhr, ajaxOptions, thrownError) {
// error handling
}
});
}
If you want download file without change URL, you can call form.submit() programmatically instead of using AJAX.
JavaScript:
function downloadFileUsingForm(url) {
var form = document.createElement("form");
form.method = "post";
form.action = url;
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
downloadFileUsingForm("/YourController/DownloadFile");
Controller:
[HttpPost]
public ActionResult DownloadFile()
{
string content = "Some Values";
byte[] bytes = System.Text.UTF8Encoding.UTF8.GetBytes(content);
return File(bytes, System.Net.Mime.MediaTypeNames.Application.Octet, "file.txt");
}
As the comments said you can't do it with an ajax call, but you can do it with plain Javascript.
function getLicenseFile() {
var downloadUrl = "${pageContext.request.contextPath}/licenses/rest/downloadLicenseFile";
// (optionally) provide the user with a message that the download is starting
window.location.href = downloadUrl;
}
Note the use of ${pageContext.request.contextPath}, which is preferred over <%=request.getContextPath()%>.
Ajax is not going to help you try with hidden form approach
<form action='../servletname' method='POST' id='formid'>
<input type='hidden' value='' name='name' id='id'/>
<input type='hidden' value=' ' name='name' id='id' />
</form>
pass you json through form field
on click of of your download button submit form
$('#formid').submit();
then in server side
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=filnemae.fileformat");
ServletOutputStream out = res.getOutputStream();
write on ouput stream then close or flush
if you are sending large data through post update postsize in server.xml
As the title states, I'm trying to send data from a Javascript frontend to my C# MVC 5 backend, and it doesn't seem to make it. I've run through it with the debugger in Visual Studio and the data I'm trying to pass always ends up null.
Here is my front end code:
var file = $("#my-file").files[0];
file = file[0];
var formData = new FormData();
var MyData = {
Name: "Form 133",
Attachments: {
Type: "Check"
}
};
formData.append('file', file);
$.ajax({
type: "POST",
url: '/NMISProduct/Index',
contentType: false,
processData: false,
data: { formData: formData, MyData: MyData },
success: function (result) {
console.log(result);
},
error: function (xhr, status, p3, p4) {
var err = "Error " + " " + status + " " + p3 + " " + p4;
if (xhr.responseText && xhr.responseText[0] == "{")
err = JSON.parse(xhr.responseText).Message;
console.log(err);
}
});
Backend code:
[HttpPost]
public async Task<JsonResult> Index(MyData MyData)
{
Debug.WriteLine(Request.Params["MyData"]);
Debug.WriteLine(MyData.Name);
try
{
foreach (string file in Request.Files)
{
var fileContent = Request.Files[file];
if (fileContent != null && fileContent.ContentLength > 0)
{
// get a stream
var stream = fileContent.InputStream;
// and optionally write the file to disk
var fileName = fileContent.FileName;
var path = Path.Combine(Server.MapPath("~/App_Data/"), fileName);
using (var fileStream = System.IO.File.Create(path))
{
stream.CopyTo(fileStream);
}
}
}
}
catch (Exception)
{
return Json("Upload failed");
}
return Json("File uploaded successfully");
}
public class MyData
{
public string Name { get; set; }
public Attachment Attachments { get; set; }
}
public class Attachment
{
public string Type { get; set; }
}
As I stated, on the Backend MyData always ends up being null. What am I doing wrong?
jQuery docs state:
processData (default: true)
Type: Boolean
By default, data passed in to the data option as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded". If you want to send a DOMDocument, or other non-processed data, set this option to false.
The problem is that you are trying to send MyData as an object while setting processData to false. Which will result in the data not being processed before being send. The data property should contain a query string of the form key1=value1&key2=value2, or an object of the form {key1: 'value1', key2: 'value2'}, the latter will be converted into a query string before being send unless you are setting processData to false.
So if you want to send your formData along with the MyData you will need to append the MyData to the formData before sending it like so.
formData.append('Name', 'Form 133');
formData.append('Type', 'Check');
And then in the $ajax call add the FormData to the data property like so.
data: formData,
contentType setting to false you just told him to not sending any data in the header so basically the tag [HttpPost] become useless.
processData setting to false you told him not to process has and object so rendering MyData useless again by setting to true if i remember correctly it mean process anything beside string has a object.
$.ajax({
url: "#Url.Action("Your METHOD", "Your Controller")",
type: "POST",
contentType: "application/json",
data: JSON.stringify({ MyData: MyData}),
success: function(response) {
response ? alert("Process") : alert("Boom");
}
});