Passing JSON object to MVC Controller - json

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.
=]

Related

Backbone model .toJSON() doesn't work after .fetch()

Good day! I need to render a model's attributes to JSON so I can pass them into a template.
Model:
var UserInfo = Backbone.Model.extend({
url: appConfig.baseURL + "users/",
});
Template:
<script type="text/html" class="template" id="profile-form">
<h2 class="ui-li-heading"><%= username %></h2>
<p class="ui-li-desc"><strong><%= phone %></strong></p>
</script>
View:
var ProfilePageView = Backbone.View.extend({
events: {
'click #edit': "edit"
},
initialize: function () {
this.template = $.tpl['profile-form'];
var user = new UserInfo()
user.fetch({
data: $.param({email: localStorage.getItem('user_email')}),
type: 'POST'
});
console.log(user) //returns correct object with attrs
console.log(user.toJSON()) //returns empty object
},
render: function (eventName) {
$(this.el).html(this.template());
},
edit: function () {
window.workspace.navigate('#account/edit', { trigger: true});
}
});
When i put in console something like this, user.toJSON() returns correct data
var user = new UserInfo();
user.fetch({
data: $.param({email: localStorage.getItem('user_email')}),
type: 'POST'
});
But when i put it to my view, its returns Object {}.
Where is a mistake or tell me how can differently pass to the template data received from the server in json format? Thanks!
You appear to have two problems. fetch is asyncronous, so you need to use a callback to use the information. But first, an explanation about toJSON. .toJSON() doesn't actually return a JSON string, it returns an object that is what you want JSON to stringify. This allows you to modify the toJSON method to customize what attributes will be taken from your model or collection and added to the JSON string representation of your model. Here is a quotation from the Backbone.js docs:
toJSON collection.toJSON([options])
Return a shallow copy of the model's attributes for JSON
stringification. This can be used for persistence, serialization, or
for augmentation before being sent to the server. The name of this
method is a bit confusing, as it doesn't actually return a JSON string
— but I'm afraid that it's the way that the JavaScript API for
JSON.stringify works.
So you should replace this line in your code
console.log(user.toJSON())
with this one
console.log(JSON.stringify(user))
The object that you saw was returned by toJSON will then be turned into JSON.
Now, even after you do that, it won't work properly, because you will execute the console.log before you get the data for your model from fetch. fetch is asynchronous, so you need to call any code you want to be executed after the fetch is done in the success callback:
user.fetch({
data: $.param({email: localStorage.getItem('user_email')}),
type: 'POST',
success: function(){
console.log(user);
console.log(JSON.stringify(user));
}
});

Return JSON from ASMX web service, without XML wrapper?

I need to get Json data from a C# web service.
I know there are several questions based on this, trust me I have read through quite a few but only to confuse me further.
This is what I have done :
In my web service I have included : [System.Web.Script.Services.ScriptService] for the class & [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] for the method
I have also used a JavaScriptSerializer() to convert my data to a string
I am calling this service using $.getJSON()
If I don't use that I get an Cross domain reference error.
To do this I had to setup m service to get the callback function name
so I am passing this.Context.Request["callback"] + serialized Json Data;
But in the output I get it wrapped in
< string xmlns="http://XYZ...">
The data within the tags is in the format I need
I also tried setting content type using : $.ajaxSetup({ scriptCharset: "utf-8" , contentType: "application/json; charset=utf-8"});
But still no success.
Addded later: I accepted frenchie's anwser beacuse I know it is the correct approach but I stil cud not get it to work... I just put the webservice & website in the same domain & used xml, I know it wasnt the best way, but I had spent 2 days on it & could not afford to waste more.
Use this:
var JsonString = ....;
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "YourWebServiceName.asmx/yourmethodname",
data: "{'TheData':'" + JsonString + "'}",
dataType: "json",
success: function (msg) {
var data = msg.hasOwnProperty("d") ? msg.d : msg;
OnSucessCallBack(data);
},
error: function (xhr, status, error) {
alert(xhr.statusText);
}
});
function OnSuccessCallData(DataFromServer) {
// your handler for success
}
and then on the server side, in the code behind file that's auto-generated in your AppCode folder, you write something like this:
using System.Web.Services;
using System.Web.Script.Serialization;
[System.Web.Script.Services.ScriptService]
public class YourWebServiceName : System.Web.Services.WebService
{
[WebMethod]
public string yourmethodname(string TheData)
{
JavascriptSerializer YourSerializer = new JavascriptSerializer();
// custom serializer if you need one
YourSerializer.RegisterConverters(new JavascriptConverter [] { new YourCustomConverter() });
//deserialization
TheData.Deserialize(TheData);
//serialization
TheData.Serialize(TheData);
}
}
If you don't use a custom converter, the properties between the json string and the c# class definition of your server-side object must match for the deserialization to work. For the serialization, if you don't have a custom converter, the json string will include every property of your c# class. You can add [ScriptIgnore] just before a property definition in your c# class and that property will be ignored by the serializer if you don't specify a custom converter.

