Parsing [FromBody] JSON: model null - c#

I'm trying to parse some json in my action which will then do things with it. However I keep getting null as my model instead of the filled out model.
This is the json I'm trying to parse:
{
"sameLanguages":true,
"sameDeadlines":true,
"sameDeliverables":false,
"quotations":[
{
"name":"zasd",
"deliverable":"538184e1-9a62-4ce9-baa7-ed746f267a9a",
"subtitleAssignments":{
"languageCombinations":[
{
"from":"d177b276-8f10-472f-84c6-f2ef59052a09",
"to":"d177b276-8f10-472f-84c6-f2ef59052a09",
"startDate":"19-09-2017",
"endDate":"19-09-2017"
}
],
"amount":12
},
"translationAssignments":{
"languageCombinations":[
]
}
}
]
}
This is my action:
[HttpPost]
public IActionResult Add([FromBody] SubmitQuotationsModel model)
{
//Do things...
return View();
}
These are my models:
public class SubmitQuotationsModel
{
public bool SameLanguages { get; set; }
public bool SameDeadlines { get; set; }
public bool SameDeliverables { get; set; }
public List<SubmitQuotationModel> Quotations { get; set; } = new List<SubmitQuotationModel>();
}
public class SubmitQuotationModel
{
public string Name { get; set; }
public string Deliverable { get; set; }
public List<AssignmentModel> SubtitleAssignments { get; set; }
public List<AssignmentModel> TranslationAssignments { get; set; }
}
public class AssignmentModel
{
public List<LanguageCombinationModel> LanguageCombinations { get; set; }
public int Amount { get; set; }
}
public class LanguageCombinationModel
{
public string From { get; set; }
public string To { get; set; }
public DateTimeOffset StartDate { get; set; }
public DateTimeOffset EndDate { get; set; }
}
I am sending the json from my knockout/typescript script as such:
fetch('/Quotation/Add', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include',
body: this.toJSON()
});
public toJSON(): string {
let model = {
sameLanguages: this.step1().sameLanguages(),
sameDeadlines: this.step1().sameDeadlines(),
sameDeliverables: this.step1().sameDeliverables(),
quotations: this.step2().quotations().filter((q) => q.isFilledIn()).map((q) => {
return {
name: q.name(),
deliverable: q.selectedDeliverable().id,
subtitleAssignments: this.getAssignmentModel(q.subtitleAssignmentGroup()),
translationAssignments: this.getAssignmentModel(q.translationAssignmentGroup())
}
})
};
return ko.toJSON(model);
}
private getAssignmentModel(model: AssignmentGroupModel) {
return {
languageCombinations: model.assignments().map((a) => {
return {
from: a.fromLanguage().value,
to: a.toLanguage().value,
startDate: a.startDate().format('DD-MM-YYYY'),
endDate: a.endDate().format('DD-MM-YYYY')
}
}),
amount: model.amount()
}
}
I'm not getting any exceptions, the model parameter just remains null. I have found that if I comment out the SubtitleAssignments and TranslationAssignments in SubmitQuotationModel, it deserializes the other parts of the json just fine. But I can't figure out why it won't deserialize with those two ...Assignments declarations not commented out.

SubtitleAssignments and TranslationAssignments aren't lists in the json but they are lists in the models. They just need to be AssignmentModel and not List<AssignmentModel>

Related

Deserialize a json object with multiple nested objects /lists using JsonConvert

