AJAX & Web Api Post Method - How does it work? - c#

I am trying to write to my database using AJAX / Jquery and c#. Whenever I pass the parameter in to the C# code it shows as null. I am using the default template that visual studio generates when creating a controller class. Any help would be appreciated!
NOte: This is a rest service that I am trying to call. (A regular ASP website... not MVC. Also, the GET Rest api works perfectly.)
Jquery/AJAX:
var dataJSON = { "name": "test" }
$('#testPostMethod').bind("click", GeneralPost);
function GeneralPost() {
$.ajax({
type: 'POST',
url: '../api/NewRecipe',
data:JSON.stringify(dataJSON),
contentType: 'application/json; charset=utf-8',
dataType: 'json'
});
}
C#
//If I remove the [FromBody] Tag then when I click the button this method is never called.
public void Post([FromBody]string name)
{
}
EDIT:
I have adjusted my code slightly but am still encountering the same issue. To recap, It is loading the POST method, but it is passing in null.
C#
public class RecipeInformation
{
public string name { get; set; }
}
public void Post(RecipeInformation information)
{
}
AJAX:
var dataJSON = { information: { name: "test" } };
$('#testPostMethod').bind("click", GeneralPost);
console.log(dataJSON);
function GeneralPost() {
$.ajax({
type: 'POST',
url: '../api/NewRecipe',
data: dataJSON,
contentType: 'application/json; charset=utf-8',
});
}

For simple type, on server side:
public void Post([FromBody]string name)
{
}
on the client side, you just define if you want to send in json format:
var dataJSON = "test";
$('#testPostMethod').bind("click", GeneralPost);
function GeneralPost() {
$.ajax({
type: 'POST',
url: '/api/NewRecipe',
data: JSON.stringify(dataJSON),
contentType: 'application/json; charset=utf-8',
dataType: 'json'
});
}
If you want to make it work in complex type, from server side you should define:
public class RecipeInformation
{
public string name { get; set; }
}
public class ValuesController : ApiController
{
public void Post(RecipeInformation information)
{
}
}
And from client side:
var dataJSON = { name: "test" };
$('#testPostMethod').bind("click", GeneralPost);
function GeneralPost() {
$.ajax({
type: 'POST',
url: '/api/NewRecipe',
data: JSON.stringify(dataJSON),
contentType: 'application/json; charset=utf-8',
dataType: 'json'
});
}

You can try doing something like this and use the jquery param method
var postData = {
name : 'name'
}
$('#testPostMethod').bind("click", GeneralPost);
function GeneralPost() {
$.ajax({
type: 'POST',
url: '../api/NewRecipe',
data: $.param(postData,true),
contentType: 'application/json; charset=utf-8',
dataType: 'json'
});
}

I suppose that you are using ASP.NET WebAPI and it bind all simple types (int, bool, string, etc) from URL and all complex types from body. When you marked name with FromBody attribute then it bind it from request body instead of url mapping.
You can read more about ASP.NET WebAPI routing and parameter binding here:
On www.asp.net
On www.west-wind.com
and on MSDN

There's a piece you're missing is the data contract attributes
If you make a your class like:
[DataContract]
public class RecipeInformation
{
[DataMember]
public string name { get; set; }
}
These attributes are found in System.Runtime.Serialization, and the Json parser (Json.NET) uses them to (help) deserialize the model.

Binding in API controllers is a little on the strange side. I believe:
public void Post([FromBody]RecipeInformation information)
with
var dataJSON = { name: "test" };
should work, and will definitely work if you just pass it as form data.

I found the problem with help from Microsoft Docs
Use JS code as mentioned
$.post('api/updates/simple', { "": $('#status1').val() });
What I missed was adding empty property name, so what OP needs to do is{"":data:JSON.stringify(dataJSON)}, instead of data:JSON.stringify(dataJSON),

