ASP.NET MVC 4 : enabling XmlHttpRequest post to controller with $.ajax() - asp.net

Seems a simple thing but I've spent all day looking through posts all over the web with little recourse! Please help. I have a simple request to be posted to a MVC controller...
$(document).ready(function () {
$('#json_request').on("click", function () {
// send request to server for menu json data
$.ajax({
type: "POST",
url: location.protocol + "//" + location.host + "/Tablet/Menu",
data: { restaurantId: $('#restaurantId option:selected').val(), mealSessionId: $('#mealSessionId option:selected').val() },
success: function (menuData) {alert(menuData); },
error: function () { alert("failed"); }
});
});
});
The request just won't reach the controller! The app works fine when I post the request as a Html form. It works fine with the Visual Studio Development Server too.
I get 404 error with IIS 7.0 / ASP.NET / MVC 4. Possibly, contentType: application/x-www-form-urlencoded does not get through the http-protocol filters. Do I have to set those specifically? How? Thanks for your help. I am not send the request as a json, so i did not try contentType: application/json.
Controller / Action:
[HttpPost]
public ActionResult Menu(short restaurantId, short mealSessionId)
{
try
{
MenuInput menuInput = new MenuInput(restaurantId, mealSessionId);
menuInput.LoadMenu();
if (Request.IsAjaxRequest())
{
MemoryStream ms = new MemoryStream();
menuInput.AsJson(ms);
string jsonString = Encoding.UTF8.GetString(ms.ToArray());
JsonResult result = Json(jsonString, "text/x-json");
ms.Close();
return result;
}
else
{
return View("MenuInformation", menuInput);
}
}
catch (Exception ex)
{
System.Console.Write(ex.ToString());
return View();
}
}

Related

Posting to Web API Controller from Razor Page Always Returns 400 Error

