I am using Web Api.
I have an object of type A. when I return a list of type A to my client and then pass the list of type A back using a Post method the JSON serialisation and deserialisation is done automatically form me.
Because I want to pass multiple parameters using my POST method I have created a wrapper object with properties for each of the parameters I want to pass in. The JSON ser / DeSer is taken care of for this wrapper object, but how do I deserialise the JSON that represents my list of Type A within the wrapper object?
Thanks.
Added Code:
public class ConfigurationUpdateMessage
{
public string IpAddress { get; set; }
public List<object> Configurations { get; set; }
}
The Post method
public string PutUpdateConfigurations(ConfigurationUpdateMessage configMessage)
{}
Client Code
$scope.UpdateConfigs = function () {
$.ajax({
url: 'api/configurations',
dataType: "json",
type: "PUT",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ IpAddress: "127.0.0.1", Configurations: $scope.configs }),
async: true,
processData: false,
cache: false,
success: function (data) {
},
error: function (xhr) {
}
});
};
PRE: Can you post some code?
If your wrapper object contains properties which match the types of the serialized objects the model binder should automatically deserialize them into the matching properties. Unless there's something wrong with the structure of the JSON you're POSTing.
You should create your same wrapper type on server-side.
For example:
public class OperationDTO
{
public string Parameter1 { get; set; }
public int Parameter2 { get; set; }
public IEnumerable<A> MyList { get; set; } //List<A> will also work too
}
Your Web Api action should look like this:
[HttpPost]
public IHttpActionResult Operation([FromBody] OperationDTO)
{
//...
}
Related
I am working on angularJS application where I am making post call to send data to API controller everything is being sent to controller apart from array of data.
Here is code to make controller call
this.UpdateJobWithDeadlines = function (JobData) {
var request = $http({
method: "POST",
url: "/api/JobAPI/UpdateJobWithDeadlines",
data: JSON.stringify(JobData)
});
return request;
}
I have checked the JobData object, it's value (indented for easier reading) is:
{
"jobNum":null,
"jobName":"fgfg",
/* snip */
"StatusDatas":[
{
"scId":0,
"JobNum":9746.030148450296,
"StatusComment":"03-03-2017 : 1",
"scTimeStamp":"2017-03-03T15:47:48.174Z",
"IsNew":0
},
{
"scId":0,
"JobNum":8527.946898255957,
"StatusComment":"03-03-2017 : 3",
"scTimeStamp":"2017-03-03T15:47:49.459Z",
"IsNew":0
}
],
/* SNIP */
"telephone":"9"
}
The controller method signature is as below:
public int UpdateJobWithDeadlines(JobDataWithDeadlines JobData)
And the JobDataWithDeadlines class is as below:
public class JobDataWithDeadlines
{
public int? jobNum;
public string jobName;
/* snip */
public List<StatusData> StatusDatas;
}
public class StatusData
{
public int scId;
public int JobNum;
public string StatusComment;
public string scTimeStamp;
public bool IsNew;
}
But I am getting an empty list for the StatusDatas property of the controller method parameter.
The problem is your fields, they all need to be properties instead. The deserialization and serialization for json.net will not bind to fields (out of the box anyways, it is possible with additional configuration / custom mapping code).
public class JobDataWithDeadlines
{
public int? jobNum {get;set;}
public string jobName {get;set;}
/* snip */
public List<StatusData> StatusDatas {get;set;}
}
public class StatusData
{
public int scId {get;set;}
public double JobNum {get;set;}
public string StatusComment {get;set;}
public string scTimeStamp {get;set;}
public bool IsNew {get;set;}
}
Also you should specify the content-type in the http header of the request. In this case set it to application/json
You have to add the following properties to the object you pass to the $http method:
this.UpdateJobWithDeadlines = function (JobData) {
var request = $http({
method: "POST",
contentType: "application/json",
dataType: "json",
url: "/api/JobAPI/UpdateJobWithDeadlines",
data: JSON.stringify(JobData)
});
return request;
}
You can optionally specify a charset to the content type, i.e.:
contentType: 'application/json; charset=utf-8'
Some people also suggest adding traditional: true to it, but in my experience that is not always what causes this problem.
I am trying to send a complex Json with the following kind of form:
{
"Success":false,
"ErrorMessage":{
"ErrorMessage":"Some Message",
"ErrorType":"Serialization Failed",
"SiteReportDescription":"Some Desc",
"Status":false
},
"Result":null
}
To the following controller:
[Authorize, HttpPost]
public ActionResult DoThing(ThingModel model)
{
return Json(true);
}
Which accepts the following model (ThingError is another object with the four fields mentioned in the json):
public class ThingModel
{
public bool Success { get; set; }
public ThingError ErrorMessage { get; set; }
public ThingResult Result { get; set; }
}
I've used the following two methods to communicate with this Controller:
var form = $('<form method="post" enctype="multipart/form-data" style="visibility:hidden;"><input type="submit" name="model" /></form>');
$(document.body).append(form);
form.attr("action", '#Url.Action("DoThing", "Script")');
form.find("input[name='model']").val(JsonString);
form.submit();
$.ajax({
type: 'POST',
url: '#Url.Action("DoThing", "Script")',
contentType: "application/json; charset=utf-8",
processData: false,
dataType: 'json',
data: JsonString,
success: function (result) { }
},
});
Both of these methods of communication will interact with the controller but only the Ajax request will send a json string that is converted to the controller object ThingModel, the form.submit will just leave it null. What is the reason behind this? Is there something I am doing wrong in the Form?
You would need to capture this in fiddler in order to understand why.
Essentially, the ajax call is passing this:
{ "Something": "123" }
whereas the form is passing this:
{ "Model": { "Something": "123" } }
Not the same.
I'm working on a little test bed app, where you give the app a note name, sign, and octave, and it spits out the frequency the note should sound at.
I'm having a problem with a JavaScript object that is sent to a server via AJAX. However, it does not map at all to the class on the action.
The sender code is a piece of JavaScript:
$someContainer.on('click', '.raise-pitch', function (e) {
e.preventDefault();
var $line = $(this).parents('.item-line'),
// Cache GUI elements for this line. Not pertinent.
var data = {
'model': {
'NoteName': $noteName.val(),
'Sign': $noteSign.val(),
'Octave': $noteOctave.val()
},
'steps': 1
};
var dataString = JSON.stringify(data);
$.ajax({
type: 'POST',
url: '#Url.Action("AlterPitch", "Home")',
data: dataString,
async: true,
dataType: 'json',
success: function (result) {
// Unimportant things.
}
});
});
In the data object, you can see that I have two things: the model and the steps. The steps determines how far we alter the musical note. I have verified that the values for note name, sign, and octave are making it into the data object. The steps are pre-determined.
The data object, however, maps to a ViewModel on the C# side, which looks like this:
public class NoteViewModel
{
public enum NoteSign
{
Natural,
Sharp,
Flat
}
public string NoteName { get; set; }
public NoteSign Sign { get; set; }
public int Octave { get; set; }
public float Frequency { get; set; }
private static readonly Dictionary<string, float> FrequencyLookup = new Dictionary<string, float>
{
{"C", 16.35f},
{"C#", 17.32f},
{"D", 18.35f},
{"D#", 19.45f},
{"E", 20.60f},
{"F", 21.83f},
{"F#", 23.12f},
{"G", 24.50f},
{"G#", 25.96f},
{"A", 27.50f},
{"A#", 29.14f},
{"B", 30.87f}
};
// Methods...not important for reasons below.
}
...which itself is encapsulated in a unique view model:
public class AlterPitchViewModel
{
public NoteViewModel model;
public int steps;
public NoteViewModel AlterPitch()
{
model.ChangeStep(steps);
return model;
}
}
...or at least it should. I set a break point in my controller method:
[HttpPost]
public ActionResult AlterPitch(AlterPitchViewModel model)
{
return Json(model.AlterPitch(), JsonRequestBehavior.AllowGet);
}
...But the model is null, which leads to a NullReference exception.
the model isn't serializing to an object that gets sent along in this context. Obviously I am still doing something wrong. Question is...what?
This approach has worked for me.
Server Side:
First, create your ViewModel
public class TestViewModel
{
public string Id { get; set; }
public string Description { get; set; }
}
Then, in the Controller:
[HttpPost]
public ActionResult TestingViewModel(TestViewModel udata)
{
// Stuff.
}
Client Side:
function CallTestingViewModel() {
// We create the javascript object based on the
// definition of our C# ViewModel class.
var udata = {
Id: 1,
Description: 'This is a test.'
};
// Calling the C# method via AJAX.
$.when(GenericAjaxCall('Home/TestingViewModel', false, udata)).then(function (result) {
// do stuff
});
}
// Return the AJAX call as a Promise Object
function GenericAjaxCall(controllerUrl, async, clientData) {
return $.ajax({
type: 'POST',
async: async,
url: controllerUrl,
data: JSON.stringify(clientData),
contentType: 'application/json;',
dataType: 'json'
});
}
Hope it helps.
Your HttpPost Method must have one unique parameter which is your ViewModel. My advice: create a viewmodel per post WebMethod.
So here:
public class AlterPitchViewModel
{
public NoteViewModel note { get; set; };
public int Steps { get; set; };
}
And adapt your Javascript accordingly. No need to name your javascript model instance as the parameter in the ASP method -> one object arrives and only one parameter is available so no ambiguity.
I need post two argument to method in C#
[HttpPost]
public bool information([FromBody]int idInfromation,[FromBody] string information)
{
.....
return true;
}
with ajax, but my solution doesn´t work. Newtwork tab is showing:
POST http://-----/information/SubmitAnswer 500 (Internal Server Error)
I have this:
var source = { "idInfromation": 5, "information": "Wau" };
$.ajax({
url: "/information/",
type: "POST",
data: source,
dataType: "json",
contentType: "application/json",
success: function (data) {
alert("Complete");
}
});
Thank you for your advice.
You can't pass multiple [FormBody] parameters instead you have to pass parameter as an object.
for example, declare a DTO class
// DTO
public class InformationClass{
public int idInfromation{ get; set; }
public string Information{ get; set; }
}
[HttpPost]
public bool information(InformationDTO Info)
{
.....
return true;
}
to pass object using Json ajax:
// Initialize the object, before adding data to it.
// { } is declarative shorthand for new Object().
var Information= { };
Information.idInfromation= ParseInt($("txtId").val()); // your desired value
Information.Information= $("#Information").val();
// Create a data transfer object (DTO) with the proper structure.
var DTO = { 'Information' : Information};
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "InformationService.asmx/information", // or your specified url, if you don't want //use service like url: "/information/",
data: JSON.stringify(DTO),
dataType: "json"
});
Hope this helps,
Thanks.
You can't return two values with [FromBody]. Either create a DTO class or receive it as a JObject.
I am having problems passing a javascript array to an MVC3 controller, not sure what I am doing wrong but this code does work with standard WCF service.
$(function () {
$("button").click(function () {
Poster();
});
});
function Poster() {
var data = [];
data.push(new WidgetProperty("test1", "value1"));
alert(data.length);
$.post("Home/Test", {test : data});
}
function WidgetProperty(name, value) {
this.Name = name;
this.Value = value;
}
and controller is
[HttpPost]
public ActionResult Test(WidgetProperty[] test)
{
return View("About");
}
public class WidgetProperty
{
public string Name { get; set; }
public string Value { get; set; }
}
Any ideas why the object that comes to the controller has null values for the properties? Checked with fiddler and it appears it passing the correct values.
Thanks!
You should use JSON.stringify() on your data before you post it, and since you know the data type is JSON, it is best to specify that the data being posted is JSON.
$.post("Home/Test", {test : JSON.stringify(data) }, "json");
Live DEMO
Edit:
I researched this a little more and it seems that you need to include contentType: "application/json" in order for this to work in mvc3:
$.ajax({
type: "POST",
url: "Home/Test",
data: JSON.stringify(data),
success: function(data){},
dataType: "json",
contentType: "application/json"
});