Issue with my Ajax & JQuery using Spring MVC in java - javascript

My jQuery AJAX implementation does not work properly, so if i want add, delete, update a product, or retrieve all sites, it simply does not react to my clicks.
Here is my simple web-page that allows me to click but i donot get any result.
When someone wants to submit the form with the specified ID, all form fields are assigned to appropriate variables. After that, a new JSON document is generated based on the form field variables. Then the AJAX call is performed. It is directed to URL which is specified in the action attribute of form tag. The JSON is used as a data which needs to be processed.
You can downlaod my project from here
I get there errors:
localhost:8080/api/sites Failed to load resource: net::ERR_CONNECTION_REFUSED
2localhost:8080/api/sites/ Failed to load resource: net::ERR_CONNECTION_REFUSED
From my Java class:
#RequestMapping(method = RequestMethod.GET, value = "/api/sites")
public List<Site> getAllSites(){
return siteService.getAllSites();
}
#RequestMapping(method = RequestMethod.POST, value = "/api/sites")
public void addSite(#RequestBody Site site){
siteService.addSite(site);
}
A webpage to replicate the problem:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<hr><p> New page </p>
<input name="search" type="text" maxlength="100" id="search"/>
<button onclick="getAllSites()"> Show All </button>
<hr>
<hr>
<p> Id: <input name="search" type="text" maxlength="100" id="id"/></p>
<p> First name: <input name="search" type="text" maxlength="100" id="name"/></p>
<button onclick="addSite()"> Save </button>
<div id="site"></div>
<script>
function addSite()
{ var data = {
id: document.getElementById("id").value,
name: document.getElementById("name").value
}
$.ajax({
url: "http://localhost:8080/api/sites",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
type: "POST",
dataType: "json",
data: JSON.stringify(data)
});
}
function getAllSites()
{
$("#site").html("");
$.getJSON("http://localhost:8080/api/sites/", function(data)
{
for (var i in data) {
$('#site').append("<p>ID: " + data[i].id + "</p>")
$('#site').append("<p>Name: " + data[i].name + "</p>")
}
});
}
</script>
</body>
</html>

Assuming that the ajax implementation is in a file for example: mySites.html and you need to test it directly from browser or from other site try this:
Go to SiteController.class
If you need to test your api outside of your localhost:8080 then add #CrossOrigin annotation to the specific method of SiteController.class, for example in this case I'm enabling CrossOrigin for two specific methods:
Method 1
#CrossOrigin(origins = "*")
#RequestMapping(method = RequestMethod.GET, value = "/api/sites")
public List<Site> getAllSites(){
return siteService.getAllSites();
}
Method 2
#CrossOrigin(origins = "*")
#RequestMapping(method = RequestMethod.POST, value = "/api/sites")
public void addSite(#RequestBody Site site){
siteService.addSite(site);
}
For more information about #CrossOrigin see the following documentation from spring site #CrossOrigin Document
My conclusion of this answer is because the first time that I ran the ajax implementation I got the No 'Access-Control-Allow-Origin' header exception from console developer, wich means that for security reasons the browser block the ajax request when it is outside of the rest api host.
All the rest of the components (backend java classes, spring) worked perfect after I get imported to my development environment.

Related

Asp.net returning whole page

