Ajax Post (Model binded) passing null to the controller - javascript

I am making an AJAX POST request to the controller (ASP.NET Core MVC), yet the value for the parameter is coming through as null. I tried several solutions given on StackOverflow. But, I couldn't correct it. Please help.
My view collects class fees information. There may have more than one payment.
$(function () {
$('#sendSlip').click(function (e) {
e.preventDefault();
let fees = new Array(); //To store payment info
let tb = $('#feesTable:eq(0) tbody');
//Collecting info of each payment
tb.find("tr").each(function () {
let row = $(this);
let fee = {};
if (row.find('input:checkbox:first').is(':checked')) {
fee.ClassId = row.find("TD").eq(0).html();
fee.FeeId = row.find("TD").eq(1).html();
fee.Amount = row.find(".fee").html();
fee.Month = row.find(".month").html();
fees.push(fee);
}
});
//Arranging data to send to controller
var data = {
fees: fees,
Bank: $(".bank").val(),
PaidAmount : $(".amount").val(),
PaidDate : $(".date").val()
};
console.log(data);
$.ajax({
type: 'POST',
url: '#Url.Action("StudentPayment_Create", "StudentPayment")',
contentType: "application/json",
headers: { 'RequestVerificationToken': gettoken() },
data: //{ data: JSON.stringify(data) },
JSON.stringify(data) ,
})
});
});
Model
public class StudentPaymentSlipVM
{
public StudentPaymentPaidClassVM fees { get; set; }
public string Bank { get; set; }
public DateTime PaidDate { get; set; }
public int PaidAmount { get; set; }
}
Controller
public ActionResult StudentPayment_Create([FromBody] List<StudentPaymentSlipVM> data)
{
---
}
Object details at runtime

From your attached screenshot for data to be passed to the controller, the data's structure was unmatched with the data model the controller expected.
Assume the data structure for the front-end is correct.
Controller should expect that the received data is a StudentPaymentSlipVM object. While in the StudentPaymentSlipVM object, the fees is a StudentPaymentPaidClassVM array.
Model
public class StudentPaymentSlipVM
{
public List<StudentPaymentPaidClassVM> fees { get; set; }
public string Bank { get; set; }
public DateTime PaidDate { get; set; }
public int PaidAmount { get; set; }
}
Controller
public ActionResult StudentPayment_Create([FromBody] StudentPaymentSlipVM data)
{
}
While from your JQuery part, make sure that your data object to be passed to API must be matched with the data type as your model in the back-end.
var data = {
fees: fees,
Bank: $(".bank").val(),
PaidAmount : parseInt($(".amount").val()),
PaidDate : $(".date").val()
};

I tried to pass my data to controller by binding to a ViewModel (StudentPaymentSlipVM) which has all required definitions. But I couldn't do it. So I changed the way and pass my object to Controller as following way now it is working.
And also I would like to thanks Yong Shun.
Changed the JQuery code
$.ajax({
type: 'POST',
url: '#Url.Action("action", "controller")',
headers: { 'RequestVerificationToken': gettoken() },
data: dataObj,
})
I changed the Controller
[HttpPost]
public ActionResult StudentPayment_Create(List<StudentPaymentPaidClassVM> Fees, string Bank, decimal PaidAmount, DateTime PaidDate)
{
.....
}

Related

ASP Net Core3.1 AJAX Post Sending NULL to Controller