.NET MVC3 HttpRequestValidation & JSON

I'm new to MVC3 framework (and .NET overall; Java veteran), so bear with me, but here goes:
Input submitted to a Controller as JSON doesn't seem to be subject to the HttpRequestValidation -- Does that sound right?
I realize if you're receiving data input via JSON you're possibly already doing more work with it, but the Controller Action doesn't seem to necessarily know whether it has JSON data at that point; input values are mapped to parameters just as they would be if they were standard POST params.
Example - I'm asynchronously submitting JSON data to my Controller like the following:
var data = { "title": $titleField.val(), "content": $textArea.val(),
"location": $location.val()
};
$.ajax(submitUrl,
{
type: "POST",
contentType: "application/json; charset=utf-8",
complete: function (data) {
//blah blah
},
dataType: 'json',
data: JSON.stringify(data)
});
}
I then receive the input in my Action:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult New(string title = "", string content = "", string location = "")
{
//yada yada
}
Doing this, params are mapped and the user can easily send tags, etc. I'm not turning ValidateInput off, and if I submit with a standard POST and remove the Stringify, it throws the error as expected. Any good reason why JSONified data would skip validation?
Edit - More specific question: If JSONified data will pass HttpRequestValidation, how can we protect against the event where someone would intentionally mock a request to send JSON data instead of post params? I haven't found a way to force the Action method to differentiate between params passed as JSON vs. those passed non-encoded.
Got an answer for my question over on asp.net - See 2nd response.
Solution involves replacing the default ModelBinder.
Any good reason why JSONified data would skip validation?
JSON is encoded => so it ensures that what transits over the wire is safe. When you use JSON.stringify all dangerous characters are encoded.

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.

How to parse ASP.NET JSON Date format with GWT

ASP.NET JSON serialize DateTime to the following format "/Date(1251877601000)/". Pls, help parse this string into the java(GWT) Date object.
At this time the solution I came with is parsing with regex, extract long.. but then I cannot push long through JSNI.
function FixJsonDates(data) {
//microsoft script service perform the following to fix the dates.
//json date:\/Date(1317307437667-0400)\/"
//javasccript format required: new Date(1317307437667-0400)
//copied from micrsoft generated fiel.
var _dateRegEx = new RegExp('(^|[^\\\\])\\"\\\\/Date\\((-?[0-9]+)(?:[a-zA-Z]|(?:\\+|-)[0-9]{4})?\\)\\\\/\\"', 'g');
var exp = data.replace(_dateRegEx, "$1new Date($2)");
return eval(exp);
}
The answer to this question is, use nuget to obtain JSON.NET then use this inside your JsonResult method:
return Json(JsonConvert.SerializeObject(/* JSON OBJECT TO SEND TO VIEW */));
inside your view simple do this in javascript:
JSON.parse(#Html.Raw(Model.data))
If it comes via a view model that is or if it is an ajax call:
var request = $.ajax({ url: "#Url.Action("SomeAjaxAction", "SomeController")", dataType: "json"});
request.done(function (data, result) { JSON.parse(data); });