JSON stringify not serialising ? Bind issue - c#

In the controller WidgetConfigurationRequestVM request object
is returning 3 properties (lists) as null
jurisidctions
tags
workareas
I have binded this in the view and I am sure there is data set. They have same method types IEnumerable, why companyid binding and the other properties not binding in WidgetConfigurationRequestVM? Thank you for help!
API Controller:
[Route("api/track/v1/taxibriefing")]
public async Task<TaxiContainerModel> Post([FromBody] WidgetConfigurationRequestVM request)
{
request.Jurisidctions/tags/workareas = null?
request.companyId = exists
}
JS:
taxiBriefingButton.click(function (e) {
e.preventDefault();
var widgets = taxiConfigurationContainer.serialize();
var workAreaRefs = $(this).data("workarearefs");
var jurisdictions = $(this).data("jurisdictions");
var tags = $(this).data("tags");
var preset = $(this).data("preset");
createPdf($(this).data('companyid'), widgets, $('#notes').val(), workAreaRefs, jurisdictions, tags);
});
JS create PDF button:
function createPdf(companyId, widgets, notes, workAreaRefs, jurisdictions, tags) {
var doc = new PDFDocument({
bufferPages: true,
size: [842, 595]
});
window.dispatchEvent(GeneratingTaxiBriefingEvent);
var xhr = new XMLHttpRequest();
xhr.open('GET', '/taxiFonts/Roboto-Light.ttf', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function (e) {
if (this.status == 200) {
doc.registerFont('Roboto', xhr.response);
$.ajax({
type: 'POST',
url: '/api/track/v1/taxibriefing',
contentType : 'application/json',
data: JSON.stringify({ CompanyId: companyId, Notes: notes, Configuration: widgets, Workareas: workAreaRefs, Jurisdictions: jurisdictions, Tags: tags }),
dataType: 'json',
success: function (result) { GeneratePDF(doc, result); }
});
}
};
xhr.send();
}
View:
#model Areas.Track.Models.TrackVM
<button id="taxi-briefing" class="btn btn-danger" data-preset="#Model.Filter.DatePreset" data-workarearefs="#Model.Filter.WorkareaRefs" data-jurisdictions="#Model.Filter.JurisdictionRefs" data-tags="#Model.Filter.TagsRefs" data-companyid="#Model.Filter.FirmRefs.First()">Create PDF</button>
Viewmodel:
public class WidgetConfigurationRequestVM
{
public int CompanyId { get; set; }
public string Notes { get; set; }
public IEnumerable<WidgetConfigurationVM> Configuration { get; set; }
public IEnumerable<int> Workareas { get; set; }
public IEnumerable<int> Jurisdictions { get; set; }
public IEnumerable<int> Tags { get; set; }
}

Related

JSON.stringify Passing Into Razor-Page As Null

I have a asp.net core razor-page where I am trying to read the data off of a table and pass it into a my controller so that I can process changes made in the table. I've checked other similar questions on this site like this one: MVC model is null when posting json in ASP.Net Core
but I keep getting a null value in the razor-page. I'm posting the relevant code below. If there is something else that you need to see please let me know.
Ajax Call Below:
//--------------------------------------------------------------------
// Load Up An Array and Pass the Data To The Razor Page
//--------------------------------------------------------------------
$('#UpdateScoresButton').click(function () {
// Store Data in an Array
var enteredScores = new Array();
// Loops through whole table
$("#table tbody tr").each(function () {
// Grabs Each Row
var row = $(this);
var score = {};
score.DeputyID = row.find("td").eq(0).html();
score.DivisionID = row.find("td").eq(1).html();
score.QuarterID = row.find("td").eq(2).html();
score.PrimaryModelID = row.find("td").eq(3).html();
score.SecondaryModelID = row.find("td").eq(4).html();
score.ShotgunModelID = row.find("td").eq(5).html();
score.RifleModelID = row.find("td").eq(6).html();
score.PrimaryFirstScoreID = row.find("td").eq(7).html();
score.PrimarySecondScoreID = row.find("td").eq(8).html();
score.PrimaryThirdScoreID = row.find("td").eq(9).html();
score.SecondaryScoreID = row.find("td").eq(10).html();
score.ShotgunScoreID = row.find("td").eq(11).html();
score.RifleScoreID = row.find("td").eq(12).html();
enteredScores.push(score);
});
$.ajax(
{
url: '/EnterScores/Enter_Shooter_Scores?handler=InsertUpdateAndReloadData',
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
type: 'POST',
dataType: 'application/json; charset=utf-8',
data: JSON.stringify(enteredScores),
success: function (result) {
if (result.pass != undefined) {
document.forms[0].submit();
}
},
error: function (result, exception) {
console.log(result);
// Your error handling logic here..
},
});
});
Here is the razor-page code:
public JsonResult OnPostInsertUpdateAndReloadData([FromBody] List<EnteredScores> enteredScores)
{
var test = enteredScores;
return new JsonResult(new { pass = "Pass" }); ;
}
My EnteredScores Class :
public class EnteredScores
{
public int DeputyID { get; set; }
public int DivisionID { get; set; }
public int QuarterID { get; set; }
public int PrimaryModelID { get; set; }
public int SecondaryModelID { get; set; }
public int ShotgunModelID { get; set; }
public int RifleModelID { get; set; }
public int PrimaryFirstScoreID { get; set; }
public int PrimarySecondScoreID { get; set; }
public int PrimaryThirdScoreID { get; set; }
public int SecondaryScoreID { get; set; }
public int ShotgunScoreID { get; set; }
public int RifleScoreID { get; set; }
}
Since the properties in EnteredScores are int type.You need to pass int type data to handler.Try to change
score.DeputyID = row.find("td").eq(0).html();
score.DivisionID = row.find("td").eq(1).html();
score.QuarterID = row.find("td").eq(2).html();
score.PrimaryModelID = row.find("td").eq(3).html();
score.SecondaryModelID = row.find("td").eq(4).html();
score.ShotgunModelID = row.find("td").eq(5).html();
score.RifleModelID = row.find("td").eq(6).html();
score.PrimaryFirstScoreID = row.find("td").eq(7).html();
score.PrimarySecondScoreID = row.find("td").eq(8).html();
score.PrimaryThirdScoreID = row.find("td").eq(9).html();
score.SecondaryScoreID = row.find("td").eq(10).html();
score.ShotgunScoreID = row.find("td").eq(11).html();
score.RifleScoreID = row.find("td").eq(12).html();
to
score.DeputyID = parseInt(row.find("td").eq(0).html());
score.DivisionID = parseInt(row.find("td").eq(1).html());
score.QuarterID = parseInt(row.find("td").eq(2).html());
score.PrimaryModelID = parseInt(row.find("td").eq(3).html());
score.SecondaryModelID = parseInt(row.find("td").eq(4).html());
score.ShotgunModelID = parseInt(row.find("td").eq(5).html());
score.RifleModelID = parseInt(row.find("td").eq(6).html());
score.PrimaryFirstScoreID = parseInt(row.find("td").eq(7).html());
score.PrimarySecondScoreID = parseInt(row.find("td").eq(8).html());
score.PrimaryThirdScoreID = parseInt(row.find("td").eq(9).html());
score.SecondaryScoreID = parseInt(row.find("td").eq(10).html());
score.ShotgunScoreID = parseInt(row.find("td").eq(11).html());
score.RifleScoreID = parseInt(row.find("td").eq(12).html());
And since you passed data is json type,you need to add contentType: "application/json", to your ajax like this:
$.ajax(
{
url: '/EnterScores/Enter_Shooter_Scores?handler=InsertUpdateAndReloadData',
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
type: 'POST',
contentType: "application/json",
dataType: 'application/json; charset=utf-8',
data: JSON.stringify(enteredScores),
success: function (result) {
if (result.pass != undefined) {
document.forms[0].submit();
}
},
error: function (result, exception) {
console.log(result);
// Your error handling logic here..
},
});
result:
Your issue is likely due to model binding failing. Looking over this code, the first issue I'd address is the difference been the Javascript object names [that you're passing up to your C#/MVC action] and the "EnteredScores" model/class properties. The easiest refactor would be to edit your Javascript code like so:
score.DeputyID = row.find("td").eq(0).html();
score.DivisionID = row.find("td").eq(1).html();
score.QuarterID = row.find("td").eq(2).html();
etc.
Change the above [your orginal code] to the below [my refactor of that code], just make sure you update all fields so they match.
DeputyID = row.find("td").eq(0).html();
DivisionID = row.find("td").eq(1).html();
QuarterID = row.find("td").eq(2).html();
etc.

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.

List of Objects sent to the controller from jQuery are always null

So this is my class that of my model:
[Table("Question", Schema = "trs")]
public class Question
{
[Key]
public int QuestionId { get; set; }
[ForeignKey("TranType")]
[Required]
public int TranTypeId { get; set; }
[ForeignKey("Company")]
[Required]
public int CompanyId { get; set; }
[Required]
[StringLength(300)]
public string Text { get; set; }
[Required]
public bool IsActive { get; set; }
[ForeignKey("QuestionType")]
public int QTypeId { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedUserId { get; set; }
public DateTime UpdateDate { get; set; }
public string UpdateUserId { get; set; }
public Company Company { get; set; }
public QuestionType QuestionType { get; set; }
public TranType TranType { get; set; }
public ICollection<Answer> Answer { get; set; }
public ICollection<Grading> Grading { get; set; }
}
This is my controller action, for now it is doing nothing because I need to get the values first which are the problem:
[Authorize(Roles = "Admin")]
public class QuestionController : Controller
{
readonly IQuestionRepository questionRepository;
readonly ICompanyRepository companyRepository;
public QuestionController(IQuestionRepository qRepository, ICompanyRepository cpnRepository)
{
questionRepository = qRepository;
companyRepository = cpnRepository;
}
[HttpPost]
public ActionResult Save([FromBody] List<Question> qView)
{
return View(qView);
}
}
Now I have tried also:
[HttpPost]
public ActionResult Save(List<Question> qView)
{
return View(qView);
}
In both cases I have problems; in the first option (with [FromBody]) qView is null; and in option 2 (without [FromBody]) qView is not null but the List is empty (Count == 0).
Here is the Code to generate the JSON data:
function Send()
{
var qCounter = parseInt($('#quesCounter').val());
var listQuestion = [];
var qView = {};
qView.Questions = listQuestion;
for (i = 1; i <= qCounter; i++)
{
var question = {};
var listAnswer = [];
question.Answers = listAnswer;
var anCounter = parseInt($('#qtCounter' + i).val());
var qText = $('#qtText' + i).val();
var qType = $('#qType' + i).val();
question["Text"] = qText;
question["QTypeId"] = qType;
for (j = 1; j <= anCounter; j++)
{
var answer = {};
var aText = $('#anText' + i.toString() + j.toString()).val();
var aCorrect = "";
if ($('#anCorrect' + i.toString() + j.toString()).prop('checked')) {
aCorrect = "yes";
}
else {
aCorrect = "no";
}
answer["Text"] = aText;
answer["IsCorrect"] = aCorrect;
question.Answers.push(answer);
}
qView.Questions.push(question);
}
$.ajax({
type: "POST",
url: "Save", // the method we are calling
contentType: "application/json",
data: JSON.stringify(qView),
//data: JSON.stringify({ 'qView': qView }),
dataType: "json",
success: function (result) {
alert('Yay! It worked!');
// Or if you are returning something
alert('I returned... ' + result.WhateverIsReturning);
},
error: function (result) {
alert('Oh no :(');
}
});
}
I have no clue what is wrong.
Please any idea where is my issue?
Hi guys so the issue was the way I was calling the the ajax method in the wrong way and some of the properties in the mapping on the client side; I fixed by running the method this way:
function Send()
{
var qCounter = parseInt($('#quesCounter').val());
var listQuestion = [];
for (i = 1; i <= qCounter; i++)
{
var question = {};
var listAnswer = [];
question.Answer = listAnswer; //Second problem was here because I was calling here the array Answers when the List<Answer> property on the server side was called Answer.
var anCounter = parseInt($('#qtCounter' + i).val());
var qText = $('#qtText' + i).val();
var qType = $('#qType' + i).val();
question["Text"] = qText;
question["QTypeId"] = parseInt(qType);// first problem was here because the property on the Server side was integer and I was sending string.
for (j = 1; j <= anCounter; j++)
{
var answer = {};
var aText = $('#anText' + i.toString() + j.toString()).val();
var aCorrect = "";
if ($('#anCorrect' + i.toString() + j.toString()).prop('checked')) {
aCorrect = 1; //third problem was here because true/yes was not recognize so I had to change to 1/0;.
}
else {
aCorrect = 0; //same as above (third problem).
}
answer["Text"] = aText;
answer["IsCorrect"] = aCorrect;
question.Answer.push(answer);
}
listQuestion.push(question);
}
$.ajax({
type: "POST",
url: "Save", // the method we are calling
contentType: "application/json",
data: JSON.stringify(listQuestion),
success: function (result) {
alert('worked');
},
error: function (result) {
alert('Something failed');
}
});
}
You're setting the contentType to application/json and then you stringify your data before sent? You've just contradicted yourself.
You're basically saying: Server, I am sending you a JSON object. But then since you stringify the object, the Server will only see a string. That's why the server wouldn't match the data to your model.
My 2 cents
As long as the JavaScript object / JSON you construct on client-side matches the model you have in the parameter of your controller, you don't need to specify contentType and [FromBody] - to keep things simply. MVC is smart enough to do the binding for you. You don't even need to use lowercase in your C# model for the properties. You can even use true/false for boolean, as long as the matching property in C# model is defined as bool.
Don't use your domain/data model on your view/page. Create a separate model (called view model) and put only what you need to display/use on the view/page there. You don't want to expose what you have in the database to the whole world.
Use camelCase for variables and functions please in JavaScript. The way you declared your function Send(), qView.Questions = and question.Answers.push(answer); just made me crazy :p.
Code Example
$.ajax({
type: 'POST',
// Use HTML helper to generate the link instead of hardcode.
// HTML helper will take care the host, port, and more for you.
url: '#Url.Action("save", "question", new { area = "" })',
// You usually don't need to specify the contentType.
// The default 'application/x-www-form-urlencoded' works well for
// JSON objects.
//contentType: "application/json",
// You don't need to stringify the data
data: { qView: qView },
//data: JSON.stringify({ 'qView': qView }),
dataType: "json",
success: function (result) {
alert('Yay! It worked!');
// Or if you are returning something
alert('I returned... ' + result.WhateverIsReturning);
},
error: function (result) {
alert('Oh no :(');
}
})
// I would use .done() here instead of success and error() but
// this is just personal taste.
;

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.

tryupdatemodel does not work through ajaxcall?

i am trying to post my model to the server through an ajax call. Unfortunately the Model is not updated?
<script src="../../Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<form id="ajaxForm" action="">
<div>
name:<%= Html.TextBoxFor(model => model.number) %>
</div>
<%--hidden vars--%>
<input type="hidden" id="Hidden1" />
<%= Html.Hidden("myModel", Model.Serialize())%>
</form>
<button id="submitbutton">
save
</button>
<script type="text/javascript">
$(document).ready(function () {
$("#submitbutton").click(function () {
var FormData = $("#ajaxForm").serialize();
$.ajax({
type: 'POST',
url: "/Home/SaveAjax",
data: { inputdata: $("#myModel").val() },
datatype: 'JSON'
});
})
});
</script>
[HttpPost]
public JsonResult SaveAjax(string inputdata)
{
MyModel myModel = (inputdata.DeSerialize() ?? TempData["myModel"] ?? new MyModel()) as MyModel;
//TryUpdateModel does not update my model??
TryUpdateModel(myModel);
TempData["myModel"] = myModel;
return Json(new { resultaat = "finished" });
}
[Serializable]
public class MyModel
{
//[Required]
public string name { get; set; }
public bool flag { get; set; }
public int number { get; set; }
public string address { get; set; }
public string abn { get; set; }
public string postalcode { get; set; }
}
public static class Extensions
{
public static string Serialize(this object myobject)
{
var sw = new StringWriter();
var formatter = new LosFormatter();
formatter.Serialize(sw, myobject);
return sw.ToString();
}
public static object DeSerialize(this string mystring)
{
if (string.IsNullOrEmpty(mystring))
return null;
var formatter = new LosFormatter();
MyModel mym = (MyModel)formatter.Deserialize(mystring);
return mym;
}
}
In your AJAX request you are sending only the value of the hidden field:
data: { inputdata: $("#myModel").val() }
so you cannot expect to get any other values on your server than this hidden field. If you want to POST the entire form contents use the formData variable that you declared in your code but left unused:
$('#submitbutton').click(function () {
var formData = $('#ajaxForm').serialize();
$.ajax({
type: 'POST',
url: '/Home/SaveAjax',
data: formData,
dataType: 'json'
});
});

Categories