Controller Action Not Found JSON and ASP.NET MVC - c#

Hi I have this controller method
[HttpPost]
public JsonResult CalculateAndSaveToDB(BMICalculation CalculateModel)
{
if (ModelState.IsValid)
{
CalculateModel.Id = User.Identity.GetUserId();
CalculateModel.Date = System.DateTime.Now;
CalculateModel.BMICalc = CalculateModel.CalculateMyBMI(CalculateModel.Weight, CalculateModel.Height);
CalculateModel.BMIMeaning = CalculateModel.BMIInfo(CalculateModel.BMICalc);
db.BMICalculations.Add(CalculateModel);
db.SaveChanges();
}
var data = new
{
CalculatedBMI = CalculateModel.BMICalc,
CalculatedBMIMeaning = CalculateModel.BMIMeaning
};
return Json(data, JsonRequestBehavior.AllowGet);
}
And this is my JS functions:
$('#good').click(function () {
var request = new BMICalculation();
$.ajax({
url: "CalculateAndSaveToDB",
dataType: 'json',
contentType: "application/json",
type: "POST",
data: JSON.stringify(request), //Ahhh, much better
success: function (response) {
$("#result").text(response.result);
},
});
ShowBMI();
});
function ShowBMI() {
$.ajax({
type: "GET",
dataType: "json",
contentType: "application/json",
url: "CalculateAndSaveToDB",
success: function (data) {
var div = $('#ajaxDiv');
div.html("<br/> " + "<b>" + "Your BMI Calculations: " + "</b>");
printBMI(div, data);
}
});
};
When ShowBMI() is executed, Chrome says GET http://localhost:50279/BMICalculations/CalculateAndSaveToDB/0 404 (Not Found)
The POST works as it saves to the database etc but the GET doesn't? Is there any reason for this? As you can see the URLs are exactly the same in each JS function so Im not sure why its found once nut not again the second time?
UPDATE:
After separating logic, the values appearing on the webpage are both null. See below for code changes
[HttpPost]
public JsonResult CalculateAndSaveToDB(BMICalculation CalculateModel)
{
if (ModelState.IsValid)
{
CalculateModel.Id = User.Identity.GetUserId();
CalculateModel.Date = System.DateTime.Now;
CalculateModel.BMICalc = CalculateModel.CalculateMyBMI(CalculateModel.Weight, CalculateModel.Height);
CalculateModel.BMIMeaning = CalculateModel.BMIInfo(CalculateModel.BMICalc);
db.BMICalculations.Add(CalculateModel);
db.SaveChanges();
}
CalculateAndSaveToDB(CalculateModel.BMICalc.ToString(), CalculateModel.BMIMeaning.ToString());
return Json("", JsonRequestBehavior.AllowGet);
}
[HttpGet]
public JsonResult CalculateAndSaveToDB(string o, string t)
{
var data = new
{
CalculatedBMI = o,
CalculatedBMIMeaning = t
};
return Json(data, JsonRequestBehavior.AllowGet);
}

That's because you've applied the [HttpPost] attribute :) That attribute renders the action available solely for POSTing and not GETing. You should move the logic that is relevant for GETing to an action with the same name but without the [HttpPost] attribute and keep the logic for handling POSTed data in the action marked with the [HttpPost] attribute.
Be advised that you should reconsider the names when separating logic into different methods, or else the names will be misleading.
Regarding your update
I would have the POST request handling action (your action marked with HttpPost) return an ActionResult which in essence would mean that the POST request handling action upon successfully handling your request would redirect the user to a confirmation page or somewhere else. Wherever's preferable really :)
Try to approach it logically, what would be the natural chain of events upon POSTing the data? What would you as a user expect to happen?
Regarding your GET action, that is because you are not sending in the parameters o and t, which you then immediately return. Since nothing happens to these parameters in your logic and they are not otherwise specified, they will contain null which is the default value for variables of type string. Are you not intending to retrieve data from the database, rather than supply two parameters only to immediately return them?

Related

ASP.NET Core jQuery POST - Incorrect Content-Type despite correctly formatted headers

I have researched similar threads, such as this one and this one, and have determined that this deserves its own thread, as I could not find any help in an hour of research.
I am trying to send a POST request to an ASP.NET Core host from a jQuery request. This is how I've formatted my POST request in the frontend:
$.ajax({
url: "/Merge",
type: "POST",
contentType: 'application/x-www-form-urlencoded',
datatype: "json",
data: {
"example": "examplecontent"
},
success: function (data) {
alert(data);
}
});
This is the way I'm ingesting it in the backend for testing purposes:
[HttpPost]
public IActionResult Index()
{
var x = HttpContext.Request.Form;
Dictionary<string, string> exampleDict = new();
//exampleDict.Add("Testing", HeaderElem);
JsonResult result = new(exampleDict);
return result;
}
Despite including complete headers, I have been getting this error on the backend claiming that I have an 'incorrect content type':
What might be wrong with my request?
you have to fix the action
[Route("~/Merge")]
public IActionResult Index(string example)
{
return Ok ( new { example = example } );
}