I am new to .Net Core and MVC. I've got several Razor Pages that allow users to post stuff like comments and ratings for individual posts, but I want to try something new for liking a post so that it can be done using javascript without refreshing the page. To do this I am trying to pass data from the page to a service class via an API controller using jQuery ajax. Unfortunately every time I try to pass a simple value to the controller I get a an error 400 saying that the value cannot be converted to System.WhateverObjectTypeITry. For instance if I try to pass it as an integer I get "The JSON value could not be converted to System.Int32" and if I try to pass it as a string I get "The JSON value could not be converted to System.String"
My API controller looks like this:
[HttpPost]
[Route("AddPostLike")]
public async Task<string> AddPostLike([FromBody] int postid)
{
if(_signInManager.IsSignedIn(User))
{
ApplicationUser user = await _userManager.GetUserAsync(User);
Likes newLike = new Likes();
newLike.Post = Convert.ToInt32(postid);
newLike.Commentid = null;
newLike.Userid = user.Id;
await _likeService.LikeAsync(newLike);
return $"liked";
}
else
{
return $"User Must Be Logged in to Like";
}
}
My jQuery in the Razor Page looks like this:
<script>
$(document).ready(function () {
$('#like-post').on('click', function () {
var postid = parseInt($('#idlabel').text());
$.ajax({
url: '/api/Likes/AddPostLike/',
type: 'POST',
dataType: 'text',
data: '{"postid":"' + postid + '"}',
contentType: 'application/json',
success: function () {
var likecount = parseInt($('#like-post-count').text());
likecount + 1;
$('#like-post-count').text(likecount);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("responseText=" + XMLHttpRequest.responseText + "\n textStatus=" + textStatus + "\n errorThrown=" + errorThrown);
}
});
});
});
</script>
I am using .Net Core 5.0 and am trying to use the Contoso Crafts demo as a guide, but the people at Microsoft that built Contoso Crafts decided to use a Blazor component instead of a razor page which somehow communicates with controllers despite not requiring the developer to write any javascript (see https://github.com/dotnet-presentations/ContosoCrafts/blob/master/src/Components/ProductList.razor) and they don't use a database to store data (they use a static JSON file), so I've had to go out and find a solution that might actually work in the real world.
Your [FromBody] attribute is saying that the body should be parseable as an integer, but the body is actually something like {"postid":"13"}.
The body is an object with a property named postId. So try defining that as your DTO:
public sealed class AddPostLikePostDto
{
public int PostId { get; set; }
}
...
public async Task<string> AddPostLike([FromBody] AddPostLikePostDto dto)
If you just want to post an Integer data, just change like below:
data: JSON.stringify(postid)
but the success function did not work.
That is because the counter does not increase, you can use likecount++ or likecount = likecount + 1 to make it work.
Another problem seems to be with the response from the controller which never tells people they must be logged in if the user is not signed in like it should.
That is because the else clause in your backend is a correct response for the ajax, you can simply throw an exception like:throw new Exception("User Must Be Logged in to Like");
Another way, you can change your code like below:
[HttpPost]
[Route("AddPostLike")]
public async Task<IActionResult> AddPostLike([FromBody] int postid)
{
if (xxx)
{
return Ok("liked");
}
else
{
//return $"User Must Be Logged in to Like";
return BadRequest("User Must Be Logged in to Like");
}
}
A whole working demo:
<label id="idlabel">1</label>
<label id="like-post-count" >4</label>
<input id="like-post" type="button" value="Post"/>
#section Scripts
{
<script>
$(document).ready(function () {
$('#like-post').on('click', function () {
var postid = parseInt($('#idlabel').text());
$.ajax({
url: '/api/Likes/AddPostLike/',
type: 'POST',
dataType: 'text',
data: JSON.stringify(postid), //change here....
contentType: 'application/json',
success: function () {
var likecount = parseInt($('#like-post-count').text());
likecount++;
$('#like-post-count').text(likecount);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("responseText=" + XMLHttpRequest.responseText + "\n textStatus=" + textStatus + "\n errorThrown=" + errorThrown);
}
});
});
});
</script>
}
Controller:
[HttpPost]
[Route("AddPostLike")]
public async Task<string> AddPostLike([FromBody] int postid)
{
if (xxxx)
{
return $"liked";
}
else
{
//return $"User Must Be Logged in to Like";
throw new Exception("User Must Be Logged in to Like");
}
}
In addition to fixing the way data can be sending to controller ( #StephenCleary already offered one of the possible ways), you have to fix a success function too by adding a result parameter
success: function (result) {
var likecount = parseInt(result).text());
likecount + 1;
$('#like-post-count').text(likecount);
},

ajax call status is 200 but it is not successfull

I working on mvc asp.net project. I call my controller function with ajax, the call status is 200 but it is not successful, and goes to error section.
service:
public async Task<IEnumerable<TeamDto>> GetAllTeamsList()
{
var teams = await _teamRepository.GetAll().Include(u => u.Users).ThenInclude(m => m.User).ToListAsync();
return ObjectMapper.Map<IEnumerable<TeamDto>>(teams);
}
Controller:
public async Task<IEnumerable<TeamDto>> GetTeams()
{
var teams = await _teamAppService.GetAllTeamsList();
return teams;
}
js file:
$.ajax(
{
type: "GET",
url: "/App/Team/GetTeams",
success: function (data) {
///
},
error: function (data) { console.log("it went bad " + JSON.stringify(data)); }
});
Error:
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
this is what I get when copy the url in the browser:
{"result":[{"tenantId":1,"name":"admin
team","users":[{"tenantId":1,"userId":2,"teamId":58,"user":{"profilePictureId":null,"shouldChangePasswordOnNextLogin":false,"signInTokenExpireTimeUtc":null,"signInToken":null,"googleAuthenticatorKey":null,"pin":"1234","hourlyRate":0.00,"payrollId":"","warehouseId":1,"tandaUser":null,"normalizedUserName":"ADMIN","normalizedEmailAddress":"ADMIN#DEFAULTTENANT.COM","concurrencyStamp":"bd7ee91e-587b-4ae2-bc97-be2ce7d7789b","tokens":null,"deleterUser":null,"creatorUser":null,"lastModifierUser":null,"authenticationSource":null,"userName":"admin","tenantId":1,"emailAddress":"admin#defaulttenant.com","name":"admin","surname":"admin","fullName":"admin
admin","password":"AQAAAAEAACcQAAAAENfcSE+zBppFKVxKUynGBiy4WZgDU3C3gbbWnQUdEyBb5J/S0uLkcqk+2MwM0DXxjw==","emailConfirmationCode":null,"passwordResetCode":null,"lockoutEndDateUtc":null,"accessFailedCount":1,"isLockoutEnabled":true,"phoneNumber":"","isPhoneNumberConfirmed":false,"securityStamp":"07a4d582-7233-3fbc-f3f7-39f015ee388b","isTwoFactorEnabled":false,"logins":null,"roles":null,"claims":null,"permissions":null,"settings":null,"isEmailConfirmed":true,"isActive":true,"isDeleted":false,"deleterUserId":null,"deletionTime":null,"lastModificationTime":"2020-09-30T02:54:34.402372Z","lastModifierUserId":null,"creationTime":"2019-09-05T23:27:47.8514365Z","creatorUserId":null,"id":2},"team":{"tenantId":1,"name":"admin
team","users":[
Open up the developer tools and look at the URL it is trying to request. Normally in the context of the application, you don't have the /App defined. In fact, you can use ASP.NET MVC Url helper to get the action method, to make sure the path is correct:
$.ajax({
type: "GET",
url: "#Url.Action("GetTeams", "Team")",
Also, normally you would return data via JSON from the controller like:
public async Task<IEnumerable<TeamDto>> GetTeams()
{
var teams = await _teamAppService.GetAllTeamsList();
return Json(teams, JsonRequestBehavior.AllowGet);
}
And maybe that would make a difference, using Json() from the asp.net mvc controller. Note AllowGet ensures that GET requests on an action returning JSON works, otherwise it will be blocked and return an error.

Can't send data with $http.post in Ionic Framework

I'm trying make an application with Ionic framework which can take and send data to MS SQL server. For this I am using web api. I have no problem with taking data but something wrong with send new datas. Here is my ionic code :
angular.module('starter.controllers',[])
.controller('CheckListCtrl', function($scope, ChecklistService, $ionicPopup) {
function addCheck(){
ChecklistService.addCheck()
}
.factory('ChecklistService', ['$http', function ($scope, $http) {
var urlBase = 'http://localhost:56401/api';
var CityService = {};
CityService.addCheck = function(){
var url = urlBase + "/TBLCHECKLISTs"
var checkdata = {
AKTIF : true,
SIL : false,
KAYITTARIHI : Date.now(),
KULLANICIID : 3,
BASLIK : "Onur",
TAMAMLANDI : false,
TAMAMLANMATARIHI : null,
GUN : 1
}
var request = $http({
method: 'POST',
url: url,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: checkdata
});
return request;
}
return CityService;
}]);
And here is my web api:
[HttpPost]
[ResponseType(typeof(TBLCHECKLIST))]
public IHttpActionResult PostTBLCHECKLIST(TBLCHECKLIST tBLCHECKLIST)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
tBLCHECKLIST.KAYITTARIHI = DateTime.Now;
db.TBLCHECKLISTs.Add(tBLCHECKLIST);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = tBLCHECKLIST.TABLEID }, tBLCHECKLIST);
}
When i try to send i get this exception:
After, I realize that I take that exception because my checkdata is never come to web api. I don't know why.
These are not the datas I send:
I have tried different versions of post request but nothing. When I try to send data with PostMan, it works and I can insert data to my database. But why I can't do it with my application? Can anybody help me?
I think this should be the problem:
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
Try this:
return $http.post(url, checkdata);
And in your API:
[HttpPost]
[ResponseType(typeof(TBLCHECKLIST))]
public IHttpActionResult PostTBLCHECKLIST([FromBody]TBLCHECKLIST tBLCHECKLIST)
{
//code here
}
Also, make sure your checkdata properties match the ones in your TBLCHECKLIST c# type.

web api returned content missing when posting in angularjs

I am trying to post data and return some content posting to a .net web api using angularjs
here is my web api
[HttpPost]
public HttpResponseMessage Post()
{
return new HttpResponseMessage()
{
Content = new StringContent(
"<strong>test</strong>",
Encoding.UTF8,
"text/html"
)
};
}
and here is my post from my client
$http({
url: 'my happy url',
method: "POST",
data: objData,
headers: {
'Content-Type': 'text/html'
}
}).success(function (data, status, headers, config) {
console.log(headers());
}).error(function (data, status, headers, config) {
console.log("error");
});
my problem is I do not get any data returned. I am sure I am missing something simple. Thanks for your help.
in the above code the data parameter is empty and I would expect to find the string "test" in the data parameter.
Instead of HttpResponseMessage, can you try to use IHttpActionResult? Sample code as below.
public IHttpActionResult PostSample()
{
return Content(HttpStatusCode.OK, "Test String");
}

Asp.Net web-api ajax call 404 method not found

I am using Asp.net mvc4 web-api.
I got an error 404 method not found, i am calling DelteMenu Method using jquery ajax. I am pssing argument Using data : of Jquery ajax. if i am passing Model parameter it is working fine but for other parameters like Guid, String throwing exception : 404 method nod found.please let me know if you have any idea why it is throwing 404 error.
//api method
public HttpResponseMessage DeleteMenu(Guid MenuId)
{
try
{
MenuDA.DeleteMenu(objMenuModel.MenuId);
return this.Request.CreateResponse(
HttpStatusCode.OK,
new
{
Success = true
});
}
catch (Exception ex)
{
ErrorLogDA.LogException(ex);
throw ex;
}
}
//Jquery ajax function
function performdeletemenu(MenuId)
{
if (confirm('Are you sure you want to delete this menu?'))
{
$.ajax({
type: 'DELETE',
url: '/api/MenuWebApi/DeleteMenu/',
data: "MenuId=" + MenuId,
success: function (data)
{
if (data.Success == true)
{
GetMenuList();
}
},
error: function (xhr, textStatus, errorThrown)
{
//window.location = JsErrorAction;
},
dataType: "json",
headers:
{
'RequestVerificationToken': JsTokenHeaderValue
}
});
}
return false;
}
Regards
The data setting does not work when sending a HTTP DELETE through jQuery's ajax function. You will have to pass the Guid in the url itself: url: '/api/MenuWebApi/DeleteMenu?MenuId=' + MenuId.
What I do find strange is that a 404 is returned, instead of a 400 Bad Request.
Add this line in RouteConfig.cs as below
routes.IgnoreRoute("{*x}", new { x = #".*\.asmx(/.*)?" });
I tool reference from https://stackoverflow.com/a/17058251/2318354
It will work definately in case of 404 Error Method not found.

Resources