I've been trying to develop a site which has a login system.
As part of that I want to make an AJAX call to the server to handle the login system with the username and password.
When I make the call, it goes through well but i recieve the entire web page in return and I don't know why
Ajax call(JS):
function AJAXfunc(username, password) {
var parameter = JSON.stringify({ "username": username, "password": password })
$.ajax({
type: "POST",
contentType: 'application/json; charset=utf-8',
url: '/Login?handler=LoginFunc',
data: parameter,
dataType: 'json',
headers: { "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val() },
success: function (data) {
onsuccess(data)
},
error: function (data, success, error) {
alert("Error: " + error + " - " + data + " - " + success + " - " + data.value)
}
})
}
Server side code(C#):
public class LoginModel : PageModel
{
public async Task<IActionResult> OnPostLoginFuncAsync(HttpContext http, JsonDocument json)
{
return new JsonResult("success");
}
}
Any help would be much appreciated
Thanks
Edit: here is the code that calls the ajax function
function onLoginLoad() {
const formLogin = document.getElementById("login");
formLogin.addEventListener("submit", function (event) {
const userName = formLogin.getElementsByClassName("username")[0].value;
const password = formLogin.getElementsByClassName("password")[0].value;
// stop form submission
event.preventDefault();
AJAXfunc(userName,password);
});
}
here is the HTML code
<form id = "login" action = "/LoginFunc" method = "post">
<h1>Login</h1>
<small></small>
<div class = "field">
<label for = "username" class="loginpg" style="top:45%;left:45%;position:fixed;color:white; width:10%;">Username</label>
<input type="text" class="username" name="username" id="username" style="top:48%;left:45%;position:fixed;width:10%;" placeholder = "Username"><br><br>
</div>
<div class = "field">
<label for = "password" class="loginpg" style="top:51%;left:45%;position:fixed;color:white;width:10%;">Password</label>
<input type= "password" class="password" id="password" name="password"style="top:54%;left:45%;position:fixed;width:10%;" placeholder = "Password"><br><br>
</div>
<input type="submit" value="Submit" class = "loginpg" style="top:57%;left:45%;position:fixed;width:10%;">
</form>
This is the exact error: 'Unexpected token '<', "\r\n\r\n<!DOCTYPE "... is not valid JSON'
yes, as a general rule if you client side js code is a big pile of a mess?
Then hitting the web page will OFTEN just choke, and simple return the whole page. When this occurs, it means your code is all wrong.
When you build/make a ajax call, you can pass values in the URL. This is what we call a REST call.
However, in most cases, we all "very much dislike" having to use those messy URL parmaters, so when we use .ajax calls, we perfer to use the .data option of the jQuery .ajax call.
Your code looks to have BOTH - and that's not going to work.
next up:
Remember those .ajax calls are NOT a post-back, and that means in code behind for that page class, such code does NOT have use of an "instance" of the page class (that code for example can't see/use/enjoy/change controls on the page).
So, that "method" of the page class MUST be static - since no "instance" of the page class will exist (since there is no page post-back).
So, dump the parmtaers in the URL - use ONE or the other (data, or URL based parmaters).
next up, if you NOT createing a seperatet asmx page with page methods, then if you choose to place the web methods in the existing page? (and I much like this choice, since then code and web methods are in the same place?
Then that web method must be MARKED as a web method, and also must be a static member of that page.
So, your code would/should look like this:
So, say client side markup and js code:
<h3>Enter user</h3>
<asp:TextBox ID="txtUser" runat="server" ClientIDMode="Static">
</asp:TextBox>
<h3>Enter password</h3>
<asp:TextBox ID="txtPass" runat="server" ClientIDMode="Static">
</asp:TextBox>
<br />
<asp:Button ID="cmdLogIn" runat="server" Text="Login"
OnClientClick="mylogin();return false;"
/>
<script>
function mylogin() {
sUser = $('#txtUser').val()
sPass = $('#txtPass').val()
AJAXfunc(sUser,sPass)
}
function AJAXfunc(username, password) {
var parameter = JSON.stringify({ "username": username, "password": password })
$.ajax({
type: "POST",
contentType: 'application/json; charset=utf-8',
url: 'WebCalltest.aspx/LoginFunc',
data: parameter,
dataType: 'json',
success: function (mydatastuff) {
alert('return value = ' + mydatastuff.d)
// onsuccess(mydatastuff.d)
},
error: function (data, success, error) {
alert("Error: " + error + " - " + data + " - " + success + " - " + data.value)
}
})
}
</script>
And code behind (assuming same page), then is this:
[WebMethod]
public static string LoginFunc(string username, string password)
{
// do whatever
return "this is the string return result";
}
So, now when we run above, we get/see this:
So, above is the "basic" layout and "pattern" as to how this works.
Now in above example, the web method in the page is on/placed in the same page - hence the URL change I used in above. You of course will have to change the url to your current page. And be careful, the page URL is relative to your current page - the "/" does not mean root in js code.
Also note close, the return value is a .d attribute. This is a .net quirk, and thus you don't use data, but use data.d, or in my example mydatastuff.d
So, don't forget/leave out the .d to get the return result from that web method.

Getting null in spring-boot REST request param from HTML form

I've an HTML form where I'm getting 2 inputs, which is submitted to a spring boot REST api. But in this simple application, I'm still receiving null as request in backend api.
Form
<div>
<label>alphaID</label>
<div>
<input id="alphaID" name="alphaID" type="text"/>
</div>
</div>
<div>
<label class="col-md-4 control-label">Domain Name</label>
<div class="col-md-4">
<input id="domain" name="domain" type="text"/>
</div>
</div>
Upon submit, I'm calling ajax call, like:
function formSubmit() {
$("#productForm").submit(function(e) {
e.preventDefault();
var requestJson = createRequestJSON();
var url = config.myurl;
$.ajax({
url: url,
type : "POST",
data: JSON.stringify(requestJson),
success: function( data, textStatus, jQxhr ) {
console.log("sucess: " + data);
},
error: function( jqXhr, textStatus, errorThrown ){
console.log( "error: " + errorThrown );
}
});
});
}
The backend is a spring-boot application with REST call:
#RequestMapping(value = "/validate", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public Map<String, List<String>> validate(#Valid MyDTO myDTO) {
System.out.println(myDTO.getId()); // GETTING null
System.out.println(myDTO.getDomain()); // GETTING null
}
MyDTO.java
public class MyDTO {
#JsonProperty("alpha_id")
private String alphaID;
#JsonProperty("domain")
private String domain;
....
}
Change your Content-Type to
consumes = MediaType.APPLICATION_JSON_VALUE
Add #RequestBody annotation
public Map<String, List<String>> validate(#Valid #RequestBody MyDTO myDTO)
Make sure you are calling proper URL and sending proper content-type from your browser request too.
It might be interesting to see if your requestJson actually has the correct format in order for the MyDTO to consume it.
You also don't have to Json.stringify you data. When you do this, you basically just send an string to the backend. The backend does not know that it hast to parse this string to get a valid document. You either just send the JavaScript object directly in the data property or you change the API to expect a String and parse it in the function later.

Why isn't my form data getting to my #RequestBody

I am using Spring. I have a controller that creates a page for the user, who then enters data. I need to capture that data and put in a database
My Controller
#Controller
#RequestMapping({"/pdc"})
public class PDCController {
// generate page to send to user
#RequestMapping(value = {"/{ffaAssgnId}"}, method = RequestMethod.GET)
public String getAssignment(Model model, #PathVariable Integer ffaAssgnId) {
Integer userContactId = userService.getUserContactId();
PDCAssgn assignment = pdcService.getAssgn(ffaAssgnId, userContactId);
List<MagValidate> statuses = validateService.getValidateByType("FAS");
Map<Integer, MagValidate> mapStatuses = new HashMap<>();
for (MagValidate status : statuses) {
mapStatuses.put(status.getValidateId(), status);
}
model.addAttribute("mapStatus", mapStatuses);
model.addAttribute("assignment", assignment);
return "pdc";
}
// get response from user
#RequestMapping(value = {""}, method = RequestMethod.POST)
public #ResponseBody AjaxResponse updateAssignment(#RequestBody PDCAssgn assignment) {
System.out.println(assignment.toString());
// try {
// pdcService.updateAssgn(assignment);
// } catch (Exception ex) {
// ex.printStackTrace();
// List<String> errors = new ArrayList<>();
// errors.add("Error saving DARF.");
// return new AjaxResponse("ERROR", null, errors);
// }
return new AjaxResponse("OK", null, null);
}
}
Part of my rendered form
<td><input id="wholesalerIssues0.assgnIssue.promoDealers" name="wholesalerIssues[0].assgnIssue.promoDealers" class="numberLarge" type="text" value=""/></td>
<td><input id="wholesalerIssues0.assgnIssue.dealersFound" name="wholesalerIssues[0].assgnIssue.dealersFound" class="numberLarge" type="text" value=""/></td>
<td><input id="wholesalerIssues0.assgnIssue.curDraw" name="wholesalerIssues[0].assgnIssue.curDraw" class="numberLarge" type="text" value=""/></td>
<td><input id="wholesalerIssues1.assgnIssue.promoDealers" name="wholesalerIssues[1].assgnIssue.promoDealers" class="numberLarge" type="text" value=""/></td>
<td><input id="wholesalerIssues1.assgnIssue.dealersFound" name="wholesalerIssues[1].assgnIssue.dealersFound" class="numberLarge" type="text" value=""/></td>
<td><input id="wholesalerIssues1.assgnIssue.curDraw" name="wholesalerIssues[1].assgnIssue.curDraw" class="numberLarge" type="text" value=""/></td>
Equivalent jsp
<td><form:input path="wholesalerIssues[${whStatus.index}].assgnIssue.promoDealers" cssClass="numberLarge" placeholder="${targetTitle.promoDealers}"/></td>
<td><form:input path="wholesalerIssues[${whStatus.index}].assgnIssue.dealersFound" cssClass="numberLarge" placeholder="${targetTitle.dealersFound}"/></td>
<td><form:input path="wholesalerIssues[${whStatus.index}].assgnIssue.curDraw" cssClass="numberLarge" placeholder="${targetTitle.curDraw}"/></td>
The javascript to send the data
function doSendA(e) {
e.preventDefault();
var form = $("#frm-assignment");
var formFields = $("#frm-assignment input:not([readonly])")
var formData = {}
$.each(formFields, function(i, v){
var input = $(v);
// populate form data as key-value pairs
// with the name of input as key and its value as value
formData[input.attr("name")] = input.val();
});
console.log(formData);
$.ajax({
type: "POST",
url: "${pageContext.request.contextPath}/pdc",
contentType: "application/json; charset=utf-8" ,
data: JSON.stringify(formData),
dataType: "json",
success : function(ajaxResponse) {
if (ajaxResponse.status !== "OK") {
hideLoading();
showToast("bad", ajaxResponse.errors[0]);
return;
}
hideLoading();
// location.reload();
showToast("good", "Your data was saved.");
},
error : function(res) {
hideLoading();
showToast("bad", "There was a problem saving your data.");
}
});
}
The console.log(formData);
{"wholesalerIssues[0].assgnIssue.promoDealers":"123","wholesalerIssues[0].assgnIssue.dealersFound":"","wholesalerIssues[0].assgnIssue.curDraw":"","wholesalerIssues[1].assgnIssue.promoDealers":"","wholesalerIssues[1].assgnIssue.dealersFound":"","wholesalerIssues[1].assgnIssue.curDraw":""}
The controller's System.out.println(assignment.toString());
magforce.model.PDCAssgn#4f71f251[wholesalerIssues=<null>]
I played around with printing out things from the request and found that there were no errors during the binding, but my resultant data object remains empty. I have done many Google queries, but haven't yet found anything that uses Spring's form tags (<form:form> , <form:input>, etc.) plus ajax json and Spring's #RequestBody.
Not a real answer, but putting it here as an expansion to my comment. The goal here is to show you how you could test your endpont.
Your controller is exposing an endpoint. If you start up your application you have a URL you can access, in this case at "http://localhost:8080/pdc" (unless you are prefixing your URL, but based on what your are posting this should be your URL). If you are on a *NIX system you have curl at your disposal. If you are on Windows you might want to give Postman a try. To use curl on your POST endpoint, a call to your endpoint would be something like this. Of course I don't know your object structure so make sure to adjust the JSON according to the structure of your object.
curl -i -H "Accept: application/json" -H "Content-Type: application/json" \
-X POST -d \
'{
"yourObject":{
"someArray":[
{
"aDate":{
"year":2019,
"month":10,
"day":1
},
"someValue":4,
"otherVaule":10000,
"anId":1
}
],
"someOtherValue":100000,
"someStatus":"DRAFT"
}
}' http://localhost:8080/pdc
By testing your endpoint using a tool like this you can isolate the problem you are having. Once you have a successful cal to your endpoint you will at least know that your endpoint is in order and that any problems will lie in your JavaScript code.

How do I add basic auth headers to a post request that returns html?

For one of the projects I am working on, there is a POST endpoint protected by basic auth that returns a HTML form. This is hosted using a express server and protected using passport's basic auth. I want to have another HTML form that has a button that, when clicked, loads that html in the browser. I tried to have a form similar to this one:
<form method="post" action="http://username:password#localhost:8080/endpoint">
<input type="submit">
</form>
But when the button is clicked and I check the auth headers on the server, they seem to be unset (req.headers.authorization = undefined). I know that I can set the auth headers using Javascript, but if I do that, I'm not sure how to load up the html in the browser on that page. So, how do I deal with an endpoint that requires basic auth headers, is accessed using post and returns HTML? This seems like it should be easy to do, but I'm not sure how to do it.
You need to add the auth headers in javascript.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example</title>
<script src="http://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
</head>
<body>
<form id="myForm">
<input type="submit">
</form>
<script type="application/javascript">
$("#myForm").submit(function (e) {
var url = 'http://localhost:8080/endpoint';
var username = 'username';
var password = 'password';
$.ajax
({
type: "POST",
url: url,
dataType: 'json',
async: false,
headers: {
"Authorization": "Basic " + btoa(username + ":" + password)
},
data: '{ "comment" }',
success: function (response){
$(body).empty();
$(body).html(response);
}
});
e.preventDefault();
});
</script>
</body>
</html>

How to add Header Authorization for POST FORM using JS/AJAX/JQUERY?

I wanna get inputs using a form on my page and submit those values to a php hosted on another external site. Request maker extension shows the Header Authorization being passed along with other inputs when submitting data on the external site.
The result is probably an xml file (Student Record).Need to pull and show it as result.
Tried a lot using $.Ajax and jquery in vain. Please help.
[1]: http://i.stack.imgur.com/rDO6Z. jpg
[2]: http://i.stack.imgur.com/92uTh. jpg
function myFunction() {
var name = document.getElementById("name").value;
// AJAX code to submit form.
$.ajax({
type: "POST",
url: "http://externalsite.cpm/results.php.php",
data: dataString,
beforeSend: function(xhr) {
xhr.setRequestHeader('Authorization', "Basic XXXXXXXXXXXXXXXXXXXXXXXXX" ); or xhr.setRequestHeader('Authorization', "Basic " +btoa(ser_user + ':' + ser_pass));
},
cache: false,
success: ???
xmlhttp.open("POST","your_url.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("name=" + name + "&email=" + email);
<body>
<form action="http://externalsite.cpm/results.php" method="post" >
Enter Your Name<br>
<input type="text" name="name" >
<br>
<input type="submit" onclick="myFunction()" value="Submit">
</body>
How do I add this header authorization when submitting values from my page to external php? Please Help !
Its bit late but still posting the answer for future readers who might face the same issue.
Please do not provide the form submit url (action) and method type (POST) inside the html code when it is explicitly mentioned inside the ajax request.
Notice the corresponding changes added in the code snippets given.
Html form code :
<form><!---Removed form submit url-->
<input type="text" id="keyName" value="testValue">
<!---Id attribute added to input field to be submitted--->
<input type="button" onclick="myFunction()" value="Submit">
<!---Input type is button NOT submit--->
</form>
Javascript code:
function myFunction(){
var dataValue = $("#keyName").val();
$.ajax({
type : 'POST',
//remove the .php from results.php.php
url : "http://externalsite.cpm/results.php",
//Add the request header
headers : {
Authorization : 'Bearer ' + 'XXXXXXXXXXXXXXXXXXXXXXXXX'
},
contentType : 'application/x-www-form-urlencoded',
//Add form data
data : {keyName : dataValue},
success : function(response) {
console.log(response);
},
error : function(xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
console.log(err);
}
}); //End of Ajax
} // End of myFucntion
Update :
PHP service results.php
<?php
print_r($_POST["keyName"]);
?>
I had a similar issue, needed to add authentication header name and authentication token value in the HTTP POST request headers. Added this javascript interceptor function in one of the JSPs that forms the HTML panel that's part of every page in the web application.
// this will add employee authentication headers to every ajax call
(function() {
var site = window.XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.send = function() {
this.setRequestHeader("${employee.role.header}", "${employee.auth.secret}")
return site.apply(this, [].slice.call(arguments));
};
})();

Categories