I would like to know how to convert the following object to C# when reaching the mathod. I needed to create an object which can hold multiple array's within JSON something like the following
{
"cars": {
"Ferrari":["LaFerrari","F40","458"],
"Porsche":["911","959"],
"Lamborghini":["Aventador"]
}
}
The code I used is the following within cshtml
<div class="row">
<div class="col-md-4">
<div>
<input type="text" id="txtKey" />
<input type="button" id="btnKey" />
</div>
<div>
<input type="text" id="txtChild" />
<input type="button" id="btnChild" />
</div>
<div>
<input type="button" id="btnSubmit" />
</div>
</div>
</div>
#section scripts
{
$(function () {
AddKeyToDictionary('Ferrari');
AddKeyToDictionary('Porsche');
AddKeyToDictionary('Lamborghini');
AddValueToDictionary('Ferrari', 'LaFerrari');
AddValueToDictionary('Ferrari', 'F40');
AddValueToDictionary('Ferrari', '458');
AddValueToDictionary('Porsche', '911');
AddValueToDictionary('Porsche', '959');
AddValueToDictionary('Lamborghini', 'Aventador');
$('#btnKey').click(function () {
AddKeyToDictionary($('#txtKey').val());
});
$('#btnChild').click(function () {
AddValueToDictionary($('#txtKey').val(), $('#txtChild').val());
});
$('#btnSubmit').click(function () {
submit();
});
});
var dict = {};
function AddKeyToDictionary(key) {
dict[key] = [];
}
function AddValueToDictionary(key, value) {
dict[key].push(value);
}
function submit() {
var url = "#Url.Action("UpdateCustomFields", "Home")";
var data = JSON.stringify({ 'cars': dict });
$.ajax({
type: "POST",
contentType: "Application/json;charset=utf-8",
url: url,
data: data,
datatype: "json",
success: function (msg) {
},
error: function (request, status, error) {
displayDialog("A communication Error has occurred, please contact IT support: " + error);
}
});
}
</script>
}
I've tried the following within MVC (got this from a JSON c# convertor)
public JsonResult UpdateCustomFields(RootObject cars)
{
return Json("");
}
}
public class Cars
{
public List<string> Ferrari { get; set; }
public List<string> Porsche { get; set; }
public List<string> Lamborghini { get; set; }
}
public class RootObject
{
public Cars cars { get; set; }
}
The car makes should be dynamic and then the arrays below should be converted correctly.
I also tried to iterate through the array and changed them all to key value pairs which still wasn't rendering
function convertToKeyValue() {
submitValue = [];
for (var k in dict) {
if (dict.hasOwnProperty(k)) {
if (dict[k].length > 0) {
for (var i = 0; i < dict[k].length; i++) {
submitValue.push({ key: k, value: dict[k][i] });
}
} else {
submitValue.push({ key: k, value: '' });
}
}
}
}
Passing them through the name/value pairs I was able to see them in the dynamic property within the controller but can't get to the variables.
public JsonResult UpdateClientCustomFields(object cars)
{
var result = customFields.XmlSerializeToString();
return Json("hello");
}
If anyone can help or point me in the right direction.
Thanks
Updated: I've had to convert the javascript array to a list of key pairs (not ideal) and use List> cars as the paramter, the model is not ideal, but will use this until I find a better way.
Here is the updated code
HTML
<input type="button" id="btnSubmit2" />
var submitValue = [];
function convertToKeyValue() {
submitValue = [];
for (var k in dict) {
if (dict.hasOwnProperty(k)) {
//alert("Key is " + k + ", value is" + dict[k]);
//alert("KEY: " + k);
if (dict[k].length > 0) {
for (var i = 0; i < dict[k].length; i++) {
//alert("childrec: " + dict[k][i]);
submitValue.push({ key: k, value: dict[k][i] });
}
} else {
submitValue.push({ key: k, value: '' });
}
}
}
}
function submit2() {
convertToKeyValue();
var url = "#Url.Action("UpdateCustomFields2", "Home")";
var data = JSON.stringify({ 'cars': submitValue });
$.ajax({
type: "POST",
contentType: "Application/json;charset=utf-8",
url: url,
data: data,
datatype: "json",
success: function (msg) {
},
error: function (request, status, error) {
}
});
}
MVC
public JsonResult UpdateCustomFields2(List<Dictionary<string, string>> cars)
{
return Json("");
}
Try changing your cars property in RootObject to public Dictionary<string,List<string>> cars {get; set;}
Try to make your input param as string and then deserialize it to your object.
public JsonResult UpdateCustomFields(string cars)
{
RootObject yourCars = JsonConvert.DeserializeObject<RootObject>(cars);
return Json("");
}
Good luck :)
Unless I am missing something, the following seems to work fine
public class Program
{
public void Main(string[] args)
{
var json = #"
{
""cars"": {
""Ferrari"":[""LaFerrari"",""F40"",""458""],
""Porsche"":[""911"",""959""],
""Lamborghini"":[""Aventador""]
}
}
";
var dataObj = JsonConvert.DeserializeObject<Data>(json);
}
public class Data
{
public Dictionary<string, List<string>> Cars { get; set; }
}
}
Which version of JSON.NET are you using? I remember older versions had issues with dictionaries, but you could probably just create your own converter if that is the case.
Related
I am using JQuery DataTables and AJAX. I am having difficulty getting fields from the secondary table that are connected through the primary key. The only thing that I am able to show is the primary key. In this case concern_id.
Model: Question
public int question_id { get; set; }
public int concern_id { get; set; }
public string question_text { get; set; }
public string question_answer { get; set; }
Model: Concern
public int concern_id { get; set; }
public string concern_desc { get; set; }
I would like to be able to show the concern_desc. If I don't use AJAX in datatables I can easily grab the field I need.
Example:
#Html.DisplayNameFor(model => model.concern.concern_desc)
Controller:
public JsonResult GetQuestionRecord()
{
bool proxyCreation = db.Configuration.ProxyCreationEnabled;
try
{
db.Configuration.ProxyCreationEnabled = false;
var list = (from q in db.questions
join c in db.concerns on q.concern_id equals c.concern_id
select q).ToList();
return Json(list, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(ex.Message);
}
finally
{
db.Configuration.ProxyCreationEnabled = proxyCreation;
}
}
View:
<table id="DataTable" class="display" style="width:100%">
<thead>
<tr>
<th>ConcernID</th>
<th>QuestionText</th>
</tr>
</thead>
<tbody></tbody>
The JavaScript:
$(document).ready(function () {
GetQuestionRecord();
});
var GetQuestionRecord = function () {
$.ajax({
type: "Get",
url: '#Url.Action("GetQuestionRecord","questions")',
success: function (response) {
BindDataTable(response);
}
});
}
var BindDataTable = function (response) {
$("#DataTable").DataTable({
"aaData": response,
"aoColumns": [
{ "mData": "concern_id" },
{ "mData": "question_text" },
]
});
}
What do I change in the "mData : concern_id" to in order to display "concern_desc" . I tried:
{ "mData": "concern_desc" }
And
{ "mData": "concern.concern_desc" }
Step 1: Change your LINQ query in the Controller to this.
var list = (from q in db.questions
join c in db.concerns on q.concern_id equals c.concern_id
select new
{
question_id = q.question_id,
concern_id = q.concern_id,
question_text = q.question_text,
question_answer = q.question_aswer,
concern_desc = c.concern_desc
}).ToList();
Step 2: Change your BindDataTable JS code to.
var BindDataTable = function (response) {
$("#DataTable").DataTable({
"aaData": response,
"aoColumns": [
{ "mData": "concern_id" },
{ "mData": "question_text" },
{ "mData": "concern_desc" }
]
});
Thanks to #NikhilGhuse, which solution have been sent to me (please mark his answer). I can apply this solution to my data these are the results and the keys:
First of all my model need to send a List to the controller. This is my my function to send the List:
public List<VistaModelo> SegundaConsulta()
{
//Web.Config
Entities db = new Entities();
var consulta = from varLocal in db.LecturaContadorLuzAANDRES
group varLocal by varLocal.dispositivo into subconsulta
select subconsulta.OrderByDescending(t => t.unixtime).FirstOrDefault();
List<LecturaContadorLuzAANDRES> lista = consulta.ToList();
List<VistaModelo> listaVistaModelo = new List<VistaModelo>();
foreach (LecturaContadorLuzAANDRES b in lista)
{
VistaModelo objLista = b.pasaObjetoAVistaModelo();
listaVistaModelo.Add(objLista);
}
return listaVistaModelo;
}
Then in my controller I need two functions:
Consulta 6. Read the list and transform to JSON (you need: using Newtonsoft.Json; in the controller:
public JsonResult Consulta6()
{
var Consulta = new ConsultaContraBD();
List<VistaModelo> miSegundaConsulta = Consulta.SegundaConsulta();
return Json(miSegundaConsulta, JsonRequestBehavior.AllowGet); //El JsonRequest Behaviour permite que se devuelva información de JSON en un getRequest.
}
Consulta7. From this method I make the View:
public ActionResult Consulta7()
{
return View();
}
Finally I need Ajax into the script to read the information pass to method Consulta6. Note: Remember to load the packages json2.js and jquery-3.0.0.js
#{
ViewBag.Title = "Consulta7";
}
<script src="~/Script/jquery-3.0.0.js"></script>
<script src="~/Script/json2.js"></script>
<script type="text/javascript">
$(function () {
$('#btonLista').on("click", function (e) {
e.preventDefault();
$.ajax
({
url: '/Home/Consulta6/',
type: 'get',
dataType: 'json',
success: function (data) {
$(data).each(function (index, item) {
$('#ulLista').append("<li>" + item.consumo + "</li>")
});
}
});
});
});
</script>
<div>
<input type="button" id="btonLista" value="Click" name="" />
<ul id="ulLista"></ul>
</div>
The final result is a page where you click a button and returns the list.
<script type="text/javascript">
$(function ()
{enter code here
$('#btonLista').on("click", function (e)
{
e.preventDefault();
$.ajax
({
url: '/Home/Consulta52/',
type: 'GET',
dataType: 'json',
success: function (data) {
$(data).each(function (index, item) {
$('#ulLista').append("<li>"+item.consumo+"</li>")
});
}
});
});
});
</script>
My two controllers:
public ActionResult Consulta51()
{
return View();
}
public JsonResult Consulta52()
{
var Consulta = new ConsultaContraBD();
var miSegundaConsulta = Consulta.SegundaConsulta();
return Json(miSegundaConsulta.ToList(), JsonRequestBehavior.AllowGet);
}
/// My Sample Starts here
//Controller
namespace Sample.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
public JsonResult Consulta52()
{
modelCS model = new modelCS();
List<Department> ds = model.getList();
return Json(ds, JsonRequestBehavior.AllowGet);
}
}
}
//Index.cshtml
#{
ViewBag.Title = "Index";
}
<h2>
Index</h2>
<script src="../../scripts/jquery-2.1.4.js" type="text/javascript">
</script>
<script src="../../scripts/json2.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$('#btonLista').on("click", function (e) {
e.preventDefault();
$.ajax
({
url: '/Home/Consulta52/',
type: 'get',
dataType: 'json',
success: function (data) {
$(data).each(function (index, item) {
$('#ulLista').append("<li>" + item.DepartmentName + "</li>")
});
}
});
});
});
</script>
<div>
<input type="button" id="btonLista" value="Click" name="" />
<ul id="ulLista">
</ul>
</div>
And My Model Class goes like this
public class modelCS
{
string constr = "Data Source=.;Initial Catalog=test1;Integrated Security=True";
List<Department> newDept = new List<Department>();
public List<Department> getList()
{
SqlConnection con = new SqlConnection(constr);
// SqlCommand cmd = new SqlCommand("select * from Department", con);
con.Open();
SqlDataAdapter da = new SqlDataAdapter("select * from Department", con);
DataSet ds = new DataSet();
da.Fill(ds);
var td = ds.Tables[0];
// List<Department> newDept = new List<Department>();
foreach (DataRow t in td.Rows)
{
newDept.Add(new Department() { DepartmentId = (int)t.ItemArray[0], DepartmentName = t.ItemArray[1].ToString() });
}
return newDept;
//List<string> list = listT
}
}
Department class
public class Department
{
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
}
Ok, this might be simple, I'm having a simple $.post call to server sending string array as parameters..
$.get('/home/ReadCalPacTagValue', data, function (data) {
data = $.parseJSON(data);
if (data.length != 0) {
var ReadFromDb = data[0]["PushToDb"].replace('PushToDb','ReadFromDb');
var DBAckno = ReadFromDb.replace('ReadFromDb', 'DataAck');
var FIdTag = ReadFromDb.replace('ReadFromDb', 'FluidTypeId');
var UserIdTag = ReadFromDb.replace('ReadFromDb', 'UserId');
var UniqueIdTag = ReadFromDb.replace('ReadFromDb', 'UniqueRecordId');
var dbconnTag = ReadFromDb.replace('ReadFromDb', 'DatabaseConnectionString');
updateTags = [dbconnTag,FIdTag,ReadFromDb, UserIdTag,UniqueIdTag];
actionvalue = ["", fluidtypeid, '1', userid, uniqueID];
var data_Tags = { updateTags: updateTags, actionvalue: actionvalue }
$.post('/home/WriteCalPacTagValue', data_Tags, function (response) {
//var Path = "Config/16_CalPac/" + FluidType + "/" + metername + "/" + FileName
//$.cookie('FileName', FileName, { expires: 7, path: '/' });
//$.cookie('FilePath', Path, { expires: 7, path: '/' });
//$.cookie('ModuleName', "CalPac", { expires: 7, path: '/' });
//window.open('../home/CalPac', '_blank');
});
} else {
swal("Error !", "Data operation tag not binded for this product", "warning");
}
})
my problem is, every time it makes $.post call, server is getting null values int prarameters..
public void WriteCalPacTagValue(string[] updateTags, string[] actionValue)
{
string[] writetags = { };
DanpacUIRepository objNewTag = new DanpacUIRepository();
if (updateTags.Count() > 0)
{
actionValue[0] = ConfigurationManager.AppSettings["DBString"].ToString();
for (int i = 0; i < updateTags.Count(); i++)
{
writetags = updateTags[i].Replace("<", "").Replace(">", ">").Split('>');
objNewTag.WriteTag(writetags, actionValue[i]);
}
}
}
I'm not getting what I've done wrong here.. whereas same function is working from another JS file with some difference string into array updateTags.
any help?
Having
public class DataTags
{
public string[] UpdateTags { get; set; }
public string[] ActionValue { get; set; }
}
At the server: Change the method to this
[HttpPost()]
public void WriteCalPacTagValue([FromBody]DataTags data_Tags)
{
}
At the client: call it
$.ajax({
type: 'POST',
url: '/home/WriteCalPacTagValue',
data: data_Tags,
success: function (response) {
//your code
}
});
Also you can send the whole data as json string using data: JSON.stringify(data_Tags), in javascript code the change the WriteCalPacTagValue to accept a single string at the parameter and deserialize it in C# code at the server side.
EDIT if you cannot change the server side code, you may follow this as stated in the comments.
I m trying to call web method from jsTree but unable to call it. can someone please help me out to get this resolved.
my jsTree function is:-
$('#tree').jstree({
"json_data": {
"ajax": {
"type": "POST",
"dataType": "json",
"async": true,
"contentType": "application/json;",
"opts": {
"method": "POST",
"url": "../../SurveyReport/Metrics.aspx/GetAllNodes11"
},
"url": "../../SurveyReport/Metrics.aspx/GetAllNodes11",
"data": function (node) {
if (node == -1) {
return '{ "operation" : "get_children", "id" : -1 }';
}
else {
//get the children for this node
return '{ "operation" : "get_children", "id" : ' + $(node).attr("id") + ' }';
}
},
"success": function (retval) {
alert('Success')
return retval.d;
},
"error": function (r) {
alert(r.attr);
alert('error');
}
}
},
"plugins": ["themes", "json_data"]
});
And web method and data file is:-
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static List<G_JSTree> GetAllNodes11(string id)
{
if (id != "-1") //-1 means initial load else async loading of children
{
if (id == "10")
//Add 3 children to parent node with id=10.
return AddChildNodes(10, 3, "xxxx");
else
return new List<G_JSTree>();
}
List<G_JSTree> G_JSTreeArray = new List<G_JSTree>();
//Creating the JsTree data
//In live scenarios this will come from db or Web Service
//Add 5 root nodes
G_JSTreeArray.AddRange(AddChildNodes(0, 5, ""));
//Add 4 children to 3rd root node
//The third node has id=30
//The child nodes will have ids like 301,302,303,304
G_JSTreeArray[3].children = (AddChildNodes(30, 4, G_JSTreeArray[3].data)).ToArray();
//Add 5 children to level1 Node at id=302
G_JSTreeArray[3].children[1].children = (AddChildNodes(302, 4, G_JSTreeArray[3].children[1].data)).ToArray();
return G_JSTreeArray;
}
private static List<G_JSTree> AddChildNodes(int _ParentID, int NumOfChildren, string ParentName)
{
List<G_JSTree> G_JSTreeArray = new List<G_JSTree>();
int n = 10;
for (int i = 0; i < NumOfChildren; i++)
{
int CurrChildId = (_ParentID == 0) ? n : ((_ParentID * 10) + i);
G_JSTree _G_JSTree = new G_JSTree();
_G_JSTree.data = (_ParentID == 0) ? "root" + "-Child" + i.ToString() : ParentName + CurrChildId.ToString() + i.ToString();
_G_JSTree.state = "closed"; //For async to work
_G_JSTree.IdServerUse = CurrChildId;
_G_JSTree.children = null;
_G_JSTree.attr = new G_JsTreeAttribute { id = CurrChildId.ToString(), selected = false };
G_JSTreeArray.Add(_G_JSTree);
n = n + 10;
}
return G_JSTreeArray;
}
public class G_JSTree
{
public G_JsTreeAttribute attr;
public G_JSTree[] children;
public string data
{
get;
set;
}
public int IdServerUse
{
get;
set;
}
public string icons
{
get;
set;
}
public string state
{
get;
set;
}
}
public class G_JsTreeAttribute
{
public string id;
public bool selected;
}
}
I want to load the tree in an async fashion from a webmethod in an asp.net page.
Thanks in advance.
I use this Code Successfully By add this Complete Reference :
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)] //ResponseFormat.Json)]
public static List<GG_JSTree> GetAllNodes11(string id)
{......}
I have multiple parameters which I have to pass to api controller.
What I was doing is
In my javascript
var routeInfo = JSON.stringify(routes);
var colors = JSON.stringify(colorsArray);
var times = JSON.stringify(mytimeArray);
var distances = JSON.stringify(myDistancArray);
var dir = $("#Direction").val();
var fullString = routeInfo + ";" + colors + ";" + times + ";" + distances+";"+dir;
$.post("api/HomeToSchool/?route=" + fullString,
function (data) {
if (data = true) {
alert("Routes Saved Successfully");
}
else if (data = false) {
alert("Routes are not saved");
}
});
& in my Controller
public bool PostHomeToSchoolRoutes([FromUri]string route)
{
// my logic
}
Here I am just getting values of "routeInfo" & other values are not comming.
e.g.
var routeInfo = [["Børge,Brogade 38, 4100, Ringsted,09:25:00,55.43953, 11.79043","Grete,Sjællandsgade 27, 4100, Ringsted,09:25:00,55.44024, 11.78852","Else,Fynsgade 14, 4100, Ringsted,09:25:00,55.44128, 11.78595","Birthe,Eksercerpladsen 47, 4100, Ringsted,09:25:00,55.44954, 11.80309","Knud Lavard Centret, Eksercerpladsen 3, 4100, Ringsted,370,55.45014, 11.80474"]]
var colors = ["#886A52"]
var times = [7.97]
var distances = [3.36]
var dir = 0
What I get in my Controller is
[["Børge,Brogade 38, 4100, Ringsted,09:25:00,55.43953, 11.79043","Grete,Sjællandsgade 27, 4100, Ringsted,09:25:00,55.44024, 11.78852","Else,Fynsgade 14, 4100, Ringsted,09:25:00,55.44128, 11.78595","Birthe,Eksercerpladsen 47, 4100, Ringsted,09:25:00,55.44954, 11.80309","Knud Lavard Centret, Eksercerpladsen 3, 4100, Ringsted,370,55.45014, 11.80474"]];["
Other values are not coming.
Whats wrong I am doing here.
I'm afraid that your url is too long (>255 characters), You can try this.
$.ajax({
type: 'POST',
url:"api/HomeToSchool",
data:{routeInfo:routes,colors:colorsArray,times:mytimeArray,distances:myDistancArray,dir:dir},
dataType: "json",
traditional:true,
function (data) {
if (data = true) {
alert("Routes Saved Successfully");
}
else if (data = false) {
alert("Routes are not saved");
}
}
});
and your controller:
public bool PostHomeToSchoolRoutes(string[] routeInfo,string[] colors,double[] times,double[] distances,int dir)
{
// my logic
}
I see that you're using 2-dimensional array for routeInfo. But there is only 1 item, i think you should change it to 1-dimensional array to make it compatible with the controller code string[] routeInfo
Far too much information going into the URL here, not only that your not correctly appending the parameters together they need to be separated using & not ;.
On top of that, your not really taking advantage of the MVC capabilities here. At the client side you want to send up your information as a collective object rather than individual parameters e.g.
var schoolRoutes = {
routes: routes,
colors: colorsArray,
times: mytimeArray,
distances: myDistanceArray,
direction: $("#Direction").val()
};
$.ajax({
type: 'POST'
url: "api/HomeToSchoolRoutes",
data: JSON.stringify(schoolRoutes),
dataType: "json",
success: function (data) {
if (data = true) {
alert("Routes Saved Successfully");
}
else if (data = false) {
alert("Routes are not saved");
}
});
Then at the server side, introduce a class which will be able to bind to the incoming data aka a ViewModel
public class RouteInfoViewModel
{
...
}
public class SchoolRoutesViewModel
{
public RouteInfoViewModel[] Routes { get; set; }
public string[] Colours { get; set; }
public double[] Times { get; set; }
public double[] Distances { get; set; }
public string Direction { get; set; }
}
Then update your action to expect this particular ViewModel and that should give you access to all the information posted.
public bool PostHomeToSchoolRoutes(SchoolRoutesViewModel schoolRoutes)
{
...
}