I a beginner in C# application development and have the following json data which I want to de-serialize:
{
"Parameters": [
{
"Info": {
"Id": 0,
"No": "0001"
},
"IntOptions": [
{
"Value": 0,
"ValInfo": "FIFO"
},
{
"Value": 1,
"ValInfo": "FIFO2"
}
],
"BubbleList": [
{
"Position": 0,
"SubBubbleList": [
{
"Value": 0,
"Message": "ListObj1"
},
{
"Value": 1,
"Message": "ListObj2"
}
]
}
]
}
]
}
I have the class structure defined as follows:
public class ParamList
{
private List<Param> _param = new List<Param>();
[JsonProperty("Parameters")]
public IReadOnlyCollection<Param> Param { get => _param.AsReadOnly(); }
}
public class Param
{
private List<IntOptions> _intOptions;
private List<BubbleList> _bubbleList;
[JsonProperty("Info")]
public Info? Info { get; }
[JsonProperty("IntOptions")]
public IReadOnlyCollection<IntOptions> IntOptionsVar { get => _intOptions.AsReadOnly(); }
[JsonProperty("BubbleList")]
public IReadOnlyCollection<BubbleList> BubbleListVar { get => _bubbleList.AsReadOnly(); }
}
public class Info
{
public Info(int id, string number)
{
Id = id;
Number = number;
}
[JsonProperty("Id")]
public int Id { get; private set; }
[JsonProperty("No")]
public string Number { get; private set; }
}
public class IntOptions
{
public IntOptions(int value, string valInfo)
{
Value = value;
ValInfo = valInfo;
}
[JsonProperty("Value")]
public int Value { get; private set; }
[JsonProperty("ValInfo")]
public string ValInfo { get; private set; }
}
public class BubbleList
{
private List<SubBubbleList>? _subBubbleList;
public BubbleList(int position)
{
Position = position;
}
[JsonProperty("Position")]
public int Position { get; private set; }
[JsonProperty("SubBubbleList")]
public IReadOnlyCollection<SubBubbleList> SubBubbleListVar { get => _subBubbleList.AsReadOnly(); }
}
public class SubBubbleList
{
public SubBubbleList(int value, string message)
{
Value = value;
Message = message;
}
[JsonProperty("Value")]
public int Value { get; private set; }
[JsonProperty("Message")]
public string Message { get; private set; }
}
I came up with the following de-serializing code which results in an empty list of Param:
try
{
ParamList paramList = JsonConvert.DeserializeObject<ParamList>(readJsonContent);
Console.WriteLine(paramList);
}
This gives me an empty list of Param.
I read a lot of articles explaining about de-serializing a json object, however, could not find one which would solve my use case. I need to understand what am I doing wrong here. I need to have a List<Param> which would then have Info, List<IntOptions>, & List<BubbleList> -> List<SubBubbleList>.
Is this achievable by just de-serializing the json data, or will I have to iterate through individual objects?
you have only getters in your classes. you need setters to assign values from json to c# objects
List<Parameter> Parameters = JsonConvert.DeserializeObject<ParamList>(json).Parameters;
classes
public class ParamList
{
public List<Parameter> Parameters { get; set; }
}
public class Parameter
{
public Info Info { get; set; }
public List<IntOption> IntOptions { get; set; }
public List<BubbleList> BubbleList { get; set; }
}
public class BubbleList
{
public int Position { get; set; }
public List<SubBubbleList> SubBubbleList { get; set; }
}
public class Info
{
public int Id { get; set; }
public string No { get; set; }
}
public class IntOption
{
public int Value { get; set; }
public string ValInfo { get; set; }
}
public class SubBubbleList
{
public int Value { get; set; }
public string Message { get; set; }
}
but if for some reasons you still need readonly you can change ALL your read only classes by moving json property name using this template
public class ParamList
{
[JsonProperty("Parameters")]
private List<Param> _param = new List<Param>();
public IReadOnlyCollection<Param> Param
{
get => _param.AsReadOnly();
}
}

How to return IEnumerable<T> as null