$("#updateuser").click(function ()
{
var id = $("#id").val();
var dataJSON = $("#username").val();
alert("" + dataJSON);
$.ajax({
url: 'http://localhost:44700/api/Home/' + id,
type: 'PUT',
data: JSON.stringify(dataJSON),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (data, textStatus, xhr) {
$.each(data, function (key, val) {
$("<li>" + val + "</li>").appendTo($("#names"));
})
},
error: function (xhr, textStatus, errorThrown) {
alert('Error in Operation');
}
})
})

Related

Unable to send json string from html form to web api controller

I have this web api in C#. When I submit the form, it doesn't reach this action method.
[HttpPost]
public void Post([FromBody] string jsonString)
{
}
When I submit the form, this is the output for stringifyObj in the console.log and I got 415 error code.
{"application_name":"1225848d-5941-4fac-bdff-7799b53d6fd0test1","asset_type":"1225848d-5941-4fac-bdff-7799b53d6fd1test2"}
and this is my front-end code.
$.ajax({
url: 'https://localhost:7273/WeatherForecast',
type: 'POST',
data: stringifyObj,
dataType: 'application/json',
success: function (response) {
debugger
console.log(response);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
debugger
console.log(XMLHttpRequest.responseText)
}
});
When I remove the [FromBody] at the Web Api action method, the error becomes {"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1","title":"One or more validation errors occurred.","status":400,"traceId":"00-1841751068f6545f081cd59195b65b0d-f07b55a84e3d8b29-00","errors":{"jsonString":["The jsonString field is required."]}}
Modify the Post action to expect to receive the request body of Model (object) type instead of string type.
[HttpPost]
public void Post([FromBody] Model model)
{
}
public class Model
{
[JsonProperty("application_name")]
public string ApplicationName { get; set; }
[JsonProperty("asset_type")]
public Guid AssetType { get; set; }
}
While in Ajax:
Add contentType: "application/json".
For dataType, should be "json" instead of "application/json".
$.ajax({
url: 'https://localhost:7273/WeatherForecast',
type: 'POST',
data: stringifyObj,
dataType: 'json',
contentType: "application/json;charset=utf-8",
success: function (response) {
debugger
console.log(response);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
debugger
console.log(XMLHttpRequest.responseText)
}
});

How to use model binder in .net core mvc with Ajax Post?

I'm new to .net core MVC and am trying to execute an Ajax post similar to .net framework MVC. I'm simply trying to POST a single int value to the controller action below. The Ajax call hits the controller, but the action parameter is always 0. I verified that the correct integer value is being sent in the Ajax request payload. What am I missing?
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult Ajax_GenerateSecretNum([FromBody]int lower)
{
return Json(new { success = true });
}
$.ajax({
url: '#Url.Action("Ajax_GenerateSecretNum", "Home")',
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: { lower: lower },
success: function (response) {
}
});
You could create a model (DTO) for the controller parameter and use JSON.stringify() on your data before posting to the controller.
$.ajax({
url: '#Url.Action("Ajax_GenerateSecretNum", "Home")',
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({ lower: lower }),
success: function (response) {
}
});
public class ModelDto
{
public int Lower { get; set; }
}
[HttpPost]
public IActionResult Ajax_GenerateSecretNum([FromBody]ModelDto model)
{
// model.Lower should contain your int
return Json(new { success = true });
}
$.ajax({
url: '#Url.Action("Ajax_GenerateSecretNum", "Home")',
type: 'POST',
data: { "lower": lower, "upper": upper },
success: function (response) {
}
});
Changing my jQuery ajax to the above sample solved the issue. I'm not sure why, but it looks like specifying the extra ajax parameters caused the values to fail model binding. After changing the ajax, I was also able to remove the [FromBody] attribute from the controller action.
You can do something like below:
$.ajax({
method: "POST",
data: { "Property1": "value1", "Property2": "value2"},
url: "#Url.Action("Ajax_GenerateSecretNum", "Home")",
success: function (data) {
//success login
},
error: function (data) {
alert('error' + data.status);
}
});
Controller will look like below:
[HttpPost]
public ActionResult Ajax_GenerateSecretNum(ModelClass modelClass)
{
//You logic will be here
}

Using Ajax to POST to ASP.Net controller - Data for Post incorrect

