I have a javascript object on the client-side that has a SettingName and SettingValue properties.
Data Examples -
obj1.SettingName = "createdDate";
obj1.SettingValue = "10/07/2013";
obj2.SettingName = "arrayOfNames";
obj1.SettingValue = SomeArray; //An array of 5 strings
var settingsArray =new Array();
settingsArray[0] = obj1;
settingsArray[1] = obj2;
var settingsContainer = new Object;
settingsContainer.Settings = settingsArray;
ajax call -
$.ajax({
type: "POST",
url: "myURL",
data: { settings: JSON.stringify(settingsContainer)},
dataType: 'json',
success: function (data) {
//do something
}
});
Server side class -
public class Setting
{
public string SettingName { get; set; }
public object SettingValue { get; set; } //so this can hold multiple data types
}
public class SettingsContainer
{
public List<Setting> Settings { get; set;}
}
Controller action -
public ActionResult myURL(SettingsContainer settings) {
//Here, the value for SettingsContainer.Settings[1].SettingValue, which
should be Array[5] i.e. on the C# side, I expect to see Object[5],
is only {object}. I'm not sure what's going on.
Is my approach of handling this correct?
}
Any advise/help would be greatly appreciated. Thank-you!
On Server Side Method, you should use:
public ActionResult myURL(string settings) {
// deserialize the string to your object here;
}
But you have to re-design your classes because they aren't supported for the
javascript deserialization.
Try using 'SettingValue' as List<string> or something that you are expecting. You cannot deserialize to object, because the deserializer doesn't know what is the object.
try to set the data line in the ajax call as this
data: "{ 'settings':" + JSON.stringify(settingsContainer)+"}",
(and maybe you can avoid the SettingsContainer and just use a vector or a list of settings as method argument).
The following code should help you solve the issue.
Codebehind:
public class helper
{
public List<DoubleText> prop { get; set; }
}
public class DoubleText
{
public string data1 { get; set; }
public object data2 { get; set; }
}
[WebMethod]
public static string work(helper example)
{
// do stuff here
return "ok";
}
javascript/jquery
var example = new Object();
example.data1 = 'value';
example.data2 = ['value1', 'value2'];
var example2 = new Object();
example2.data1 = 'value';
example2.data2 = ['value1', 'value2'];
var vector = new Array();
vector[0] = example;
vector[1] = example2;
var ex = new Object();
ex.prop = vector;
var test = "{ 'example':" + JSON.stringify(ex) + "}";
$.ajax({
type: "POST",
url: '/work.aspx/work',
data: test,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
// stuff
},
error: function () { // other stuff}
});
Related
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.
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; }
}
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.
;
I want to send and work on multidimensional array in c# webmethod for that i have done some work.I dont want to run the ajax function in loop.
ASPX page code
var trip_id = $("#example1").val();
var user_id = $("#example2").val();
var facebookData = [];
facebookData[0] = trip_id;
facebookData[1] = user_id;
var fnds_list_array=[];
fnds_list_array=[["0678678678","XYZ","something.jpg"],["432524352","ABC","somethingABC.jpg"]]
var jsonData = JSON.stringify({ fb_Data: facebookData, fb_user_data: fnds_list_array });
$.ajax({
type: "POST",
url: "Ajax_function/myfunction.asmx/insert_custom",
data: jsonData,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess_insert_custom,
error: OnErrorCall
});
function OnErrorCall()
{ console.log("OHHH there is a mistake");}
function OnSuccess_insert_custom(response)
{ console.log("SUCESS");}
Webmethod Code
[WebMethod]
public string[] insert_custom(List<string> fb_Data,List<string> fb_user_data)
{
string temp = "";
string tripid = fb_Data[0];
string owner_id = fb_Data[1];
string fb_all_data;
string fb_id_user;
string fb_name;
string fb_img_src;
for (int i = 0; i < fb_user_data.Count; i++)
{
fb_all_data=fb_user_data[i];
string[] spltVal = fb_all_data.Split(',');
for (int j = 0; j < spltVal.Length; j++)
{
fb_id_user=spltVal[0];
fb_name = spltVal[1];
fb_img_src = spltVal[2];
temp = inFn.insert_custom(tripid, owner_id, fb_id_user, fb_name, fb_img_src);
}
}
// }
string[] arr1 = new string[] { temp };
return arr1;
}
But I am getting following error
"Type 'System.String' is not supported for deserialization of an array."
NOTE: fnds_list_array is not static ..It can increase or decrease
You can do this
MyWebMethod(List<List<string>> fnds_list_array)
See below example, I was not able to test it. but it can show you some way to your problem.
[WebMethod]
public static string[] insert_custom(List<MyTest> fnds_list_array)
{
}
public class MyTest
{
publc int Id
{ get; set;}
publc string Name
{ get; set;}
publc string ImageName
{ get; set;}
}
all,
I'm getting to my webmethod in my code behind but I'm having problems deserializing my json data.
I have no good reference but here is what I"m trying to do. My the code in my webmethod is not allowing me to get the data out passed from my ajax call. thanks for any help.
$("[id$=rdbSaveAjax1]").click(function () {
var mappedJobRole = new Array();
$(".jobRole").each(function (index) {
var jobRoleIndex = index;
var jobRoleID = $(this).attr('id');
var jobRoleName = $(this).text();
// add all the roleids and rolenames to the job role array.
var roleInfo = {
"roleIndex": jobRoleIndex,
"roleID": jobRoleID,
"roleName": jobRoleName
};
queryStr = { "roleInfo": roleInfo };
mappedJobRole.push(queryStr);
});
$.ajax({
type: "POST",
url: "Apage.aspx/Save_Mapped_Role",
data: "{'savedRole': " + JSON.stringify(mappedJobRole) + "}",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false,
success: function (data) {
alert("successfully posted data");
},
error: function (data) {
alert("failed posted data");
}
});
});
In my code behind I can't seem to get the data out.
My class:
public class MappedRole
{
public int Index { get; set; }
public string RoleID { get; set; }
public string RoleName { get; set; }
}
My webmethod:
[WebMethod]
public static bool Save_Mapped_Role(object savedRole)
{
bool success = false;
JavaScriptSerializer js = new JavaScriptSerializer();
IList<MappedRole> role = new JavaScriptSerializer().Deserialize<IList<MappedRole>>savedRole);
int Index = role[0].Index;
string RoleID = role[0].RoleID;
string RoleName = role[0].RoleName;
return success;
}
This line seems to be missing an opening parenthese
IList<MappedRole> role = new JavaScriptSerializer().Deserialize<IList<MappedRole>>savedRole);
Should read
IList<MappedRole> role = new JavaScriptSerializer().Deserialize<IList<MappedRole>>(savedRole);
Furthermore, in order to use the Deserialize method, you need to create classes based on the JSON variables you are passing. For example based on the JSON object you created, you should have the two classes below.
SavedRole Class
public class SavedRole
{
public roleInfo[] { get; set; }
}
roleInfo Class
public class roleInfo
{
public int roleIndex { get; set; }
public string roleID { get; set; }
public string roleName { get; set; }
}
Now the Deserialze method will do its magic and populate the objects for you. Then you'll be able to loop through the object and do what you need with the data.
[WebMethod]
public static bool Save_Mapped_Role(object savedRole)
{
bool success = false;
var serializer = new JavaScriptSerializer();
SavedRole role = serializer.Deserialize<SavedRole>(savedRole);
//Loop through the data like so
int roleIndex = 0;
string roleID = null;
string roleName = null;
foreach (var item in role.roleInfo) {
roleIndex = item.roleIndex;
roleID = item.roleID;
roleName = item.roleName;
//Do more logic with captured data
}
return success;
}
Hope that helps
this post explain how you can convert a JSON to C#: Parse JSON in C#
If you don't want to use that, you need to do some changes in your project:
First, to get the your RoleInfo, you need to transform it in a Dictionary like:
(((object[])savedRole)[0] as Dictionary<string, object>)["roleInfo"]
After that, you can manipule your object to create your List:
var list = ((object[])savedRole);
IList<MappedRole> role = new List<MappedRole>();
foreach (var item in list)
{
var dic = ((item as Dictionary<string, object>)["roleInfo"] as Dictionary<string, object>);
MappedRole map = new MappedRole()
{
roleIndex = Convert.ToInt32(dic["roleIndex"]),
roleID = dic["roleID"].ToString(),
roleName = dic["roleName"].ToString()
};
role.Add(map);
}