Model is null from Json object - c#

So when I set the javascript ReminderModel object properties this will work and my controller will receive the object if I set LeadId and StaffId to 1, but as soon as I turn them into strings the controller receives a null object.
I'm not sure what's going on, it might be a problem with the quotes?
My view code
var ReminderModel = {
"LeadId": "#Model.Id",
"StaffId": "1a53c286-b17e-4afd-9ccb-684fd1a92f7b",
"Subject": "Call Back",
"Time": "iTime",
"Date": "iDate"
};
$.ajax({
url: "#Url.Action("SetReminder","Appointment")",
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(ReminderModel),
success: function (valid) {
if (valid) {
//show that id is valid
} else {
//show that id is not valid
}
}
});
My controller Method
[HttpPost]
public async Task<ActionResult> SetReminder([FromBody] ReminderViewModel viewModel)
{
using (var db = new LeadCoreDbContext())
{
DateTime dt = DateTime.MinValue;
DateTime.TryParse($"{viewModel.Date} {viewModel.Time}", out dt);
if (dt == DateTime.MinValue)
throw new Exception("Failed to set reminder");
var reminder = new Reminder
{
Deleted = false,
LeadId = viewModel.LeadId,
Subject = viewModel.Subject,
TimeToRemind = dt,
StaffId = viewModel.StaffId
};
db.Reminder.Add(reminder);
await db.SaveChangesAsync();
}
return Content("received");
}
Here is the model
public class ReminderViewModel
{
public int Id { get; set; }
public int LeadId { get; set; }
public int StaffId { get; set; }
public string Date { get; set; }
public string Time { get; set; }
public string Subject { get; set; }
}

Related

Not posting data to an action with MVC(HTTP 415)