How to pass data from a controller to view during a JQuery AJAX call in MVC?

In my view, I have an AJAX call which sends an id parameter to my controller. This bit works fine. In my controller, I plan to query the database with that id, pull out associated data and want to send this back to the AJAX call/view. This is the bit I am struggling with, as I am new to AJAX calls.
var chosenSchoolID = $("#SelectedSchoolId").val();
$.ajax({
url: "/Home/GetSchoolDetailsAJAX",
type: "POST",
data: {
schoolID: chosenSchoolID
},
dataType: "text",
success: function(data) {
if (data == "success") {
}
},
error: function(data) {
if (data == "failed")
alert("An error has occured!");
}
});
The above is my AJAX call, and this does hit my controller method. However in my controller, I want to now send back other string data and I am unsure on how to do this (just placeholder code currently)
[HttpPost]
public ActionResult GetSchoolDetailsAjax(string schoolID)
{
// query database using schoolID
// now we have other data such as:
string SchoolName = "";
string SchoolAddress = "";
string SchoolCity = "";
return null;
}
Must I declare variables in my Jquery and pass into the data parameter of the AJAX call in order for the values to be passed?
Many thanks in advance
The simplest way to do this is to return the entities retrieved from your database using return Json() from your controller.
Note that when retrieving data then a GET request should be made, not a POST. In addition the default MVC configuration should have the routes setup to allow you to provide the id of the required resource in the URL. As such, try this:
$.ajax({
url: "/Home/GetSchoolDetailsAJAX/" + $("#SelectedSchoolId").val(),
type: "get",
success: function(school) {
console.log(school);
},
error: function() {
alert("An error has occured!");
}
});
[HttpGet]
public ActionResult GetSchoolDetailsAjax(string id) {
var school = _yourDatabaseContext.Schools.Single(s => s.Id == id); // assuming EF
return Json(school);
}
If you'd like to test this without the database integration, amend the following line:
var school = new {
Id = id,
Name = "Hogwarts",
Address = "Street, City, Country"
};