It has been 3 days am trying to sending the [POST] form data using ajax, Javascript & HTML into MVC controller but getting null.
Please find the controller and ajax code please help me on this also let me know is it possible or not to send the data from ajax to mvc controller?
I am beginner .....thanks in advance.
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> CreateNewBug([FromBody] BugTrackerRequest bugTrackerRequest)
{
// BugTrackerResponse bugTrackerResponse = null;
if (ModelState.IsValid)
{
var Request = await _projectDetails.CreateNewBug(bugTrackerRequest);
if (Request > 0)
{
BugTrackerResponse bugTrackerResponse = new BugTrackerResponse();
bugTrackerResponse.Issuccess = true;
// return Ok(new {Messgage="Data save successfully in the DB"});
return Ok();
}
}
return StatusCode(500, new { Message = "Something went wrong" });
// return bugTrackerResponse;
//return StatusCode();
}
public class BugTrackerRequest:APIResponse
{
public int TicketId { get; set; }
public string ProjectName { get; set; }
public string ProjectDescription { get; set; }
public string Title { get; set; }
public string Status { get; set; }
public string AssignTo { get; set; }
public string AssignFrom { get; set; }
public byte[] Attachment { get; set; }
public string Impact { get; set; }
public string Platform { get; set; }
public string Priority { get; set; }
public string BugType { get; set; }
public DateTime CreatedDate { get; set; }
}
}
function savedetails() {
let saveuidetails = new BugdetailRequestclass();
saveuidetails.ProjectName = $('#projectprojectname').val();
saveuidetails.ProjectDescription = $('#description').val();
saveuidetails.Title = $('#title').val();
saveuidetails.Status = $('#status').val();
saveuidetails.AssignTo = $('#assignto').val();
saveuidetails.AssignFrom = $('#assignfrom').val();
saveuidetails.Attachment = $('#Attfileupload').val;
saveuidetails.Impact = $('#Priority').val();
saveuidetails.Platform = $('#platform').val();
saveuidetails.Priority = $('#Priority').val();
saveuidetails.BugType = $('bugtype').val();
saveuidetails.CreatedDate = $('#currentdate').val();
$.ajax({
type: 'POST',
url: '/TicketController1/CreateNewBugFromBody',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(saveuidetails),
success: function (data) {
console.log('success', data);
},
error: function () { alert('Exeption:'); }
});
}
Your URL in POST is wrong, please change
/TicketController1/CreateNewBugFromBody
to
/TicketController1/CreateNewBug
Please verify that your controller class is named TicketController1.
To start with, please comment out
saveuidetails.Attachment = $('#Attfileupload').val;
in js and
public DateTime CreatedDate { get; set; }
public byte[] Attachment { get; set; }
When controller method is working, you may look at the Attachment which will be a challenge.
You basically have three choices (https://stackoverflow.com/a/4083908/14072498):
Base64 encode the file, at the expense of increasing the data size by
around 33%, and add processing overhead in both the server and the client
for encoding/decoding.
Send the file first in a multipart/form-data POST, and return an ID to the
client. The client then sends the metadata with the ID, and the server re-
associates the file and the metadata.
Send the metadata first, and return an ID to the client. The
client then sends the file with the ID, and the server re-associates the
file and the metadata.
Else, your code shown here looks OK to me, and there is no problem using a MVC controller for this. If controller contains API methods only, you should extend from ControllerBase instead of Controller, and annotate controller with [ApiController]. The latter invokes model validation automatically.
When implementing new API end-points, always start with something simple and verify with e.g. Postman that you can reach your new end-point.
url: '/TicketController1/CreateNewBugFromBody',
public async Task<IActionResult> CreateNewBug([FromBody] BugTrackerRequest bugTrackerRequest)
First, check your request URL and the action method, it seems that you are submitting the form to the CreateNewBugFromBody method, instead of CreateNewBug action method. So try to change your code as below (I assume your controller name is TicketController1 and you want to submit to the CreateNewBug method):
$.ajax({
type: 'POST',
url: '/TicketController1/CreateNewBug',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(saveuidetails),
success: function (data) {
console.log('success', data);
},
error: function () { alert('Exeption:'); }
});
Second, please check your JQuery object BugdetailRequestclass, in the action method, it receives a BugTrackerRequest object. So, try to modify your code as below (please change the request url and the jquery selector value to yours):
function savedetails() {
var saveuidetails = {}; //define a object
saveuidetails.ProjectName = $('#ProjectName').val();
saveuidetails.ProjectDescription = $('#Description').val();
saveuidetails.Title = $('#Title').val();
saveuidetails.Status = $('#Status').val();
saveuidetails.AssignTo = $('#AssignTo').val();
saveuidetails.AssignFrom = $('#AssignFrom').val();
saveuidetails.Attachment = $('#Attfileupload').val;
saveuidetails.Impact = $('#Priority').val();
saveuidetails.Platform = $('#Platform').val();
saveuidetails.Priority = $('#Priority').val();
saveuidetails.BugType = $('#BugType').val();
saveuidetails.CreatedDate = $('#CreatedDate').val();
$.ajax({
type: 'POST',
url: '/Home/CreateNewBug',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(saveuidetails),
success: function (data) {
console.log('success', data);
},
error: function () { alert('Exeption:'); }
});
}
Besides, you could add a breakpoint in the JavaScript resource and CreateNewBug action method, and check whether you could get the correct data before/after send Ajax request.
Screenshot as below:
JavaScript debug screenshot (using F12 developer tools)
Action method debug screenshot:

Having trouble passing complex model to controller through ajax call

I'm trying to update my model whenever a button is clicked. When I log the data I'm sending in the razor file to the console, the data is all there. However, when the controller method is called, the model is empty.
My onclick method:
function addCoupon() {
var code = document.getElementById("coupon-entry").value;
$.ajax({ // Validate coupon first. This is working.
method: "post",
url: `/cart/validate-coupon/` + code,
contentType: "application/json; charset=utf-8"
}).done(result => {
if (result.success) {
var model = #Html.Raw(Json.Serialize(Model));
console.log(model); // Countries and CheckoutData are correct here
$.ajax({
method: "post",
url: `/cart/add-coupon/` + code,
contentType: "application/json; charset=utf-8",
data: model
}).done(result => {
console.log("It worked");
});
}
});
}
My model:
public bool IsPos { get; set; }
public List<CountryDto> Countries { get; set; }
public CheckoutData CheckoutData { get; set; }
public string Payment ProcessorError { get; set; }
public bool DisplayRequiredErrors { get; set; }
public List<string> ValidationErrors { get; set; } = new List<string>();
public PaymentInformationModel PaymentInformation { get; set; } = new PaymentInformationModel();
public bool UseSavedCard { get; set; }
My controller:
[HttpPost("add-coupon/{code}")]
public async Task<IActionResult> AddCouponAsync(string code, CheckoutModel model)
{
// Countries and CheckoutData are null here
}
There were several similar questions posted on here, but they all either had simple models, or had solutions that didn't work for me when I tried them.
Thanks!
You should try changing it to this (otherwise it isn't valid javascript):
(Notice that it needs to be encapsulated in '')
var model = '#Html.Raw(Json.Serialize(Model))';

Autofill Textbox based on DropDownList

MVC 4 Changing multiple display fields based on DropDownListFor selection
I'm trying to follow the above example but I think I'm having problems either with my javascript or my controller.
JavaScript in View
$('#InstitutionDDL').change(function () {
var institutionID = $(this).val();
$.ajax({
type: 'POST',
url: '/Compendia/FillImplementationInfo?InstitutionID=' + institutionID,
dataType: 'json',
contentType: 'application/json',
data: { InstitutionID: institutionID },
success: function (ret) {
$('#RegionImplementedField').val(ret.implementedRegion);
$('#ProvinceImplementedField').val(ret.implementedProvince);
$('#DistrictImplementedField').val(ret.implementedDistrict);
$('#LocationImplementedField').val(ret.implementedLocation);
},
error: function (ex) {
}
});
return false;
});
Controller Action
[HttpGet]
public JsonResult FillImplementationInfo(int InstitutionID)
{
var ret = (from e in db.Institutions
where e.ID == InstitutionID
select new
{
implementedRegion = e.Province.Region.RegionName,
implementedProvince = e.Province.ProvinceName,
implementedDistrict = e.District,
implementedLocation = e.InstitutionAdress
}).FirstOrDefault();
return Json(ret, JsonRequestBehavior.AllowGet);
}
Source of DropDownList in View
<div class="form-group">
#Html.LabelFor(model => model.InstitutionID, "Institution", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.InstitutionID, new SelectList(""), "--Select Institution--", htmlAttributes: new { #class = "form-control", #id ="InstitutionDDL" })
#Html.ValidationMessageFor(model => model.InstitutionID, "", new { #class = "text-danger" })
</div>
</div>
^from which after selecting, I want to pull all related data from connected tables using InstitutionID and put it in their respective textboxes known with IDs ending in #ImplementedField
Debugging Results
After selecting an option from the DropDownList, my script could capture the institutionID up to $.ajax({ data: { InstitutionID: institutionID }. However, it skips the success: function(ret) entirely and goes straight to return false; . Furthermore, the error that is being returned is 500 Internal Server Error, and based on the debugger, ret is being treated everywhere as undefined. I've already tried modifying my controller and/or javascript multiple times but with no success. If I'm having a problem with my linq statement, I'm also posting here my Models. Apologies in advance for the long post, I really have no idea where I went wrong.
Models
public class Compendium
{
public int ID { get; set; }
public int InstitutionID { get; set; }
public string RegionImplemented { get; set; }
public string ProvinceImplemented { get; set; }
public string DistrictImplemented { get; set; }
public string LocationImplemented { get; set; }
public virtual Institution Institution { get; set; }
}
public class Institution
{
public int ID { get; set; }
public int ProvinceID { get; set; }
public District? District { get; set; } //enum
public virtual ICollection<Compendium> Compendia { get; set; }
public virtual Province Province { get; set; }
}
public class Province
{
public int ID { get; set; }
public int RegionID { get; set; }
public virtual Region Region { get; set; }
public string ProvinceName { get; set; }
public virtual ICollection<Institution> Institutions { get; set; }
}
First, this URL pattern with query string is not correct to initiate an AJAX call:
url: '/Compendia/FillImplementationInfo?InstitutionID=' + institutionID,
You need to change int Url.Action or simply remove query string on it:
url: '/Compendia/FillImplementationInfo',
// or
url: '#Url.Action("FillImplementationInfo", "Compendia")'
and then remove contentType: 'application/json' since the return type already declared as JSON with dataType: 'json'.
Second, as a general convention, the HTTP method used by jQuery AJAX call & the controller action method must be match to send the argument data successfully. In view side the AJAX call sent as POST method:
$.ajax({
type: 'POST',
...
});
But the action method uses HTTP GET, which causes AJAX call cannot reach the action method since it only accepts GET request:
[HttpGet]
public JsonResult FillImplementationInfo(int InstitutionID)
{
...
}
Note that you can use either GET or POST method with AJAX call, but ensure both of them are matched each other. Here is an example below:
View (jQuery AJAX)
$.ajax({
type: 'GET', // ensure this HTTP method same as used by controller action method
...
});
Controller
[HttpGet]
public JsonResult FillImplementationInfo(int InstitutionID)
{
...
}

Passing objects from Ajax to C# WebApi

I’m still not fluent in calling WebAPI services. I succeed in simple items, but now my needs are getting complicated and things always fail.
I use MVC 5 for WebAPI, and call using regular jQuery functions.
My Model
Here I manage appointments of patients in a clinic. I use the following model for Patient and Appointment entities:
public class Patient
{
// Personal data
public int Id { get; set; }
public string Name { get; set; }
}
public class Appointment
{
public int Id { get; set; }
public DateTime Date { get; set; } // date only
public int Order { get; set; }
public string PatientName { get; set; }
// Parent data
public Patient Patient { get; set; }
public int PatientId { get; set; }
public Organization Organization { get; set; }
public int OrganizationId { get; set; }
}
My DTOs
public class AppointmentDto
{
public int Id { get; set; }
public int Order { get; set; }
public string PatientName { get; set; }
public PatientDto Patient { get; set; }
}
public class PatientDto
{
public string Name { get; set; }
}
First Case
I want to set new ordering for appointments within a day. I send list of JSON objects with IDs of appointments to be changed and their respective orders.
The service action:
[HttpPost]
public IHttpActionResult UpdateOrder(List<AppointmentDto> dto)
{
_unitOfWork.Appointments.UpdateOrder(dto);
_unitOfWork.Complete();
return Ok();
}
The service call:
// Handler methods
var rearrangeAppointments = function (event, ui) {
// Json object to pass
var orderedAppointments = [];
// Looping through appointments
var i = 0;
$("#sortable").children().each(function () {
// Set new order
i++;
orderedAppointments.push({ "Id": this.getAttribute("data-id").toString(), "Order": i.toString() });
});
// Call service
appointmentsService.updateOrder(orderedAppointments, done, fail);
};
var updateOrder = function (orderedAppointmens, done, fail) {
$.ajax({
url: "/api/appointments",
method: "POST",
data: orderedAppointmens,
dataType: "Json"
})
.done(done)
.fail(fail);
};
The service is called successfully, but the passed list is always empty. I debugged the JavaScript code and the array of JSON object is built successfully. Also debugged the MVC code and tested the service Postman, it works very fine. This drop is passing the list of objects from client to server.
Second Case
This time it’s a get call. I want to get list if appointments if a specific date to update the view.
The service action:
public IEnumerable<AppointmentDto> GetAppointments(DateTime date)
{
var organizationId = _unitOfWork.ApplicationUsers.GetOrganizationId(User.Identity.GetUserId());
var appointments = _unitOfWork.Appointments.GetAppointments(date, organizationId);
return appointments.Select(Mapper.Map<Appointment, AppointmentDto>);
}
The service call:
$("#datepicker").datepicker({
// TODO: Refactor to pettern
onSelect: function (dateText, inst) {
var selectedDate = $(this).datepicker('getDate');
var date = JSON.stringify(selectedDate);
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: "json",
url: "/api/appointments",
data: date,
success: function (appointments) {
alert("Service call succeeded!")
alert(appointments.length);
}
})
.fail(function () {
alert("Failure!");
});
}
});
When I test the code without passing a date (hardcoding the date into the action method) it works very well. When I add the date to the parameters (in the action method and the AJAX call), it does not work at all.
I've tried many links and articles from here and other sources with no success, like below:
Pass a datetime from javascript to c# (Controller)
Pass Date Values from Ajax Call to MVC
and more that I could not add here.
I think my major problem in the two cases in passing data.
What am I missing here?
for the second case : Do you sent date-time ?? if you do that the URL may contains ":" (12:00) & this type of character is denied by the HTTP request
After some tracing with one friend, and reviewing some other articles and questions...
First Case (passing list of objects)
I reformatted the array of objects using JSON.stringify(orderedAppointmens), and added contentType: 'application/json; charset=utf-8' to the service call. The code should look like below:
var updateOrder = function (orderedAppointmens, done, fail) {
orderedAppointmens = JSON.stringify(orderedAppointmens);
$.ajax({
url: "/api/appointments",
method: "POST",
data: orderedAppointmens,
contentType: 'application/json; charset=utf-8',
dataType: "Json"
})
.done(done)
.fail(fail);
};
Second Case (passing a Date object)
I removed the Json dataType from the service call and concatenated the date to the URL like below:
$.ajax({
url: "/api/appointments?date=" + selectedDate.toISOString(),
type: "GET",
success: function (appointments) {
alert(appointments.length);
}
});
This worked fine and the Date object is passed to the DateTime object in backend successfully.

Posting JSON with a array object to MVC controller

My ViewModel is:
public class CFUViewModel
{
public int RID { get; set; }
public int Order { get; set; }
public List<VCItem> VItems{ get; set; }
}
where VCItem is:
public class VCItem
{
public string Name{ get; set; }
public string Category { get; set; }
}
In my view, I am collecting the data from form elements. Thus,
$('#submit').click(function () {
console.log(gatherData());
transmitData(gatherData());
});
function gatherData() {
var vc = dataObject.getVCItems();
//This is a knockout function that gives an array of VCItems
var data = new Object();
data.RID = $('#rid').val();
data.VItems = vc;
return data;
};
function transmitData(dataToSend) {
$.ajax({
url: '../CFUDashboard/ReceiveData',
type: 'post',
dataType : 'json',
success: function (data) {
alert('success');
},
data: dataToSend
});
};
In the controller, I have:
[HttpPost]
public ActionResult ReceiveData(CFUViewModel viewModel)
{
//...
}
The problem is, though RID is ok, VItems list is not serialized. I suspect, the reason is, the array attached to the JS object is actually string (array wrapped in quotes). This is confirmed by the console.log(gatherData())
It is outputted as:
VItems : "[{"Name":"OPV3","Category":"FUGY"},{"Name":"OPV7","Category":"FUGX"}]"
What is the reason for not getting the list serialized? What am I missing?

Categories

Resources