I'm looking to send the following fields to a MVC action
public class AddProductViewModel
{
public string ProductId { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
public double Price { get; set; }
public bool Enabled { get; set; }
public List<CategorySelectModel> Categories { get; set; } = new List<CategorySelectModel>();
public List<IFormFile> Photos { get; set; } = new List<IFormFile>();
}
CategorySelectModel:
public string CategoryId { get; set; }
public string CategoryName { get; set; }
and I haved used what i believe represents the actual json data...but I dont get why it isnt posting the data to the action
here is the js code where I have serialized the data and send to the controller
function SubmitProducts(element)
{
element.preventDefault();
let ulContainer = document.getElementById("dropDownAndSel").getElementsByTagName('ul')[0];
var Categories = [];
let x = document.getElementById("dropDownCategories");
for (let i = 0; i < x.children.length; i++) {
if (x.options[i].selected) {
let CategoryName = x.options[i].innerHTML;
let CategoryId = x.children[i].value;
let dropdownItems = { CategoryId, CategoryName };
if (!Categories.includes(dropdownItems)) {
Categories.push(dropdownItems);
}
}
}
let pId = document.getElementById('pId').value;
let ProductId = pId;
let ProductName = document.getElementById('ProductName').value;
if (!ProductName || ProductName.length ==0) {
alert('ProdutName cannot be null or empty');
return;
}
let priceStr = document.getElementById('productPriceId').value;
if (!priceStr || priceStr.length == 0) {
alert('Price cant be empty')
return;
}
let Price = parseFloat(priceStr);
let QuantityStr = document.getElementById('qtyNum').value;
if (!QuantityStr || QuantityStr.length==0) {
alert('Quantity cant be empty');
return;
}
let Quantity = parseInt(QuantityStr);
var formData = new FormData();
let filesContainer = document.getElementById('photoProduct_0');
for (let i = 0; i < filesContainer.files.length; i++) {
formData.append('model.Photos', filesContainer.files[i], filesContainer.files[i].name);
}
formData.set('model.ProductId', ProductId);
formData.set('model.ProductName', ProductName);
formData.set('model.Price', Price);
formData.set('model.Quantity', Quantity);
formData.set('model.Categories', JSON.stringify(Categories));
$.ajax({
url: '/' + 'Product' + '/' + 'AddProduct',
type: 'POST',
contentType: false,
processData: false,
data: formData,
success: console.log('success'),
});
}
Here is the action signature:
[HttpPost]
public async Task<IActionResult> AddProduct([FromBody] AddProductViewModel model)
Code above post FormData data. Therefore, the AddProductViewModel parameter should be bound using form-data in the request body:
[HttpPost]
public async Task<IActionResult> AddProduct([FromForm] AddProductViewModel model)
Reference to the following post: ASP.NET Core form POST results in a HTTP 415 Unsupported Media Type response

"Bad request" error when passing DateTime to REST API

I am sending data to HTTP post API. But everytime I try to call the API, I get error code: 400, Bad request message.
Here is my API code:
[Route("InsUpPlayer")]
[HttpPost]
public async Task<object> InsUpPlayer([FromForm] Players player)
{
try
{
//Some code here
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
And my repository code:
public async Task<string> PlayerInsUpPost(Player player1)
{
var SendResponse = "false";
try
{
var RequestUrl = baseUrl + "Master/InsUpPlayer";
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(RequestUrl);
using (var player = new MultipartFormDataContent())
{
if (player1.ProfileImageFile != null)
{
string objimgFileBase64 = "";
ByteArrayContent fileContent;
using (var ms = new MemoryStream())
{
player1.ProfileImageFile.CopyTo(ms);
var fileBytes = ms.ToArray();
objimgFileBase64 = Convert.ToBase64String(fileBytes);
}
byte[] bytes = Convert.FromBase64String(objimgFileBase64);
fileContent = new ByteArrayContent(bytes);
player.Add(fileContent, "ProfileImageFile", string.Format("{0}", player1.ProfileImageFile.FileName));
}
if (player1.DetailImageFile != null)
{
string objimgFileBase64 = "";
ByteArrayContent fileContent;
using (var ms = new MemoryStream())
{
player1.DetailImageFile.CopyTo(ms);
var fileBytes = ms.ToArray();
objimgFileBase64 = Convert.ToBase64String(fileBytes);
}
byte[] bytes = Convert.FromBase64String(objimgFileBase64);
fileContent = new ByteArrayContent(bytes);
player.Add(fileContent, "DetailImageFile", string.Format("{0}", player1.DetailImageFile.FileName));
}
player.Add(new StringContent(player1.playerId.ToString()), "playerId");
player.Add(new StringContent(player1.FirstName), "FirstName");
player.Add(new StringContent(player1.LastName), "LastName");
player.Add(new StringContent(player1.DOB.ToString()), "DOB");
player.Add(new StringContent(player1.Nationality.ToString()), "Nationality");
player.Add(new StringContent(player1.BirthState.ToString()), "BirthState");
player.Add(new StringContent(player1.JerseyNo.ToString()), "JerseyNo");
player.Add(new StringContent(player1.Postion.ToString()), "Postion");
player.Add(new StringContent(player1.Biography), "Biography");
player.Add(new StringContent(player1.isActive.ToString()), "isActive");
player.Add(new StringContent(player1.isPublish.ToString()), "isPublish");
player.Add(new StringContent(player1.UserType.ToString()), "UserType");
HttpResponseMessage objResponse = await httpClient.PostAsync(RequestUrl, player);
if (objResponse.IsSuccessStatusCode && (int)objResponse.StatusCode == 200)
{
var serResponse = objResponse.ContentAsType<ResultModel>();
//SendResponse = serResponse.result;
SendResponse = "true";
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception Occured");
throw;
}
return SendResponse;
}
The Player class is like this:
public class Player
{
public long playerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
public int Nationality { get; set; }
public int BirthState { get; set; }
public int JerseyNo { get; set; }
public int Postion { get; set; }
public string Biography { get; set; }
public bool isActive { get; set; }
public bool isPublish { get; set; }
public int UserType { get; set; }
public IFormFile ProfileImageFile { get; set; }
public IFormFile DetailImageFile { get; set; }
public string ProfileImage { get; set; }
public string DetailImage { get; set; }
}
Update: Here is my JQuery code: The DOB here is correct, but I realized just now that it is not getting passed correctly to the controller.
$("#PublishPlayer").click(function () {
debugger;
var value = $('#CreatePlayerForm').valid();
var url = '/Admin/PlayerInsUpPost';
var day = $('#Day').val();
var month = $('#Month').val();
var year = $('#Year').val();
var DOB = new Date(year, month, day);
var fdata = new FormData();
fdata.append("playerId", $('#playerId').val());
fdata.append("FirstName", $('#FirstName').val());
fdata.append("LastName", $('#LastName').val());
fdata.append("DOB", DOB);
fdata.append("Nationality", $('#Nationality').val());
fdata.append("BirthState", $('#BirthState').val());
fdata.append("JerseyNo", $('#JerseyNo').val());
fdata.append("Position", $('#Position').val());
fdata.append("Biography", $('#Biography').val());
fdata.append('ProfileImageFile', $('#ProfileImageFile')[0].files[0]);
fdata.append('DetailImageFile', $('#ProfileImageFile')[0].files[0]);
if (value == true) {
$.ajax({
url: url,
datatype: "json",
accept: {
javascript: 'application/javascript'
},
type: "POST",
cache: false,
processData: false,
contentType: false,
data: fdata,
success: function (result) {
if (result == "true") {
alert('Player added successfully.');
window.location.href = "/Admin/PlayerList";
} else if (result == "false") {
alert('Failed to update, please try later.');
}
},
error: function () {
alert('Something went wrong');
}
});
}
else {
//$('.playeradd').removeClass('show');
//$('.playeradd').addClass('hide');
return false;
}
//event.stopPropagation();
});
The DOB in JQuery before calling Ajax is : Wed Sep 12 2001 00:00:00 GMT+0530 (India Standard Time) {}
When passed to controller it is: {01-01-0001 12:00:AM}
If I comment DOB in API and in the frontend, everything works fine. But I need to send DOB to API and I can't change the datatype of DOB in API. How do I fix this error?
When passing the data into the ajax request convert it to ISO string. Dotnet understands that. So do something like this:
fdata.append("DOB", DOB.toISOString());
I suppose it is some problem with ASP.NET deserialization of DateTime (I'm not sure tho). I have run into similar problem of sending dates before and my solution was instead of sending DateTime struct, I send number of ticks (which you can get from DateTime object) as long variable.
DateTime BOD = DateTime.Now; // You may fill your DateTime object with your own data
long BODticks = BOD.Ticks;
And then on the server side you can easily recreate date time like this:
DateTime myDate = new DateTime(BODticks);
And then in order to use it you can modify your player class as follows:
public class Player
{
public long playerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public long DOBTicks { get; set; }
public DateTime DOB { get => new DateTime(DOBTicks); set => DOBTicks = value.Ticks; }
public int Nationality { get; set; }
public int BirthState { get; set; }
public int JerseyNo { get; set; }
public int Postion { get; set; }
public string Biography { get; set; }
public bool isActive { get; set; }
public bool isPublish { get; set; }
public int UserType { get; set; }
public IFormFile ProfileImageFile { get; set; }
public IFormFile DetailImageFile { get; set; }
public string ProfileImage { get; set; }
public string DetailImage { get; set; }
}
I'm sure someone could find a better solution though and that's assuming this one actually works and I understood your problem right.
The new serializer in .net core > 3.0 is strict when parsing date formats (note that the default has changed from newtonsoft json). They have to be in ISO8601 format, i.e. YYYY-MM-DD. If you are passing something that isn't in ISO8601 forms you have to write a custom formatter.
public class DateTimeJsonConverter : JsonConverter<DateTime>
{
public override DateTime Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
DateTime.ParseExact(reader.GetString(),
"<YOUR FORMAT HERE>", CultureInfo.InvariantCulture);
public override void Write(
Utf8JsonWriter writer,
DateTime dateTimeValue,
JsonSerializerOptions options) =>
writer.WriteStringValue(dateTimeValue.ToString(
"<YOUR FORMAT HERE>", CultureInfo.InvariantCulture));
}
The code above is an example of a custom formatter.
Read further details here (https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to#sample-basic-converter) in how to create a custom formatter for your input.

Ajax POST not hitting controller break point

My ajax POST request does'nt seem to be hitting my contoller, although i have used other Ajax post requests in my application this one doesnt seem to be working. My first throught was the datatypes within the model were not strings but other than that i can't seem to figure out why it isnt working.
Model
public class AppointmentViewModel
{
public List<DTO.Appointment> appointments { get; set; }
public DTO.Appointment appointment { get; set; }
public int AppointmentId_Input { get; set; }
public string AppointmentTitle_Input { get; set; }
public string AppointmentName_Input { get; set; }
public DateTime AppointmentStartTime_Input { get; set; }
public DateTime AppointmentEndTime_Input { get; set; }
public int AppointmentType_Input { get; set; }
public List<DTO.AppointmentType> appointmentTypes { get; set; }
}
Controller:
public ActionResult AddAppointment(Models.AppointmentViewModel avm)
{
BLL.FTSPManager fm = new BLL.FTSPManager();
DTO.Appointment a = new DTO.Appointment()
{
Id = avm.AppointmentId_Input,
Info = avm.AppointmentTitle_Input,
Name = avm.AppointmentName_Input,
StartTime = avm.AppointmentStartTime_Input,
EndTime = avm.AppointmentEndTime_Input,
type = new DTO.AppointmentType()
{
Id = avm.AppointmentType_Input
}
};
return Json(avm);
}
Ajax Request:
$('#btnAdd').click(function () {
var id, title, name, startTime, endTime, AppointmentType
id = $('#hdnAppointmentId').val();
title = $('#txtTitle').val();
name = $('#txtName').val();
startTime = $('#txtStartDate').val();
endTime = $('#txtEndDate').val();
AppointmentType = $('#drptype').val();
var JsonData = {
AppointmentId_Input: id,
AppointmentTitle_Input: title,
AppointmentName_Input: name,
AppointmentStartTime_Input: startTime,
AppointmentEndTime_Input: endTime,
AppointmentType_Input: AppointmentType
};
$.ajax({
type: "POST",
url: '#Url.Action("AddAppointment", "Admin")',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(JsonData),
dataType: "json",
success: function (data) {
return false;
}
});
})
You can use a FormData function. I can give for you a working example:
Html code(button, without other "input" tags:
<div class="form-group">
<button type="button" id="dataSend">DataSend</button>
</div>
Javascript code:
$("#dataSend").on('click', function () {
var formData = new FormData();
formData.append('Image', $('#file')[0].files[0]);
formData.append('Title', document.getElementById('Title').value);
formData.append('Description', document.getElementById('Description').value);
formData.append('Topic', document.getElementById('Topic').value);
formData.append('AdditionalFields', JSON.stringify(obsFields));
$.ajax({
contentType: false,
processData: false,
type: 'POST',
url: '/Collection/Create',
data: formData,
success: function () {
console.log("success.");
},
error: function () {
console.log("error.");
},
});});
C# code(controller):
[HttpPost]
public async Task<IActionResult> Create(DataForm AllData)
{
return RedirectToAction("Action-method", "Controller");
}
C# code(model):
public class DataForm
{
public string Title { get; set; }
public string Description { get; set; }
[EnumDataType(typeof(Topic))]
public Topic? Topic { get; set; }
public IFormFile Image { get; set; }
public string AdditionalFields { get; set; }
}
Field "AdditionalFields" is a son converted and in Controller it deserialized to 'List list'.
I'm waiting for your questions.

How to send a model which consist generic list from ajax call in mvc C#

I am trying to call the controller from ajax and sending model data which consist some list of data inside it. I am getting the count correct for them but inside the list properties are coming null.
Controller:
public JsonResult InsertorUpdate(IncidentEdit incident)
{
try
{
SrvincidentDtls.TicketNo = incident.TicketNo;
SrvincidentDtls.Priority = incident.Priority;
SrvincidentDtls.Status = incident.Status;
SrvincidentDtls.Title = incident.Title;
SrvincidentDtls.IsActive = incident.IsActive;
List<Comments> lstComm = new List<Comments>();
if(incident.CommentList!=null )
{
foreach (var comm in incident.CommentList)
{
Comments Comm = new Comments();
Comm.Comment = comm.Comments;
Comm.AddedBy = comm.AddedBy;
Comm.AddedBy_ID = comm.AddedBy_ID;
Comm.CreatedDate = comm.CreatedDate;
lstComm.Add(Comm);
}
}
SrvincidentDtls.Comments = lstComm.ToArray();
SrvincidentDtls.Description = incident.Description;
var result=proxyService.InsertorUpdateIncidentDetails(SrvincidentDtls);
return Json(new { success = true, jvalue = result }, JsonRequestBehavior.AllowGet);
}
catch(Exception ex)
{
throw ex;
}
}
Model:
public class IncidentEdit
{
public string Title { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
public string Status { get; set; }
public string Priority { get; set; }
public List<IncidentComments> CommentList { get; set; }
}
Generic Class:
public class IncidentComments
{
public string Comments { get; set; }
public string AddedBy { get; set; }
public string AddedBy_ID { get; set; }
public DateTime CreatedDate { get; set; }
}
Ajax call:
function InsertOrUpdate(){
incidentDetails = {
Title: $("#txtTitle").val(),
Description: $("#txtDescription").val(),
Priority: $('#selPriority option:selected').val(),
Status: $('#selStatus option:selected').val(),
IsActive: 1,
CreatedDate :$('#spncrtdDt').text(),
CommentList:PopulateCommentList()
};
$.ajax({
type: "Get", //HTTP POST Method
url: insertORupdatUrl, // Controller/View
data: {incident:incidentDetails},
contentType: "application/json; charset=utf-8",
success: function (data) {
}
});
}
js function:
function PopulateCommentList() {
var CommentList = [];
var dtTable = $('#dvCommentTbl').DataTable();
for (var i = 0; i < 10; i++) {
if (dtTable.row(i).data() != "" && dtTable.row(i).data() != null && dtTable.row(i).data() != undefined) {
CommentList.push({
Comments: dtTable.row(i).data()[1],
AddedBy: dtTable.row(i).data()[2],
AddedBy_ID: dtTable.row(i).data()[0],
CreatedDate: dtTable.row(i).data()[3]
});
}
}
return CommentList;
}
the count for comment list is coming fine but the data like Added_By,comments,Created Dtae all coming null.
Plz help.
You can take a variable like
var commlist=PopulateCommentList();
then populate it in your model json:
incidentDetails = {
Title: $("#txtTitle").val(),
Description: $("#txtDescription").val(),
Priority: $('#selPriority option:selected').val(),
Status: $('#selStatus option:selected').val(),
IsActive: 1,
CreatedDate :$('#spncrtdDt').text(),
CommentList:commlist
};
it will work as it work for me.

How to properly use javascript deserialization to convert a json string to a complex object?

I have the following json object that is available in my .ashx handler (var items=):
{"Coverages":{"PersonID":10,"DetCode":"","Reimbursement":"","Deductible":"","MaximumPerAnnum":"","MaximumPerVisit":"","MaximumPerVisits":"","SvcCode":""},"CoverageCombinedMaximums":{"PersonID":10,"DetCode":["AAAAA","BBBBB","CCCCC"],"MaximumPerAnnum":""}}
public void ProcessRequest (HttpContext context) {
bool isSuccessful = true;
var items = context.Request.Params["items"];
if (isSuccessful)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
AdditionalCoveragesPackage package = ser.Deserialize<AdditionalCoveragesPackage>(items);
}
else
{
SendErrorMessage(context);
return;
}
}
Here is the structure of the class I'm trying to deserialize:
public class AdditionalCoverage
{
public int PersonID { get; set; }
public string DetCode { get; set; }
public decimal? Reimbursement { get; set; }
public decimal? Deductible { get; set; }
public decimal? MaximumPerAnnum { get; set; }
public decimal? MaximumPerVisit { get; set; }
public int? MaximumPerVisits { get; set; }
public string SvcCode { get; set; }
public AdditionalCoverage()
{
}
}
public class AdditionalCoverageCombinedMaximum
{
public int PersonID { get; set; }
public string SvcCode { get; set; }
public decimal? MaximumPerAnnum { get; set; }
public List<string> DetCode { get; set; }
public AdditionalCoverageCombinedMaximum()
{
}
}
public class AdditionalCoveragesPackage
{
public List<AdditionalCoverage> Coverages { get; set; }
public List<AdditionalCoverageCombinedMaximum> CoverageCombinedMaximums { get; set; }
public AdditionalCoveragesPackage()
{
}
public AdditionalCoveragesPackage(AdditionalCoverage coverage, AdditionalCoverageCombinedMaximum maximum)
{
List<AdditionalCoverage> coverages = new List<AdditionalCoverage>();
coverages.Add(coverage);
Coverages = coverages;
List<AdditionalCoverageCombinedMaximum> maximums = new List<AdditionalCoverageCombinedMaximum>();
maximums.Add(maximum);
CoverageCombinedMaximums = maximums;
}
public AdditionalCoveragesPackage(List<AdditionalCoverage> coverages, List<AdditionalCoverageCombinedMaximum> maximums)
{
Coverages = coverages;
CoverageCombinedMaximums = maximums;
}
}
Edit: Here are my client side methods that need correction:
function saveCoverageDetails() {
var handler = "HttpHandlers/UpdateAdditionalCoverageDetailsHandler.ashx";
var coverages = { PersonID: personId, DetCode: "", Reimbursement: "", Deductible: "", MaximumPerAnnum: "", MaximumPerVisit: "", MaximumPerVisits: "", SvcCode: "" };
var maximums = { PersonID: personId, DetCode: ["ACUPUN", "PODIAT", "OSTEOP"], MaximumPerAnnum: "" };
var obj = { Coverages: coverages, CoverageCombinedMaximums: maximums };
var data = ({ items: JSON.stringify(obj) });
callHandler(handler, data, saveSuccessful, failure);
}
function callHandler(handler, obj, onSuccess, onFail) {
$.ajax({
type: "POST",
url: handler,
data: obj,
dataType: "json",
success: onSuccess,
fail: onFail
});
}
When I'm using the javascript serializer it does return my AdditionalCoveragesPackage object - however - both of the properties: Coverages and CombinedMaximums are empty. How to get this to properly deserialize my json string?
In your JSON string Coverages and CoverageCombinedMaximums are simple objects, not arrays, so:
public class AdditionalCoveragesPackage
{
public AdditionalCoverage Coverages { get; set; }
public AdditionalCoverageCombinedMaximum CoverageCombinedMaximums { get; set; }
}
Also in your example JSON:
"MaximumPerAnnum":""
so make sure you define the corresponding property as a nullable decimal:
public decimal? MaximumPerAnnum { get; set; }
or the deserializer will blow.
The Coverages and CombinedMaximums properties in your JSON are objects, not arrays.
You should change those to arrays or change your C# class to not use List<T>s.
SLAKS and Darin Dimitrov both helped a ton. Ends up it works if I compose my JSON string as below (I had the array structured incorrectly and was passing empty strings instead of zeros for my numeric types). Here's the corrected client code:
var handler = "HttpHandlers/UpdateAdditionalCoverageDetailsHandler.ashx";
var coverages = [{ PersonID: personId, DetCode: "", Reimbursement: 0, Deductible: 0, MaximumPerAnnum: 0, MaximumPerVisit: 0, MaximumPerVisits: 0, SvcCode: "" }, { PersonID: personId, DetCode: "CHIROP", Reimbursement: 0, Deductible: 0, MaximumPerAnnum: 0, MaximumPerVisit: 0, MaximumPerVisits: 0, SvcCode: ""}];
var maximums = [{ PersonID: personId, DetCode: ["ACUPUN", "PODIAT", "OSTEOP"], MaximumPerAnnum: 0 }, { PersonID: personId, DetCode: ["ACUPUN", "PODIAT", "OSTEOP"], MaximumPerAnnum: 0}];
var obj = { Coverages: coverages, CoverageCombinedMaximums: maximums };
var data = ({ items: JSON.stringify(obj) });
callHandler(handler, data, saveSuccessful, failure);

Categories