Execute web controller action without view [c#]

I have a datatable that gets values from a database with on every line on the last column a delete button.
$"<button type='submit' class='btn btn-danger test' id='{i.id}' onclick='return Delete();'>Delete</button>"
My button gets an id which is the id of the model from that row.
I want to delete the row if I click on the button.
But can't figure out how to call the method without my application trying to find the view. (I have no delete view and don't want to make one).
I've looked it up but nothing works.
My controller action :
[Authorize(Roles = "user")]
[HttpDelete]
public ActionResult Delete(Guid id)
{
if (BLayer.getAllGames().ToList().Exists(x => x.id == id))
{
BLayer.DeleteGame(id);
}
return new EmptyResult();
}
My Jquery function :
function Delete() {
var table = $("#tableOverviewGames").DataTable();
$('#tableOverviewGames tbody').on('click', 'button', function () {
var idGame = $(this).attr('id');
$.ajax({
url: "Delete",
type: 'DELETE',
data: { id: idGame },
async: false,
contentType: false,
success: function (data) {
alert("Vous avez supprimé le jeu");
},
error: function (data) {
console.log(data);
}
});
});
}
Can someone help me please?
Thanks!
EDIT:
This is the error I get in the console :
DELETE http://localhost:3673/Game/Delete 404 (Not Found)
Why dont you just return a JSON from the controller such as
return Json(new {success = true})
and then you can (if you need to) do checks in the ajax success against whether or not it worked
I see that when you make the call you're passing wrong Uri, thats why you got 404 NOT FOUND.
Change your HttpDelete attribute as
[HttpDelete("{id}")]
pass the guid as part of Uri like http://localhost:3673/Game/eef63296-6bb3-40a5-aa89-be69e75a66eb, also any body passed for delete calls will be ignored unless Content-Length header is added, check this link.
If you still insist on a body, try changing signature as shown below
[Authorize(Roles = "user")]
[HttpPost("delete")] //Added route to differentiate Create/Insert REST end point
public ActionResult Delete([FromBody]Guid id)
Your AJAX call should be like
$.ajax({
url: "Delete",
type: 'DELETE',
data: idGame, // Pass value directly.
sync: false,
contentType: false,
success: function (data) {
alert("Vous avez supprimé le jeu");
},
If I were you, I'd start testing with basic type like string for fields that cause trouble.

MVC controller's method not returning view

I tried many ways and it's still not working... I'm calling controller's method with ajax call. Thanks to answer to my previous question it's working fine, I have data that I wanted to send from view in controller (in CreateIncident method). Problem is that controller should render new view and redirect to it, but it's not happening. For now I just want to see new view, nothing else, I'll deal with recieved data later. Any idea why is this happening? Is this because I'm calling method with ajax and not by e.g. simple Url.AcionLink?
Ajax call to method:
function addMarker(location, fulladdress) {
var data = JSON.stringify(fulladdress) + JSON.stringify(location)
$.ajax({
type: "POST",
url: "Incidents/CreateIncident",
dataType: "text",
data: {JsonStr : data}
})
}
Controller:
public ActionResult Create()
{
Incident newIncident = new Incident();
newIncident.AddDate = DateTime.Today.Date;
newIncident.DateOfIncident = DateTime.Today.Date;
newIncident.TimeOfIncident = DateTime.Today.TimeOfDay;
return this.View(newIncident);
}
[HttpPost]
public ActionResult CreateIncident(string JsonStr)
{
// RedirectToAction("Create"); //none of this three is working
// return View("Create");
return Redirect("Create");
}
No matter if I'm trying to access CreateIncident or Create the method is called, but there's no redirect to /Incidents/Create (I'm calling from Home/Index). Any ideas why? I would like to redirect to Create.cshtml straight from CreateIncident so I wouldn't have to pass data between methods, but any solution will do fine.
The redirect in that case has to be done through you AJAX call. Call your action method and do your logic, then redirect on success.
$.ajax({
type: "POST",
url: "Incidents/CreateIncident",
dataType: "text",
data: {JsonStr : data} ,
success: function (data) {
window.location.href = "Incidents/Create";
}
})
try:
url:"../Incidents/CreateIncident"
put in $ajax call error handling and see the error, it will help you
$.ajax({
type: "POST",
url: "Incidents/CreateIncident",
dataType: "text",
data: {JsonStr : data},
success: function(result){
// Do stuff
},
error: function(xhr){
alert('Request Status: ' + xhr.status + ' Status Text: ' + xhr.statusText + ' ' + xhr.responseText);
}
});
Use the view's full path instead of its name.
return View("/Incidents/Create");
Yes redirecting page in success event of ajax call is the only solution, as you are making ajax call not submitting a form. Browser redirects automatically after post only if you are posting a form.
However you can use following code if you don't want to redirect it in
success event.
function postData(url, allData){
form = document.createElement('form');
for(data in allData)
{
var input = document.createElement('input');
input.type = 'text';
input.name = data;
input.value = allData[data].toString();
form.appendChild(input);
}
form.method = 'post';
form.action = url;
form.submit();
}
and use this function like this :
function addMarker(location, fulladdress) {
var data = JSON.stringify(fulladdress) + JSON.stringify(location);
postData('/Incidents/CreateIncident', {JsonStr : data})
}
warning : haven't tested :).

Console Log Returning HTML Page Text Instead of JSON

I am trying to return a model in JSON form from a request sent as the following:
$(document).ready(function() {
(function(){
console.log("ran");
$.ajax({
type: "GET",
url: "https://clas.uconn.edu/Employees/Edit/22",
success: function(data) {
console.log("Success: " + data);
empData = data;
}
});
})();
});
My Controller for this method is:
// GET: Employees/Edit/5
public ActionResult Edit(int? id)
{
var id = employee.id;
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
if (employee == null)
{
return HttpNotFound();
}
return new JsonResult() { Data = employee, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
Console.WriteLine("error");
}
However I am getting an entire html page in the consol log even though none of these controller actions return a view. Any ideas?
Edit:
After adding the datatype, I am getting an error in the console log saying:
GET http://localhost:59909/Employees/EmployeeLookupDisplay
net::ERR_CONNECTION_REFUSED
It is returning the entire page because there is an error in your request somewhere.
Add a block error to your ajax call and console.log on the xhr. You will get much more information about the error like this.
What you can try is making the request on POST and checking the properties of the context on the C# code. Sometimes adding dataType and the encoding helps for the request.
Additionally check for the returning status of your request on your browser developer tools. In chrome it is the network tab that shows all requests and their status.
Try This, but according to your code its always returning HTTP not foud which is HTML page. if you have data to employee. i mean your controller action getting success without any error. then you can try tis.
$.ajax({
type: "GET",
url: "https://clas.uconn.edu/Employees/Edit/22",
dataType: "json",
success: function(data) {
console.log("Success: " + data);
empData = data;
}
Maybe instead of returning new JsonResult() { Data = employee, JsonRequestBehavior = JsonRequestBehavior.AllowGet };, just return Json(employee, JsonRequestBehavior.AllowGet);'
Another thing i see:
on the first line you are doing var id = employee.id; -> where employee comes from? maybe the error is there.

Categories

Resources