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.
Related
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;
This is my action:
[HttpGet]
public virtual ActionResult DesignItemsList(int dealId, string sort)
{
return View(MVC.Designer.Views._DesignItems, _designerService.GetDesignItems(dealId, sort));
}
The GetDesignItems() method is working correctly.
$(document).ready(function() {
$('.product__filtr__form__select').change(function(e) {
var sort = $(this).val();
var urlFilter = $('#url-filterPanel-hidden-field').val();
var dealId = $('#dealId-hidden-field').val();
var urlItems = $('#url-items-hidden-field').val();
$.ajax({
type: "GET",
data: {
dealId: dealId,
sort: sort
},
url: urlItems,
success: function (result) {
console.log(result);
$('#Product-Items-Container').html(result);
}
});
});
});
Request is working too, but I don't receive the response and get only 500 code.
500 error code means, Internal server error. Your action method failed to process thie request you sent.
Since it is a GET action method, You may add the query string parameters to the url.
var sort = $(this).val();
var dealId = $('#dealId-hidden-field').val();
var urlItems = $('#url-items-hidden-field').val();
urlItems = urlItems+"?dealId="+dealId+"&sort"+sort;
//Let's write to console to verify the url is correct.
console.log(urlItems);
$.get(urlItems,function(res){
console.log('result from server',res);
$('#Product-Items-Container').html(res);
});
Try to replace the view name inside your controller:
return View("YourControllerView", _designerService.GetDesignItems(dealId, sort));
Because I was tested your ajax request and find out that it works fine.
And pay attention to view location. This view must be located inside the directory with the same name as your controller or inside the shared dictory
Hello denizens of stackoverflow, I've been debugging a pesky ajax POST method for a bit too long now, and was hoping I could get some input. I have a JavaScript function that collects an array of strings to box up and send off to a controller method of mine, but unfortunately the parameter data is not being sent, and I cannot figure out why.
Here is the JS function:
$.ajax({
url: 'CancelDoc',
method: 'POST',
datatype: 'json',
headers: addAntiForgeryHeader(),
data: { datakeys : DataKeys }
}).done(function (data) {
if (data.status == 0) {
alert("DOCUMENT CANCELLED SUCCESSFULLY");
}
});
To clarify a little:
DataKeys is the array of strings. It is coming through to this point as it should.
Looks something like:
["1432long-crazy4297-jumbled5826string|9000|1|1|NEW",
"1432and2-another03-jumbled1594string|9000|1|1|NEW"]
addAntiForgeryHeader() is an extra client validation method that I add on to all POSTs. The problem should not lie here because I have commented this out to try the call and it still does not pass data.
The C# controller method this goes to:
Note: the code DOES make it this far, the datakeys parameter is null though.
public ActionResult CancelDoc(string[] datakeys)
{
DocObject Doc = new DocObject();
List<string> Datakeys = datakeys.ToList();
foreach (var dk in Datakeys)
{
...
Some model logic here (not even making it here so no worries)
...
}
return Json(new { status = 0 });
}
I have tried:
Data conversion to JSON in numerous ways: ko.mapping.toJS(data), JSON.stringify(data), and literal writing of a JSON object for this.
Stripping the call down to the most basic form: I have tried commenting out the datatype and headers properties. This had a couple more properties before I posted as well.
Any input is greatly appreciated.
The dataKeys payload need to be stringify as :
$.ajax({
//prev code
data: { datakeys : JSON.stringify(DataKeys) }
}).done(function (data) {
//success
});
In the MVC controller, desearlze the json as:
public ActionResult CancelDoc(string[] datakeys)
{
dynamic sourceJson = JsonConvert.DeserializeObject(dataKeys, typeof(object));
DocObject Doc = new DocObject();
List<string> Datakeys = sourceJson.ToList();
}
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.
So basically Here is what I do:
in body - onload method I call this javascript function
function TestN() {
var list = new Array();
var allElements = document.getElementsByTagName('*');
$("*[wordNum]").each(function ()
{
var endRes = {
ControllerName: this.id,
WordNumber: this.getAttribute("wordNum")
};
list.push(endRes);
});
jQuery.ajax({
url:' #Url.Action("Translate")' ,
contentType: "application/json",
dataType: "json",
data: { List : JSON.stringify(list) }
,
traditional: true
})
}
what it does - it searches all the controlls with attribute "WrdNum" and then I make an ajax request to the MVC Translate action!
In the Translate Action I make a request to a web service which populates a list of type - TranslateModel
public ActionResult Translate(string List)
{
List<TranslateModel>listto = WebServiceBea.TranslateList(1, List);
return View(listto);
}
Also Here is my TranslateModel
public class TranslateModel
{
public string ControllerName { get; set; }
public string WordNumber { get; set; }
public string Description { get; set; }
}
So basically my question is -> what type should I return to a view - > and how to return this list to a javascript or jquery function which has to set the innerHtml property of some html controls with the record from this list.**
I now that it's strange but that's my task
EDIT
Thanks so much for the help. But now I've got another problem:
After I changed my javascript and put. Done method so I could get the data from the server it looks something like this :
$(document).ready(function () {
var list = new Array();
$("*[wordNum]").each(function () {
var endRes = {
ControllerName: this.id,
WordNumber: this.getAttribute("wordNum")
};
list.push(endRes);
});
jQuery.ajax({
url: ' #Url.Action("Translate")',
contentType: "application/json",
dataType: "json",
data: { List: JSON.stringify(list) }
,
traditional: true,
}).done(function (result)
{
alert ("HII") ;
});
});
no matter what I put in the .done function it never executes. It seems like the controller doesn't know where to return the result. |I| don't now. Can something happen from the fact that I'm making this request from the .layout page - on document ready. s
this looks like a greet place to use knockout js.
here is a great step by step for using knockout with the mvc view
so the method will only return json, the view will not have a model just a call to get the json
if you are going to use $.post to pull your data you could return your list as json
[AcceptVerbs(HttpVerbs.Get|HttpVerbs.Post)]
public ActionResult Translate(string List)
{
List<TranslateModel>listto = WebServiceBea.TranslateList(1, modelObj);
return Json(listto);
}
Looking at what you are posting to the action method, it should already be a list of that type. MVC should do the heavy lifting and transform it to the objects you have.
if however you would like to handle the return yourself you can do something like
jQuery.ajax({
url:' #Url.Action("Translate")' ,
contentType: "application/json",
dataType: "json",
data: { List : JSON.stringify(list) },
traditional: true
}).success(function( returnData, returnStatus)
{
//some code to handle the list of objects reutrned
});
You've already got an answer, but consider the following for cases where you may have controller actions called by javascript:
public ActionResult GetItems(string id)
{
var MyList = db.GetItems(id);//returns a list of items
if (Request.IsAjaxRequest())//called from javascript via AJAX
{
return Json(MyList, JsonRequestBehavior.AllowGet);
}
else //regular hyperlink click
{
return View(MyList);
}
}
To use the list, do the following
$.ajax({url: "'#Url.Content("~/controllername/GetItems")?id=' + id"})
.done(function(result){
var mylist = result.responseText.evalJSON();//this is your list of items
for(i=0;i<mylist .length;i++)
{
var myitem = mylist[i];
}
});
NEVERRRR NEVERRR Forge to put jsonRequestBehavior.AllowGet
Thanks alot for everyone for the help