I am having the below ActivitiesDB.cs which is a DBEntity class.
public class ActivitiesDB
{
public IEnumerable<Activity> Activities { get; set; }
}
public class Activity
{
public Guid ActivityId { get ;set; }
public DateTime ActivityDateTime { get; set; }
public DateTime UpdatedDateTime { get; set; }
public IEnumerable<MetaData> MetaData { get; set; }
}
public class MetaData
{
public string Name { get; set; }
public string Value { get; set; }
}
sample data in DB(I am using CosmosDb in backend):
"Activities": [
{
"ActivityId": "4f436d11-7a61-4e7f-b0fb-0f0d5bb6be76",
"ActivityDateTime": "2021-04-30T09:35:35.32Z",
"UpdatedDateTime": "2021-05-03T07:45:21.5115588Z",
"Metadata": [
{
"Name": "name",
"Value": "value"
}
]
},
{
"ActivityId": "659e62c5-4408-42b4-8719-b8c577221d22",
"ActivityDateTime": "2021-04-30T09:35:35.32Z",
"UpdatedDateTime": "2021-05-03T07:45:21.5115588Z",
"Metadata": null
}
]
To display the data, I am having class DisplayActivtiesResponse.cs below:
public class DisplayActivtiesResponse
{
public IEnumerable<DisplayActivity> DisplayActivties{ get; set; }
}
public class DisplayActivity
{
public Guid ActivityId { get ;set; }
public DateTime ActivityDateTime { get; set; }
public DateTime UpdatedDateTime { get; set; }
public IEnumerable<MetaData> MetaData { get; set; }
}
public class MetaData
{
public string Name { get; set; }
public string Value { get; set; }
}
Below is the code to fetch the data from DB:
public async Task<DisplayActivtiesResponse> DisplayActivityAsync(Guid activityId)
{
var feedIterator = this.cosmosReviewRequestContainer.GetItemLinqQueryable<ActivitiesDB>()
.Where(q => q.Activities.Where(x => x.ActivityId == activityId)
.ToFeedIterator();
var requestModel = new ActivitiesDB();
while (feedIterator.HasMoreResults)
{
var items = await feedIterator.ReadNextAsync().ConfigureAwait(false);
requestModel = items.FirstOrDefault();
}
return new DisplayActivtiesResponse
{
DisplayActivties = mapper.Map<IEnumerable<DisplayActivity>>(requestModel);
};
}
MappingProfile.cs:
public class MappingProfile : Profile
{
public MappingProfile()
{
this.CreateMap<Activity, DisplayActivity>().ReverseMap();
}
}
Now, When I am fetching the data from db, I observed that if the metadata is null, I am getting empty array [] instead of null. I still dont know what i am missing from my end. Kindly help me on this.
Set AllowNullCollections to true when initializing:
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.AllowNullCollections = true;
});
or directly in the mapper configuration:
new MapperConfiguration(cfg =>
{
cfg.AllowNullCollections = true;
}

Receiving parameters with FromBody

I have a webservice where I need to receive multiple parameters, one of which is a list.
This is the webservice method:
[HttpPost("complete/{requestId}")]
public IActionResult CompleteRequest([FromBody] RequestComplete requestComplete, int requestId)
{
if (requestId == 0)
{
return BadRequest();
}
if (requestComplete == null)
{
return BadRequest();
}
// execute code
}
The RequestComplete class looks like this:
public class RequestComplete
{
public int RequestId { get; set; }
public int UserId { get; set; }
public string emailCC { get; set; }
public string emailSubject { get; set; }
public string calcsNeeded { get; set; }
public string ssiComment { get; set; }
public List<CompleteFileUpload> completeFiles { get; set; }
}
And the CompleteFileUpload class like this:
public class CompleteFileUpload
{
public int RequestFileId { get; set; }
}
From PostMan I use a post body like this:
{
"calcsNeeded" : "4",
"completeFiles": {"RequestFileId": "384"},
"emailCC" : "test#email.com",
"emailSubject": "subject here",
"ssiComment":"Thanks for your request."
}
My expectation is that the json posted by Postman will be formatted properly to be accepted by the CompleteRequest method. However, it does not. If I remove the completeFiles section of the json, it runs fine.
What am I missing?
The definition of "completeFiles" in the JSON does not define a JSON array, it defines a single object. That JSON would be valid if the definition was:
public class RequestComplete
{
...
public CompleteFileUpload completeFiles { get; set; }
}
Try changing the JSON to:
{
"calcsNeeded" : "4",
"completeFiles": [ {"RequestFileId": "384"}, {"RequestFileId": "123"} ],
"emailCC" : "test#email.com",
"emailSubject": "subject here",
"ssiComment":"Thanks for your request."
}
Hope this helps

Json.Net deserialize JSON objects

I've popped consuming a WebServer returning the Json bellow, and I'm not able to convert it to an object.
Json
{
"success":true,
"data":{
"24486146360":{
"rfid":"123465789456",
"products":[
{
"sale_id":35,
"quantity":2,
"price":"1",
"total":"2",
"unit":"uni",
"sku":14
},
{
"sale_id":36,
"quantity":2,
"price":"2.5",
"total":"5",
"unit":"uni",
"sku":17
}
]
},
"24758345953":{
"rfid":"2129",
"products":[
{
"sale_id":39,
"quantity":1,
"price":"10",
"total":"10",
"unit":"ml",
"sku":19998
}
]
},
"64577015900":{
"rfid":"1934",
"products":[
{
"sale_id":40,
"quantity":1,
"price":"10",
"total":"10",
"unit":"ml",
"sku":19998
}
]
},
"56768990934":{
"rfid":"1746",
"products":[
{
"sale_id":46,
"quantity":1,
"price":"8.00",
"total":"8",
"unit":"UN",
"sku":20
}
]
}
}
}
I used json2sharp to generate a class from the JSON, I then cleaned up the class and was left with the following:
My Class create help for json2sharp
public class Consumo
{
public string rfid { get; set; }
public List<ConsumoProduto> products { get; set; }
}
public class ConsumoProduto
{
public int sale_id { get; set; }
public double quantity { get; set; }
public string price { get; set; }
public string total { get; set; }
public string unit { get; set; }
public int sku { get; set; }
}
public class RetornoConsumo
{
[JsonProperty("success")]
public bool Processado { get; set; }
[JsonProperty("data")]
public List<Consumo> Registro { get; set; }
}
My Problem
how do I convert Json to a valid object using Json.Net?
Test
I tried to do this and I could not
Dictionary<string, RetornoConsumo> _featuredArticles = JsonConvert.DeserializeObject<Dictionary<string, RetornoConsumo>>(json);
In your RetornoConsumo class, the Registro property needs to be a Dictionary<string, Consumo> not a List<Consumo>.
public class RetornoConsumo
{
[JsonProperty("success")]
public bool Processado { get; set; }
[JsonProperty("data")]
public Dictionary<string, Consumo> Registro { get; set; }
}
Then, you need to deserialize the JSON into the RetornoConsumo class:
var data = JsonConvert.DeserializeObject<RetornoConsumo>(json);
Fiddle: https://dotnetfiddle.net/vfhdXp

Parse JSON object in C#

I use JSON.NET and I would like to parse the following object which I get from a WebService. Can someone post an example on how to do that?
#"{""MessageType"":0,
""Message"":""Success"",
""Value"":[
{""listId"":1,
""listName"":""DemoList"",
""itemInList"":[
{
""fromDate"":""\/Date(1228946400000)\/"",
""fromLocation"":null,
""toLocation"":null,
""originalRequest"":""water"",
""creationDate"":""\/Date(1339448400000)\/"",
""typeId"":1
},
{
""fromDate"":null,
""fromLocation"":null,
""toLocation"":null,
""originalRequest"":""gala"",
""creationDate"":""\/Date(1304370000000)\/"",
""typeId"":1
}
]}
]}"
JSON Object
{
"MessageType":0,
"Message":"UserLists",
"Value":
[
{
"listId":1,
"listName":"DemoList",
"itemInList"
[
{
"fromDate":"\/Date(1228946400000)\/",
"fromLocation":null,
"toLocation":null,
"originalRequest":"water",
"creationDate":"\/Date(1339448400000)\/",
"typeId":1
},
{
"fromDate":null,
"fromLocation":null,
"toLocation":null,
"originalRequest":"gala",
"creationDate":"\/Date(1304370000000)\/",
"typeId":1
}
],
"numberOfItems":2
}
]
}
Thanks.
You need to create some entity like this:
public class Entity
{
public int MessageType { get; set; }
public string Message { get; set; }
public List<EntityValue> Value { get; set; }
}
public class EntityValue
{
public int listId { get; set; }
public string listName { get; set; }
public List<ItemInList> itemInList { get; set; }
}
public class ItemInList
{
public DateTime? fromDate { get; set; }
public string fromLocation { get; set; }
public string toLocation { get; set; }
public string originalRequest { get; set; }
public DateTime creationDate { get; set; }
public int typeId { get; set; }
}
The entity must has the same structure like the json data.
And you can call the Method:
JsonConvert.DeserializeObject<Entity>(json);
If it has any exception,you need to adjust the entities until it works.
Please read the below link for parsi in metro style application.
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh770287.aspx

Categories

Resources