This is my DisputeController method stub:
[HttpPost]
public virtual ActionResult UpdateDisputeStatus(DisputeUdpateStatusModel model)
{//some code
Here is my Ajax call:
var url = '/dispute/UpdateDisputeStatus';
var disputeStatusObj = {
DisputeId: id,
DisputeStatusId: selectedValue
}
$.ajax({
url: url,
cache: false,
type: 'POST',
contentType: "application/json; charset=utf-8",
data: disputeStatusObj,
success: function (data) {
alert('Status Changed Successfully');
},
error: function (e) {
alert('Error: ' + e.status);
}
});
I know the routing works, as without using the data parameter the code enters my method (obviously without the model in parameters)
I have tried the following data formats:
data: {'DisputeId': DisputeId, 'StatusId': DisputeStatusId},
data: {disputeStatusObj},
data: JSON.Stringify(disputeStatusObj)
using controller methods:
[HttpPost]
public virtual ActionResult UpdateDisputeStatus(string disputeId, string statusId)
[HttpPost]
public virtual ActionResult UpdateDisputeStatus(modelname model)
None of which work. I get Not found errors or 500's.
Bearing in mind that I know the routing is correct, when I send the request with no data, so what am I missing here?
Am I declaring the controller incorrectly?
Verify your model that should be the same name as well as the data type because of while post the value from Jquery that values are not mapping with the property of the model.
#Mike I tried below code
public class DisputeUpdateStatusModel
{
public string DisputeId { get; set; }
public string DisputeStatusId { get; set; }
}
public class DisputeController : Controller
{
[HttpPost]
public virtual ActionResult UpdateDisputeStatus(DisputeUpdateStatusModel model)
{
return new ContentResult() { Content = "OK" };
}
}
script on view as:
<script type="text/javascript">
var disputeStatusObj = {}
disputeStatusObj.model = {
DisputeId: 1,
DisputeStatusId: 1
}
var url = '/dispute/UpdateDisputeStatus';
$.ajax({
url: url,
cache: false,
type: 'POST',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(disputeStatusObj),
success: function (data) {
alert('Status Changed Successfully');
},
error: function (e) {
alert('Error: ' + e.status);
}
});
</script>
Please see.
If this is not working, can you please show Model class?
thanks for all your input. My solution was a combination of the answers above.
I was unable to get my code to model bind, so I went back to basics.
I took out the contentType: "application/json; charset=utf-8", as suggested by Stephen Muecke, and ditched the model in my controller and replaced it with string disputeId, string statusId and as suggested by Er Pravin Suthar ensured the parametes were called the same thing. Also to note, the data section was sent as data: { disputeId: disputeId, statusId: statusId } with no quotes around the parameter names. So I ended up with:
var statusId = statusDropdown.value;
var disputeId = $("#disputeId").val();
$.ajax({
url: "/Dispute/UpdateDisputeStatus",
data: { disputeId: disputeId, statusId: statusId },
type: 'POST',
success: function (data) {
alert('Success');
},
error: function (e) {
alert('Status not changed' + e.responseText + ' : ' + e.status);
}
});
and the Controller structure is:
[HttpPost]
public virtual ActionResult UpdateDisputeStatus(string disputeId, string statusId)
Thanks Again for all your input!

when passing List<object> to a web api from jquery ajax, count is always ZERO

Web API is as below
[Route("saveFieldGroupForPayerRequestType")]
[HttpPost]
[ExcludeFromCodeCoverage]
public HttpResponseMessage SaveFieldGroupForPayerRequestType(List<PayerReqTypeFieldGroupMap> PayerReqTypeFieldGrpMapLists)
{
// Business Logic
}
The Model is as below
public class PayerReqTypeFieldGroupMap
{
public string TPSPayerId { get; set; }
public string RequestTypeCode { get; set; }
public string FieldGroupDesc { get; set; }
public bool IsEnabled { get; set; }
}
And the JQuery ajax call is as below
var PyrReqTypeFieldGrpMapsObject;
var PayerReqTypeFieldGrpMapLists=[];
PyrReqTypeFieldGrpMapsObject = {
TPSPayerId: "ddd",
RequestTypeCode : "ddd",
FieldGroupDesc : "ddd",
IsEnabled : true
};
PayerReqTypeFieldGrpMapLists.push(PyrReqTypeFieldGrpMapsObject);
$.ajax({
type: "POST",
datatype: 'application/json',
data: PayerReqTypeFieldGrpMapLists,
url: api + "saveFieldGroupForPayerRequestType",
success: function (data) {
},
error: function(XMLHttpRequest, textStatus, errorThrown){
}
}).done(function (e) {
});
The issue is , from my ajax call, the web api method gets hit, but the count is always 0.
what am i doing wrong?
Change you Ajax I test you need to stringify the data befor send to server, its working
$.ajax({
type: "POST",
contentType: 'application/json', // data type to send sever
dataType: 'json', // return type of data from server
data: JSON.stringify(PayerReqTypeFieldGrpMapLists),
url: 'http://localhost:8591/saveFieldGroupForPayerRequestType',
success: function (data) {
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
}).done(function (e) {
});
JSON.stringify():
A common use of JSON is to exchange data to/from a web server.When sending data to a web server, the data has to be a string.Convert a JavaScript object into a string with JSON.stringify()
You need to perform JSON.stringify of PayerReqTypeFieldGrpMapLists before hitting the web api.
data: JSON.stringify(PayerReqTypeFieldGrpMapLists)
And add contenttype as well.
contentType: 'application/json', // send the data type to server.
You need to set the contentType property value to "application/json". Also you need to stringify the data property value before sending the request.
$.ajax({
type: "POST",
data: JSON.stringify(PayerReqTypeFieldGrpMapLists),
contentType: "application/json",
url: api + "saveFieldGroupForPayerRequestType",
success: function (data) {},
error: function (XMLHttpRequest, textStatus, errorThrown) {}
}).done(function (e) {
});
Two more points
You should use done, fail and always instead of success, error and complete as pointed out in the documentation page. The last three callbacks are deprecated.
The datatype property should be dataType. Also the 'application/json' value is not allowed for this property. Documentation says:
The available data types are text, html, xml, json, jsonp, and script.
So, you could use this code:
$.ajax({
type: "POST",
url: api + "saveFieldGroupForPayerRequestType",
data: JSON.stringify(PayerReqTypeFieldGrpMapLists),
dataType: "json",
contentType: "application/json"
}).done(function (data, textStatus, jqXHR) {
}).fail(function (jqXHR, textStatus, errorThrown) {
}).always(function () {
});

How can send int and string with ajax to C#

I need post two argument to method in C#
[HttpPost]
public bool information([FromBody]int idInfromation,[FromBody] string information)
{
.....
return true;
}
with ajax, but my solution doesn´t work. Newtwork tab is showing:
POST http://-----/information/SubmitAnswer 500 (Internal Server Error)
I have this:
var source = { "idInfromation": 5, "information": "Wau" };
$.ajax({
url: "/information/",
type: "POST",
data: source,
dataType: "json",
contentType: "application/json",
success: function (data) {
alert("Complete");
}
});
Thank you for your advice.
You can't pass multiple [FormBody] parameters instead you have to pass parameter as an object.
for example, declare a DTO class
// DTO
public class InformationClass{
public int idInfromation{ get; set; }
public string Information{ get; set; }
}
[HttpPost]
public bool information(InformationDTO Info)
{
.....
return true;
}
to pass object using Json ajax:
// Initialize the object, before adding data to it.
// { } is declarative shorthand for new Object().
var Information= { };
Information.idInfromation= ParseInt($("txtId").val()); // your desired value
Information.Information= $("#Information").val();
// Create a data transfer object (DTO) with the proper structure.
var DTO = { 'Information' : Information};
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "InformationService.asmx/information", // or your specified url, if you don't want //use service like url: "/information/",
data: JSON.stringify(DTO),
dataType: "json"
});
Hope this helps,
Thanks.
You can't return two values with [FromBody]. Either create a DTO class or receive it as a JObject.

Categories