How to parse dynamic json data in WebAPI controller from jqgrid edit url - json

In after inline edit free jqgrid sends variable number of columns to ASP.NET MVC4 WebAPI controller using POST method.
Posted data contains json string below.
json string posted to controller in POST body looks like:
{"Toode":"","Kogus":"0.0000",
"Nimetus":"1","Mootyhik0_nimetus":"",
"Reanr":"2",
"_oper":"edit","_rowid":"1673",
"_dokdata":"[
{\"name\":\"Maksetin1_tingimus\",\"value\":\"\"},
{\"name\":\"Kinnitatud\",\"value\":\"False\"}]"
}
It has 3 regions of properties:
Order details. Dynamic properties "Toode":"","Kogus":"0.0000","Nimetus":"1","Mootyhik0_nimetus":"",
"Reanr":"2"
This list may change on runtime depending on user preferences.
This is created by using jqgrid extraparam: getDetails() setting.
Fixed properties stating with underscore `"_oper":"edit","_rowid":"
Those are
_oper and _rowid are always present
jqgrid adds them automatically.
Order data. fixed property _dokdata which contains json array of dynamic properites {\"name\":\"Maksetin1_tingimus\",\"value\":\"\"},{\"name\":\"Kinnitatud\",\"value\":\"False\"}
This is created from jqgrid colmodel.
This list may change in runtime and may contain same poperty names as in p.1 order details.
How to get this data in controller ? Probably it shoud be parsed into two dictionaries . Is it possible to force WebAPI to pass this data as classes/collection to controller or should it parsed manually?
jqgrid settings are from answer Using jqGrid's inline-editing with RESTful urls?
Those and serialize methods can changed if this makes data passing more reasonable.
Resulting WebAPI should have easily understandable data format (good API) since it will be used by third party applications also.
$.extend($.jgrid.defaults, {
ajaxRowOptions: { contentType: "application/json", async: true },
serializeRowData: function (data) {
var propertyName, propertyValue, dataToSend = {};
for (propertyName in data) {
if (data.hasOwnProperty(propertyName)) {
propertyValue = data[propertyName];
if ($.isFunction(propertyValue)) {
dataToSend[propertyName] = propertyValue();
} else {
dataToSend[propertyName] = propertyValue;
}
}
}
return JSON.stringify(dataToSend);
}
});
Update
serializeRowData is changed to
serializeRowData: function (data) {
return JSON.stringify({
headerData: $("#_form").serializeArray(),
rowData: data
} );
}
This produces bloated json for headerData:
{"headerData": [
{"name":"Tasudok","value":"134"},
{"name":"Kuupaev","value":"2015-11-23"},
{"name":"Dokumnr","value":"135319"}
],
"rowData": {"Toode":"",
"Kogus":"0.0000",
"Nimetus":"öäölä<a",
"_rowsum":"0.00",
"Id":"1639",
"Dokumnr":"135319",
"_oper":"edit",
"_rowid":"1639"
}
}
How remove name and value properties from headerData so that it contains property name and value pairs like in rowData:
headerData: {
"Tasudok": "134",
"Kuupaev": "2015-11-23",
"Dokumnr": "135319"
}

Related

How to: (a) send JSON data from the browser to the controller; and (b) send the transformed data to SQL Server within ASP.NET MVC?

I have a form which includes a variety of <input> elements and makes use of 1-to-n tabulator tables for data input. I have managed to successfully assemble data from these elements into a JSON string. I am now attempting to complete the following two steps:
Using Ajax, post the JSON object to my web server; and
In the ASP.NET MVC controller, upload the deserialized JSON data into a SQL Server 2016 table.
My client-side script to POST the JSON object is as follows:
var myJson = "the data from the form elements is programmatically inserted into the JSON string";
// use parseJSON() to test the syntax
try {
var obj = jQuery.parseJSON(myJson);
}
catch(error) {
console.log(error);
}
$.ajax({
type: "POST",
url: "/Dailies/UploadJson/",
dataType: 'json',
data: JSON.stringify(myJson),
contentType: 'application/json',
crossDomain: true,
cache: false,
success: function(data) { console.log(data); }
});
The method called within my ASP.NET MVC controller appears as follows:
[HttpPost]
public IActionResult UploadJson(Object jsonFile)
{
// insert data into SQL Server table
}
Note: I have already created the appropriate domain model within my ASP.NET MVC app and have also added a DbSet reference to the DbContext model. I have verified my ability to insert rows into the SQL Server table using mock data.
When I place a breakpoint inside the UploadJson() method, I find that the jsonFile object is null.
My quandry at this point is two-fold:
I can't seem to get JSON data from the client to the web server; and
I need to better understand how to transform the JSON data (once received) for upload into my database.
Any assistance is greatly appreciated.
Although there are plenty of questions related to this, the answers to those typically refer to binding to a model instead of just the json string. But those will also help you.
It looks like there are two things:
I would change the controller to receive a string instead of an object.
You'll need to update the json data you're passing to the controller to match the parameter name of the controller. So in this case, the controller would receive a parameter named jsonFile. So in the $.ajax method you'll want update the data to something like:
data: { jsonFile: JSON.stringify(myJson) }
UPDATE:
remove the Content-Type of application/json

Obfuscation for Asp MVC using SmartAssembly or CryptoObfuscator

I have a question in using CryptoObfuscator or RedGate SmartAssembly to obfuscate Asp Mvc Assemblies :
It seems when you use one of these tools to obfuscate assemblies, then they will rename properties of classes, right?
so I think because of this operation we will lose access to some of the values in JSON format that would comes from server during serialization ( I mean that because of renaming the properties we cant parse JSON object in JS correctly)
If this is true, so how can we prevent loosing parseJSON operation in JS?
Let me include more details :
consider this class structure
public class MyClass
{
public string FName{get;set;}
. . .
}
//SampleController :
public JsonResult GetJson()
{
return Json(new MyClass{FName = "Alex"});
}
Now in ClientSide :
$.ajax({
url: "/Sample/GetJson",
context: document.body
}).success(function(data) {
//this is my problem : can I access to FName or Not?
var fname = jQuery.parseJSON(data).FName;
});
Basically Obfuscators DO NOT change return value's Property's names.
But if some obfuscator does so... you can Simply accomplish this by using following in your ajax call:
$.ajax({
url: "/Sample/GetJson",
dataType: "json"
success: function(data) {
var transformedData = {fname:arguments[0], somethingElse:arguments[1]};
//or
var fname = arguments[0];
//do the rest here...
}
});
You can also use [DoNotObfuscate] attribute in "smart assembly"
By using this, you can prevent json results from being obfuscated at all (on server side).
Also there should be some (other/same) strategies for other obfuscators.
I personally use CryptoObfuscator and it has some options to prevent (what/where) ever you'd like from being obfuscated.

parse urls in Backbone.js

I am new to Backbones.js, and I was trying to get my JSON urls and parse them correctly.
This is my code:
window.Post = Backbone.Model.extend({
initialize: function(options) {
this.id = options.id;
},
url: function() {
return 'api/get_post/?post_type=movies&id=' + this.id;
},
parse : function(response) {
return response.posts;
},
});
window.Posts = Backbone.Collection.extend({
model: Post,
defaults: {
model: Post,
},
url: "api/get_recent_posts/?post_type=movies",
parse : function(response) {
return response.posts;
},
});
It seems that parsing for both overrides each other or something. when I remove the parse option from the Post class, I get a full response from the collection, but not from the model.
Are there any clear examples on how to set parsing for different son hierarchies? my JSON result have a status ok before it dives into the actual data.
I've never used bones.js but maybe these examples will help.
I think what you want to do is get rid of the parse() function in your collection. This assumes that since it is a Post collection, your data will come in as an array of Post JSON objects [{id:'1', 'sub':{data}},{id:'2', 'sub':{data}},{id:'3', 'sub':{data}}] or something like that.
If your Post model has sub-models or collections, your model parse() will then take the sub-object property name and do something with it.
// In Post Model definition
parse:function(response) {
if (response.sub) {
// create some model or collection etc.
}
}
You might have to pass an option parse:true when you do your collection fetch.
I posted something along these lines which might help you see how sub-models can be instantiated on fetch calls.
Backbone.js: Load multiple collections with one request
Cast/initialize submodels of a Backbone Model
I hope this helps.

Passing JSON object to MVC Controller

I can successfully make a jQuery Ajax call into my C# Controller and receive back an XML string, but I need to in turn gather some Portfolio dates and package them up into a JSON object so I can send them back into another C# Controller.
If it's a C# issue, then I apologize if I'm in the wrong forum...however I'd like to pass my JSON object into the server side controller ..
Here's what I'm trying to do:
var nodeDatesJson = {"nodedates": // CREATE JSON OBJECT OF DATE STRINGS
{ "date": 01/20/2012,
"date": "01/21/2012" } };
getTradeContribs(thisPfId, nodeDatesJson.nodedates.date);
Now call the next js function:
function getTradeContribs(pfid, nodedates) {
//alert(nodedates);
$.ajax({ // GET TRADE CONTRIBS FROM SERVER !!
url: "/Portfolios/getTradeContribs?portfolioId=" + pfid + "&nodedates=" + nodedates,
type: "GET", // or "PUT"
dataType: "json",
async: true,
success: parseTradeContribs,
error: function (error) {
alert("failed in opening Trade Contribs file !!!");
}
});
}
function parseTradeContribs(data) {
alert("In parseTradeContribs..." );
$(data).find("Trade").each(function(){
$(".TradeContrib").append($(this).text());
})
}
and my C# controller is trying to read in the "nodedates" JSON object, but HOW do I read it in ?
public string getTradeContribs(string portfolioId, **string nodedates**)
{
// Build Portfolio Select request here !
RequestBuilder rzrRequest = new RequestBuilder();
// REQUEST FOR CONTRIBUTIONS !
// ... more code here..
xmlResponse.LoadXml(contribResponse);
string jsonTest = #" {""nodedates"": ""date"":""01/01/2012""}";
//return xmlResponse.OuterXml; // WORKS FINE
return "<Trade><TradeId>1234</TradeId></Trade>"; // RETURN TEST XML STR
}
thank you in advance...
Bob
The best way to receive a list of dates in a MVC action is to bind to a collection. What this means is that you should put your dates and other attributes in a form with the following naming convention:
<input type="hidden" name="dates" value="2012-1-20" />
<input type="hidden" name="dates" value="2012-1-21" />
Then you should serialize this form (look into jquery's docs for this) and post its data to your action, which will be something along the lines of:
public ActionResult getTradeContribs(string portfolioId, IList<DateTime> dates) {
// Do your work here
}
You should really take a look into MVC Model binding and collection binding as well:
Model binding to a list
Model binding objects
Also, if I may, your javascript object has two properties with the same name, which is probably not what you mean. If you want to have multiple dates stored somewhere in a object, you should use an array:
var nodeDatesJson = {"nodedates":
[ "01/20/2012", "01/21/2012" ] };
Sorry, but I didn't understand your doubt very well...but here it goes:
Maybe you should pass the json, well-formatted, as a string and use some C# parser.
This way you can get a object in server-side as same as the Json object in javascript.
=]

asp.net mvc 3 ViewModel collection property to json not working

Good evening everyone. I am currently using MVC 3 and I have a viewmodel that contains a property that is a List. I am currently using json2's JSON.stringify method to pass my viewmodel to my action method. While debugging I am noticing that all the simple properties are coming thru but the collection property is empty even though I know for sure that there is at least one object in the collection. I wanted to know if there is anyone that is running into the same issue. Below is the code that I am using to post to the action method:
$.post("/ReservationWizard/AddVehicleToReservation/",
JSON.stringify('#ViewData["modelAsJSON"]'),
function (data) {
if (data != null) {
$("#vehicle-selection-container").html(data);
$(".reservation-wizard-step").fadeIn();
}
});
The object #ViewData["modelAsJSON"] contains the following json and is passed to my action method
{"NumberOfVehicles":1,"VehiclesToService":[{"VehicleMakeId":0,"VehicleModelId":0}]}
As you can see the property "VehiclesToService" has one object but when it gets to my action method it is not translated to the corresponding object in the collection, but rather the collection is empty.
If anyone has any insight into this issue it would be greatly appreciated.
Thanks in advance.
UPDATE
OK after making the recommended changes and making the call to new JavaScriptSerializer().Serialize(#Model) this is the string that ultimately gets sent to my action method through the post
'{"NumberOfVehicles":1,"VehiclesToService":[{"VehicleMakeId":0,"VehicleModelId":0}]}'
I can debug and see the object that gets sent to my action method, but again the collection property is empty and I know that for sure there is at least one object in the collection.
The AddVehicleToReservation action method is declared as follows:
public ActionResult AddVehicleToReservation(VehicleSelection selections)
{
...
return PartialView("viewName", model);
}
Here's the problem:
JSON.stringify('#ViewData["modelAsJSON"]')
JSON.stringify is a client side function and you are passing as argument a list that's stored in the ViewData so I suppose that it ends up calling the .ToString() and you have
JSON.stringify('System.Collections.Generic.List<Foo>')
in your final HTML which obviously doesn't make much sense. Also don't forget that in order to pass parameters to the server using the $.post function the second parameter needs to be a javascript object which is not what JSON.stringify does (it generates a string). So you need to end up with HTML like this:
$.post(
'ReservationWizard/AddVehicleToReservation',
[ { id: 1, title: 'title 1' }, { id: 2, title: 'title 2' } ],
function (data) {
if (data != null) {
$('#vehicle-selection-container').html(data);
$('.reservation-wizard-step').fadeIn();
}
}
);
So to make this work you will first need to serialize this ViewData into JSON. You could use the JavaScriptSerializer class for this:
#{
var myList = new JavaScriptSerializer().Serialize(ViewData["modelAsJSON"]);
}
$.post(
'#Url.Action("AddVehicleToReservation", "ReservationWizard")',
// Don't use JSON.stringify: that makes JSON request and without
// proper content type header your sever won't be able to bind it
#myList,
function (data) {
if (data != null) {
$('#vehicle-selection-container').html(data);
$('.reservation-wizard-step').fadeIn();
}
}
);
And please don't use this ViewData. Make your views strongly typed and use view models.