This question already has answers here:
How should I use servlets and Ajax?
(7 answers)
HTTP request parameters are not available by request.getAttribute()
(1 answer)
Closed 3 years ago.
I'm trying to send the username to the servlet through an ajax call to check its availability, but the servlet show a null pointer exception.
I've also tried with the XMLHttpRequest instead of $.ajax.
This is my Javascript file:
$(document).ready(function() {
$("#reg-form").submit(function() {
var res = true;
if (!testUser()) {
res = false;
$("#erruser").css("display", "block");
$("#username").addClass("errclass");
} else {
$("#erruser").css("display", "none");
$("#username").removeClass("errclass");
}
return res;
});
});
function testUser() {
var el = $("#username").val();
var b = false;
$.ajax({
type: "POST",
url: "CheckUserServlet",
data: { user: el },
dataType: "json",
success: function(bool) {
alert(bool);
if (bool == "si") b = true;
},
error: function() {
alert("errore");
}
});
return b;
}
This is my servlet doPost method:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username=request.getAttribute("user").toString();
System.out.println("username servlet= "+username);
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
if (!ud.doRetrieveByUser(username)) {
response.getWriter().write("si");
return;
}
response.getWriter().write("no");
return;
}
Thanks!
CLIENT SIDE
Your test user function will always return false regardless of if the server is operating correctly because $.ajax() is an async function. There are a few ways around this. In your case, without knowing much more about what you are building, I would suggest removing the return value from your test user function, and moving your logic into the success/failure areas in the ajax callback. This way, the ajax call just does it's thing and lets the success function modify your page however you want.
function testUser() {
var el = $("#username").val();
$.ajax({
type: "POST",
url: "CheckUserServlet",
data: { user: el },
dataType: "json",
success: function(bool) {
alert(bool);
// put logic here
if (bool === "si") {
$("#erruser").css("display", "block");
$("#username").addClass("errclass");
} else {
$("#erruser").css("display", "none");
$("#username").removeClass("errclass");
}
},
error: function() {
alert("errore");
}
});
}
I would also suggest setting up the initial state of your page so that while this request is happening the user is shown something that makes sense. Answer the following question: "what do I show my users when the page does not know yet if it is a test user" and then set the initial state of the page accordingly
SERVER SIDE
I've always found interacting with java & JSON data a bit clunky, and your issue seems like something I've grappled with in the past.
Your question is "why is ajax sending null to the server". It may seem like that but what is really happening is that your server doesn't understand how to interpret the data it is getting. Take a look at this question about getting a JSON payload.. You need to tell your server how to parse the data coming from the client. If you were to inspect the data being sent, I would expect it looks something like this {"user":"blablabla"}.
If you have a class definition already, use that. For this I am using something that looks like this:
public class UserRequest {
String user;
}
// get the body as a string. Requires https://commons.apache.org/proper/commons-io/
String body = IOUtils.toString(request.getReader())
// parse the json with gson. Requires https://github.com/google/gson
Gson g = new Gson();
User u = g.fromJson(body, UserRequest.class);
String username = u.user;
Related
The function getClientData() gets called from one of the anchor tags in a grid's column. The anchor tag has a couple of Data-Tags which are passed to the code behind method. I have to perform some DB operation through these parameters but before that I wanted to make sure if this prototype would work.
This is how the anchor tag looks:
Show
This is my Javascript method:
function getClientData() {
//var dataValue = { "keyData": this.event.target.getAttribute("data-kt"), "valueData": this.event.target.getAttribute("data-kv")};
$.ajax({
type: "GET",
url: "Clients.aspx/GetClientData",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ keyData: this.event.target.getAttribute("data-kt"), valueData: this.event.target.getAttribute("data-kv")}),
dataType: 'json',
error: function (error) {
alert(error.statusText);
},
success: function (result) {
alert("Success: " + result );
}
});
}
I put a break point here and it never gets triggered. This is my web method in the code behind file:
[WebMethod]
[ScriptMethod(UseHttpGet = false)]
public string GetClientData(string keyData, string valueData)
{
string result = string.Empty;
if (!string.IsNullOrEmpty(keyData) && !string.IsNullOrEmpty(valueData))
{
result = "Decrypted String!";
}
return result;
}
This is the URL that gets created for the POST request "http://localhost:60825/Clients.aspx/GetClientData?{%22keyData%22:%22Cpuqsrtsotmfegrhsi-jikdbCvuwsxtcodmeelrmI-Dn-ovpcqSresctrfegthKiejy%22,%22valueData%22:%221p7q9%22}". Please let me know if I am doing something wrong.
I am not sure how you configured routing but based on your API method (code behind) your data should be formatted in following manner:
Method 1:
http://localhost:60825/Clients.aspx/GetClientData?keyData=Cpuqsrtsotmfegrhsi-jikdbCvuwsxtcodmeelrmI-Dn-ovpcqSresctrfegthKiejy&valueData=1p7q9
As you can see, instead passing stringified JSON object I am sending data in format of query string where keyData and valueData has corresponding values.
Method 2:
If you prefer to send stringified JSON you can modify your Payload in URL like this:
http://localhost:60825/Clients.aspx/GetClientData?data=%7BkeyData%22%3A%22Cpuqsrtsotmfegrhsi-jikdbCvuwsxtcodmeelrmI-Dn-ovpcqSresctrfegthKiejy%22%2C%22valueData%22%3A%221p7q9%22%7D
Here I am sending stringified JSON as data parameter in query string. For that purpose your code behing method needs to be like this:
[WebMethod]
[ScriptMethod(UseHttpGet = false)]
public string GetClientData(string data)
{
string result = string.Empty;
if (!string.IsNullOrEmpty(keyData) && !string.IsNullOrEmpty(valueData))
{
result = "Decrypted String!";
}
return result;
}
I am calling MVC action method through jquery ajax post. This action method will either return a string value or if certain condition in action method is true it will redirect to another action method. The problem is whenever i am trying to redirect to another action method the ajax post is executing the error block and whenever the action method is returning a string value it works fine. I don't want to use html form post. Below is my code:
function VerifyCreds() {
$.ajax({
type: "POST",
url: "/Login/Verify",
data: '{Username: "' + $("#txtUsername").val() + '",Password: "' + $("#txtPassword").val() + '" }',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
alert(response);
},
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
}
public ActionResult Verify(string Username, string Password)
{
string Response = "0";
EmployeeEntities ent = new EmployeeEntities();
var val = ent.VerifyUser(Username, Password);
Response = val.FirstOrDefault().ToString();
if (Response == "1")
{
return this.RedirectToAction("LandingPage");
}
return Content(Response);
}
public ActionResult LandingPage()
{
return View();
}
You are explicitly specifying json as the data type. that means, your ajax method expects the response from the server as a json string. The jQuery ajax method will use JSON.parse method to create a JavaScript object from this json string and pass it to the callback. When you do a redirect from server, it is not returning a 200 OK response back, but a 302 redirect response back and browser will usually makes a new call to the location header value of the response. You are getting the error callback of the ajax method because the server is returning some string which cannot be safely converted to a JavaScript object using JSON.parse. (My guess is that the response for the LandingPage call!. Check the network tab to see what response is coming)
If you absolutely want to handle this situation, you may better return a proper JSON structure in both the cases and inspect this json data at client side and do a redirect as needed.
I also suggest you to use the appropriate types. Use int instead of storing a number in a string variable.
public ActionResult Verify(string Username, string Password)
{
var ent = new EmployeeEntities();
var val = ent.VerifyUser(Username, Password);
var response = val.FirstOrDefault();
if (response == 1)
{
return Json(new { status="redirect", url = Url.Action("LandingPage")});
}
return Json(new { status="success", message = "Valid login" });
}
and in the success event of your ajax call, inspect this json data and based on the status property, do a redirect or show a message to the user.
success: function (response) {
if(response.status==="redirect")
{
window.location.href = response.url;
}
else
{
alert(response.message);
}
},
You can also totally remove dataType: "json", from your ajax call. jQuery will intelligently guess the type based on the response headers and use that. Since we are explicitly returning Json from our action method, the response Content-Type header value will be application/json
this problem is really driving me crazy... I have 2 java web application: appA that publish a REST service which returns some object (which contains an image) in json format, and appB that consumes the service and shows the image. In my local machine it works (though I see the CORS error) but now I'm using a web environment (Layershift) and I'm getting an error "NetworkError: 404 Not Found - http://app-demo.j.layershift.co.uk/myservice/get/c80e9306105f4448?callback=myCallback&_=1477167892656"
I've been reading lot of examples of CORS and JSONP but I can't find what's wrong with my code, can anybody give a hint?
Controller in appA:
#RestController
public class MyController {
#RequestMapping(value="/myservice/get/{somevar}")
public #ResponseBody MyObject getMyObject (#PathVariable String somevar, HttpServletRequest request, HttpServletResponse response) {
MyObject obj = new MyObject();
//some logic
return obj;
}
}
ControllerAdvice in appA:
#ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("myCallback");
}
}
javascript code with jsonp call in appB:
(function($) {
function myCallback(data) {
if (data.status == "OK") {
//shows the image contained
}
}
$.fn.callWithJsonP = function(somevar) {
$.ajax({
url: "myservice/get/" + somevar,
type: 'GET',
dataType: "jsonp",
jsonpCallback: "myCallback"
});
};
})(jQuery);
Any help would be appreciated, regards
PS: also tried adding the directive "Header add Access-Control-Allow-Origin "*"" in Apache, but same result.
Here's how to perform a JsonP ajax call using Jquery.
E.g.:
$.ajax({
url: "http://localhost/ny-app/getJSfunction",
jsonp: "myfunctionName",
dataType: "jsonp",
data: soomedata,
success: function( response ) {
console.log( response ); // server response
}
});
Handle this call on the server side, and return a function encapsulated javascript code that returns some data. The returned javascript will look like this:
function myfunctioname(){
// some code
return 'whatever you want' ;
}
JQuery ajax will automatically execute the returned javascript function.
Hope this helps.
Finally can make the JSONP call, didn't solve my problem, but I'm able to make the call, so I'll post the changes.
First of all, in the main controller I'm not using #ResponseBody, I've changed it like this:
#RestController
public class MyController {
#RequestMapping(value="/myservice/get/{somevar}")
public MappingJacksonValue getMyObject (#RequestParam String callback, #PathVariable String somevar, HttpServletRequest request, HttpServletResponse response) {
MyObject obj = new MyObject();
//some logic
MappingJacksonValue value = new MappingJacksonValue(obj);
value.setJsonpFunction(callback);
return value;
}
}
Notice the return type is MappingJacksonValue (thanks to JSONP with Spring 3.0 and Jackson), and the javascript code is this:
$.fn.callWithJsonP = function(somevar) {
var url = "/myservice/get/" + somevar + "?callback=myCallback";
$.getJSON(url, function(data) {
if (data.value.status == "OK") {
//show the image contained
}
});
}
There was no need to define a function called "myCallback". I've tested in my local machine and it is working.
Thanks everybody for your suggestions.
I am trying to send a string to my ActionResult in the controller. I have followed many tutorials and read hundreds of stackoverflows but can't get it to work. I am trying to send a string with the value of a radiobutton.
My ActionResult code is:
[HttpPost]
public ActionResult Opslaan(string theStatus)
{
if(theStatus!= null)
Database.UpdateAanvraagStatusByGuid(Session["Guid"].ToString(), theStatus);
return new RedirectResult(Request.UrlReferrer.OriginalString);
}
My code to send the variable via AJAX:
$("#opslaan").click(function (e) {
e.preventDefault();
var theStatus = $('input[name=StatusOptions]:checked').val();
$.ajax({
type: "POST",
url: "/Aanvraag/Opslaan",
data: theStatus,
success: function (result) {
if (result.Success) {
alert("Uw wijzigingen zijn opgeslagen.");
} else {
alert(result.Message);
}
}
});
});
When I click my button called "opslaan" the program does not execute te AJAX. Alerts around it do go off.
Thanks in advance :)
Edit Fabio's answer like this:
$("#opslaan").click(function (e) {
e.preventDefault();
var theStatus = $('input[name=StatusOptions]:checked').val();
$.ajax({
type: "POST",
url: "/Aanvraag/Opslaan?theStatus= " + theStatus ,
//data: { 'theStatus': theStatus } ,
success: function (result) {
if (result.Success) {
alert("Uw wijzigingen zijn opgeslagen.");
} else {
alert(result.Message);
}
}
});
});
Note the query string at the end of the url property. Even though string IS a nullable type, if you don't have any route configuration like "/Aanvraag/Opslaan/theStatus", the routing system will not find a match.
There are a few things to note here:
Your original solution DID show an alert, that means a request went to the server, and a response has arrived.
Fabio's answer didn't work because you (as I guess) don't have any route like "/Aanvraag/Opslaan/theStatus". Even though string is a nullable type - so the routing system will allow a string parameter to have no incoming value from the request - the url parameter set by the client told the routing system 'Hey please forward me to something that is configured to a url like "/Aanvraag/Opslaan/theStatus"'. I am sure You don't have any route set up with that pattern so the routing system will fail to find a matching Controller/Action method pair, that results in a 404.
Your original solution didn't cause this problem, because you sent the theStatus parameter as data, and your url was "/Aanvraag/Opslaan". This means even the default route will be able to find out that the Controller is 'Aanvraag' and the controller is 'Osplaan'. From then on, Model Binding was able to bind your theStatus parameter to the action method parameter. (If it wasn't, the proper action method would strill be called, just with a null value given to the parameter.) However, your response didn't send any object with property Success back, so your if statement went to the else branch.
All in all, you can either send the theStatus parameter as data and let the model binding system to bind it to your action method parameter, or use routing to do that for you. In this latter case, you must either configure a proper routing entry or use a query string like in my modified version.
For the if statement to work, you need to send back something that does have a Success property, like Fabio did.
It might be helpful:
[HttpPost]
public ActionResult Opslaan(string id)
{
if(id != null)
Database.UpdateAanvraagStatusByGuid(Session["Guid"].ToString(), id);
// do your logic to check if success is true or false
return Json(new { Success = true, Message = "something" });
}
Javascript:
$("#opslaan").click(function (e) {
e.preventDefault();
var theStatus = $('input[name=StatusOptions]:checked').val();
$.ajax({
type: "POST",
url: "/Aanvraag/Opslaan/ " + theStatus ,
//data: { 'theStatus': theStatus } ,
success: function (result) {
if (result.Success) {
alert("Uw wijzigingen zijn opgeslagen.");
} else {
alert(result.Message);
}
}
});
});
EDIT
Just to see if it works, change the name of the parameter in the Action and Javascript.
I'm trying to do a simple action with some JavaScript code. I've got some items on a scheduler (DevExpress scheduler component). When I'm double clicking on an appointment (an item then), it should raise an JS function which is the case. My function should get the selected appointment id and pass it to Controller Action. Here is my JS code :
function DoubleClick() {
debugger;
var apt = GetSelectedAppointment(scheduler);
var aptid = apt.appointmentId;
$.ajax({
type: "POST",
url: "/Home/GetAppId",
data: { id: aptid },
dataType: 'json',
success: function () {
alert("ok");
},
error: function () {
alert("error");
}
});
}
And here is my C# code :
[HttpPost]
public JsonResult GetAppId(int id)
{
context = new SchedulingDataClassesDataContext();
DBAppointment app = (from a in context.DBAppointment where a.UniqueID == id select a).FirstOrDefault();
return Json(new {rep = app});
}
As you can see in my JS code, I'm not doing anything special in case of success. However, I never reach the success part. Plus, when I'm looking at the Chrome dev tool (F12), I'm getting that red error message.
POST http://localhost:25206/Home/GetAppId 500 (Internal Server Error)
Anything that I'm doing wrong?
Man, you need to force things as follows
return Json(new {rep = app},"text/json",JsonRequestBehavior.AllowGet);
In addition, mind your navigation properties (if any) in order to avoid circular reference
According to your error your problem somewhere in select your data from DB or creating anonymous object when you try to serialize it to Json. I rewrite your select to simplify it and not creating any anonymous objects when return it from Controller like this:
[HttpPost]
public JsonResult GetAppId(int id)
{
context = new SchedulingDataClassesDataContext();
DBAppointment app = context.DBAppointment.FirstOrDefault(x => x.UniqueID == id);
return Json(app);
}
Does it work like this?
Please remove the name of the property in ajax data and edit that property as below.
function DoubleClick() {
debugger;
var apt = GetSelectedAppointment(scheduler);
var aptid = apt.appointmentId;
$.ajax({
type: "POST",
url: "/Home/GetAppId",
data: aptid,
dataType: 'json',
success: function () {
alert("ok");
},
error: function () {
alert("error");
}
});
}
and edit your controller as follows
[HttpPost]
public JsonResult GetAppId([FromBody]int id)
{
//...
}
Please read this blog post which is a good read and allowed me to understand what's going on.
http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/
The original question that I asked
Simple post to Web Api
Try changing the last line of the method to:
return Json(new { rep = app }, JsonRequestBehavior.AllowGet);
You need to tell C# to allow the json to be returned to the client.