C# Web API PUTmethod for Json Multiple Array - c#

I am trying to code a PUT method for a multiple array but I am getting a NULL error.
this is my code inside my controller for valuestory where its child later is Area of Interest and AOI Value Driver:
// PUT: api/ValueStories/5
[ResponseType(typeof(void))]
public async Task<IHttpActionResult> PutValueStory(int id, ValueStory valueStory)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != valueStory.Id)
{
return BadRequest();
}
//To update Value Story Item all the way to
//Area of interest and child layers
var vsid = id;
var vs = (from v in db.ValueStories where v.Id == vsid select v).FirstOrDefault();
//db.Entry(valueStory).State = EntityState.Modified;
if (vs == null)
{
return NotFound();
}
else
{
vs.Id = vsid;
vs.ModifiedDate = DateTime.Now;
//AreaOfInterest and AOIValueDriver START
foreach (var item in vs.AreaOfInterest)
{
var aoi = (from a in db.AreaOfInterests where a.Id == vs.Id select a).FirstOrDefault();
if (aoi != null)
{
aoi.AOIName = item.AOIName;
aoi.Selected = item.Selected;
aoi.Id = vs.Id;
//AOIValueDriver START
foreach (var item2 in aoi.AOIValueDrivers)
{
var aoivd = (from b in db.AOIValueDrivers where b.AOIId == aoi.AOIId select b).FirstOrDefault();
if (aoivd != null)
{
aoivd.Item = item2.Item;
aoivd.SubItem = item2.SubItem;
aoivd.Value = item2.Value;
}
}
//AOIValueDriver EMD
}
}
//AreaOfInterest and AOIValueDriver END
// --------------------------------//
}
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ValueStoryExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
and this is the json parameter that I am trying to pass:
{
"Id": 1,
"ValueStoryName": "Value Story 101",
"Organization": "Charity Foundation",
"Industry": "Education",
"Currency": "$ ",
"AnnualRevenue": 1000,
"AreaOfInterest": [
{
"Id": 1,
"AOIId": 1,
"AOIName": "Supply Chain/ Direct Materials",
"Selected": false,
"AOIValueDrivers": [
{
"AOIId": 1,
"AOIVDId": 1,
"Item": "Negotiate better prices & conditions",
"SubItem": "Automate the process of sourcing of direct materials and integrate it to you ERP and key execution systems",
"Value": 0
}
]
},
{
"Id": 1,
"AOIId": 2,
"AOIName": "Sourcing",
"Selected": true,
"AOIValueDrivers": [
{
"AOIId": 2,
"AOIVDId": 10,
"Item": "Negotiate better prices & conditions",
"SubItem": "Foster supplier competition to reduce pricing and obtain best market value",
"Value": 3
}
]
},
{
"Id": 1,
"AOIId": 3,
"AOIName": "Procurement",
"Selected": true,
"AOIValueDrivers": [
{
"AOIId": 3,
"AOIVDId": 23,
"Item": "Lower costs",
"SubItem": "Provide access to an electronic marketplace of pre-sourced goods and services",
"Value": 3
}
]
},
{
"Id": 1,
"AOIId": 4,
"AOIName": "Accounts Payable",
"Selected": true,
"AOIValueDrivers": [
{
"AOIId": 4,
"AOIVDId": 32,
"Item": "Lower costs",
"SubItem": "Pay on time",
"Value": 3
}
]
},
{
"Id": 1,
"AOIId": 5,
"AOIName": "Working Captila/ Treasury",
"Selected": true,
"AOIValueDrivers": [
{
"AOIId": 5,
"AOIVDId": 37,
"Item": "Free up working capital",
"SubItem": "Capture more early pay discounts and allow suppliers to dynamically select discount rate and payment terms",
"Value": 3
}
]
},
{
"Id": 1,
"AOIId": 6,
"AOIName": "Risk and Compliance",
"Selected": false,
"AOIValueDrivers": [
{
"AOIId": 6,
"AOIVDId": 42,
"Item": "Protect your revenue",
"SubItem": "Proactively monitor and predict supply risks in real time",
"Value": 3
}
]
}
]
}
and the error that I am getting from postman is here
https://ibb.co/jMHmuv
I can't fully understand what does the error mean but I hope that somebody can help me with this.
revised controller code for the PUT method:
// PUT: api/ValueStories/5
[ResponseType(typeof(void))]
public async Task<IHttpActionResult> PutValueStory(int id, ValueStory valueStory)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != valueStory.Id)
{
return BadRequest();
}
//To update Value Story Item all the way to
//Area of interest and child layers
//Business value to you and child layers
//Business value from SAP and child layers
var vs = (from v in db.ValueStories where v.Id.Equals(id) select v).FirstOrDefault();
//db.Entry(valueStory).State = EntityState.Modified;
if (vs != null)
{
vs.ModifiedDate = DateTime.Now;
vs.ValueStoryName = valueStory.ValueStoryName;
vs.Organization = valueStory.Organization;
vs.Location = valueStory.Location;
vs.Industry = valueStory.Industry;
vs.Currency = valueStory.Currency;
vs.AnnualRevenue = valueStory.AnnualRevenue;
vs.MutualActionPlan = valueStory.MutualActionPlan;
vs.Id = valueStory.Id;
}
else
{
return NotFound();
}
//areaofinterest and aoivaluedriver start
foreach (var item in valueStory.AreaOfInterest)
{
var aoi = (from a in db.AreaOfInterests where a.Id == vs.Id select a).FirstOrDefault();
if (aoi != null)
{
aoi.Selected = item.Selected;
aoi.Id = vs.Id;
//aoi.AOIId = aoi.AOIId;
//aoivaluedriver start
foreach (var item2 in item.AOIValueDrivers)
{
var aoivd = (from b in db.AOIValueDrivers where b.AOIId == aoi.AOIId select b).FirstOrDefault();
if (aoivd != null)
{
aoivd.Value = item2.Value;
aoivd.AOIId = aoi.AOIId;
//aoivd.AOIVDId = aoivd.AOIVDId;
}
}
//aoivaluedriver emd
}
}
//areaofinterest and aoivaluedriver end
// --------------------------------//
//}
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ValueStoryExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
revised Json input:
{
"Id": 1,
"ValueStoryName": "Value Story 222",
"Organization": "ABC",
"Industry": 11,
"Location": "Singapore",
"Currency": "P",
"AnnualRevenue":212000,
"MutualActionPlan": "testing789",
"AreaOfInterest": [
{
"AOIId": 1,
"Selected": false,
"AOIValueDrivers": [
{
"AOIVDId": 1,
"Value": 1
},
{
"AOIVDId": 2,
"Value": 2
},
{
"AOIVDId": 3,
"Value": 1
},
{
"AOIVDId": 4,
"Value": 1
},
{
"AOIVDId": 5,
"Value": 1
},
{
"AOIVDId": 6,
"Value": 5
},
{
"AOIVDId": 7,
"Value": 1
},
{
"AOIVDId": 8,
"Value": 1
},
{
"AOIVDId": 9,
"Value": 3
}
]
}
]
}

I managed to get it working by putting additonal condition to my query for aoi and aoivd
//areaofinterest and aoivaluedriver START
foreach (var item in valueStory.AreaOfInterest)
{
var aoi = (from a in db.AreaOfInterests where a.Id == item.Id && a.AOIId == item.AOIId select a).FirstOrDefault();
if (aoi != null)
{
aoi.Selected = item.Selected;
//aoivaluedriver START
foreach (var item2 in item.AOIValueDrivers)
{
var aoivd = (from b in db.AOIValueDrivers where b.AOIId == item2.AOIId && b.AOIVDId == item2.AOIVDId select b).FirstOrDefault();
if (aoivd != null)
{
aoivd.Value = item2.Value;
}
}
//aoivaluedriver END
}
}
//areaofinterest and aoivaluedriver END

Related

C# How to get from json file list of nodes that contains specific key-value

I have a json file like this:
[
{
"key1": {
"find": 5,
"count": 65,
"name": "Parser"
},
"init": {
"key2": {
"find": 5,
"count": 15,
"name": "Some"
},
"arr": [
{
"key2": {
"find": 8,
"count": 32,
"name": "Object"
},
"temp": {
"pay": null
}
}
]
}
},
{
"key3": {
"find": 5,
"count": 23,
"name": "String"
},
"classes": [],
}
]
And I want to get list of all nodes that contains key "find" and value "5". The result have to be:
{
"find": 5,
"count": 65,
"name": "Parser"
},
{
"find": 5,
"count": 15,
"name": "Some"
},
{
"find": 5,
"count": 23,
"name": "String"
}
The difficulty is that the nesting can be any, but I need to get only those nodes that contain key "find" and the value "5" for it. How can I go through the entire file and get the nodes I need?
You can use JToken for this purpose, use the below function to find the nodes.
public void FindNodes(JToken json, string name, string value, List<JToken> nodes)
{
if (json.Type == JTokenType.Object)
{
foreach (JProperty child in json.Children<JProperty>())
{
if (child.Name == name && child.Value.ToString() == value)
{
nodes.Add(child);
}
FindNodes(child.Value, name, value, nodes);
}
}
else if (json.Type == JTokenType.Array)
{
foreach (JToken child in json.Children())
{
FindNodes(child, name, value, nodes);
}
}
}
Use the method in this way,
var json = JsonConvert.DeserializeObject<JToken>(jsonString);
var nodes = new List<JToken>();
FindNodes(json, "find", "5", nodes);

One to many relationship expressed in JSON

I am having a small problem in some LINQ I am writing
public async Task<BookingEntry[]> AuditInvoiceForAPI(BookingSearchFilter filter)
{
if (filter == null)
throw new ArgumentNullException();
using var speedPayDbContext = this.speedPayDbContextFactory();
var results = await speedPayDbContext.spAuditInvoiceForAPI(filter.BookingID, filter.VendorID, filter.InvoiceID).ToArrayAsync();
var BookingResponse = results
.Select(r =>
{
return new BookingEntry()
{
Result = r.Result,
BookingID = r.BookingID,
Balance = r.Balance,
TotalCost = r.TotalCost,
CostDetails =
results.Where(cd => cd.BookingID == r.BookingID)
.Select(a => new Costdetail(a.Amount, a.ChargeCodeID)).ToArray(),
Message = r.Message,
};
})
.ToArray();
return BookingResponse;
here is the result set
BookingId
Result
Message
TotalCost
BillKey
Balance
ChargeCodeId
amount
8446670
0
Success
498.54
8446670
89.8000
11
75.00
8446670
0
Success
498.54
8446670
89.8000
14
14.80
I am getting dup in the JSON which I can understand why. There are indeed two rows returned one booking entry with two costdetails.
Can someone please help me with get rid of the dup?
Its probably as simple as I don't understand SelectMany.
This is in essence a simple join first 6 columns are the header and the last two are the detail records and you can see that the bookingID is what they are joined on.
Thanks very much
{
"bookingID": "8446670",
"result": "0",
"message": "Success",
"totalCost": 498.54,
"balance": 89.8,
"costDetails": [
{
"chargeCodeID": 11,
"amount": 75
},
{
"chargeCodeID": 14,
"amount": 14.8
}
]
},
{
"bookingID": "8446670",
"result": "0",
"message": "Success",
"totalCost": 498.54,
"balance": 89.8,
"costDetails": [
{
"chargeCodeID": 11,
"amount": 75
},
{
"chargeCodeID": 14,
"amount": 14.8
}
]
}
]

How to put lists together into json in C#?

I have this code here in C# (just a sample):
var list1 = ( from x
join y
select new
{
id, name
});
var counta = list1.count;
if (counta > 0)
{
for (var i = 0; i < counta; i++)
{
var userid = list1[i].id;
var user = user.Where(a => a.id == user).Select(a => a.userid).FirstOrDefault();
var list2 = (
from f
join g.Where(a => a.userid = user)select new
{
hourId, hourName
}
);
if (list2 > 0)
{
foreach (var product in list2)
{
var list3 = (
from p.
where (a => a.id == user)join q.
where (a => a.id == user)select new
{
productId, productName
});
}
}
}
}
Here is list1,list2,list3 relationship: list1 has many list2, list2 has many list3 and here is the JSON that I expected to return:
[
{
"list1": {
"id": 1,
"name": "Adam",
"list2": [
{
"hourId": 1,
"hourName": "08:00",
"list3": [
{
"productId": 1,
"productName": "Candy"
},
{
"productId": 2,
"productName": "Cookie"
}
]
},
{
"hourId": 2,
"hourName": "09:00",
"list3": [
{
"productId": 1,
"productName": "Candy"
},
{
"productId": 2,
"productName": "Cookie"
}
]
}
]
}
}
]
So my question here is how can I put list1, list2, list3 together to return the below JSON? Do I have to join 3 lists in LINQ again?
Thank you!

Multiple max/min aggregation in ElasticSearch (C# Nest)

I have been searching here and I didn't find anything similar... However I apologize in advanced if it have escaped me, and I hope you can help out finding the correct direction.
I was looking for a way to implement the following in NEST C#:
"aggs": {
"sys_created_on_max": {
"max": {
"field": "sys_created_on"
}
},
"sys_created_on_min":{
"min": {
"field": "sys_created_on"
}
},
"sys_updated_on_max": {
"max": {
"field": "sys_updated_on"
}
},
"sys_updated_on_min":{
"min": {
"field": "sys_updated_on"
}
}
}
Meaning that I want to perform, in the same statement:
Max and Min aggregated value for "sys_created_on" field
and also
Max and Min aggregated value for "sys_updated_on" field
Thanks!
What you want is Stats Aggregation.
Here is an example input/output
INPUT
GET devdev/redemption/_search
{
"size": 0,
"aggs": {
"a1": {
"stats": {
"field": "reporting.campaign.endDate"
}
}
}
}
Result
{
"took": 97,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 146,
"max_score": 0,
"hits": []
},
"aggregations": {
"a1": {
"count": 11,
"min": 1443675599999,
"max": 1446353999999,
"avg": 1445607818180.818,
"sum": 15901685999989,
"min_as_string": "1443675599999",
"max_as_string": "1446353999999",
"avg_as_string": "1445607818180",
"sum_as_string": "15901685999989"
}
}
}
I've figured it out. In case of someone have the same doubt:
1) create a AggregationContainerDescriptor:
Func<AggregationContainerDescriptor<dynamic>, IAggregationContainer> aggregationsSelector = null;
2) Fill it up:
foreach (var field in requestList)
{
aggregationsSelector += ms => ms.Max(field.MaxAggregationAlias, mx => mx.Field(field.Name))
.Min(field.MinAggregationAlias, mx => mx.Field(field.Name));
}
3) Query it:
var esResponse = _esClient.Raw.Search<dynamic>(indexName.ToLower(), new PostData<dynamic>(jsonStr), null);
Cheers!

C# Backend Pro Is needed ! Data weirdness

Here's my Code
public Tournament Read(int id)
{
using (var context = new DragonLairContext())
{
Tournament tournament = context.Tournaments
.Include(a => a.Game)
.Include(g => g.Game.Genre)
.Include(b => b.Groups.Select(g => g.Teams))
.Include(k => k.Groups.Select(y => y.Teams.Select(l => l.Players)))
.Include(c => c.TournamentType)
.FirstOrDefault(d => d.Id == id);
return tournament;
}
}
I'm using API and due to serialization issues, I need to convert my entities to DTOobject.
Here's a snippet from the Dto Converter
public override DTOTournament Convert(Tournament t)
{
if (t.Game == null || t.TournamentType == null || t.Groups == null) throw new ArgumentException("Missing some data");
DTOTournament dtoTournament = new DTOTournament();
List<DTOGroup> dtoGroups = new List<DTOGroup>();
DTOTournamentType dtoTournamentType = new DTOTournamentType() { Id = t.TournamentType.Id, Type = t.TournamentType.Type };
foreach (var group in t.Groups)
{
if (group.Teams == null) return dtoTournament;
List<DTOTeam> dtoTeams = new List<DTOTeam>();
foreach (var team in group.Teams)
{
List<DTOPlayer> dtoPlayers = new List<DTOPlayer>();
if (team.Players == null) return dtoTournament;
foreach (var player in team.Players)
{
dtoPlayers.Add(new DTOPlayer() { Id = player.Id, Name = player.Name });
}
dtoTeams.Add(new DTOTeam()
{
Id = team.Id,
Name = team.Name,
Win = team.Win,
Loss = team.Loss,
Draw = team.Draw,
DtoPlayers = dtoPlayers
});
}
dtoGroups.Add(new DTOGroup()
{
Id = group.Id,
Name = group.Name,
DtoTeams = dtoTeams,
DtoTournament = dtoTournament
});
}
dtoTournament.DTOTournamentType = dtoTournamentType;
dtoTournament.Id = t.Id;
dtoTournament.Name = t.Name;
dtoTournament.StartDate = t.StartDate;
dtoTournament.DtoGroups = dtoGroups;
dtoTournament.DtoGame = new DTOGame() { Id = t.Game.Id, Name = t.Game.Name, DtoGenre = new DTOGenre() { Id = t.Game.Genre.Id, Name = t.Game.Genre.Name } };
return dtoTournament;
}
Here's the Json
{
"$id": "1",
"Id": 1,
"Name": "I'm a Tournament",
"StartDate": "2015-12-08T00:00:00",
"DTOTournamentType": {
"$id": "2",
"Id": 1,
"Type": "I'm type 2vs2",
"DtoTournaments": null
},
"DtoGroups": [
{
"$id": "3",
"Id": 1,
"Name": "I'm a Group",
"DtoTournament": {
"$ref": "1"
},
"DtoTeams": [
{
"$id": "4",
"Id": 1,
"Draw": 0,
"Loss": 0,
"Win": 0,
"Name": "I'm a Team",
"DtoPlayers": [
{
"$id": "5",
"Id": 1,
"Name": "I'm a Group",
"DtoTeams": null
}
],
"DtoGroups": null
},
{
"$id": "6",
"Id": 2,
"Draw": 0,
"Loss": 0,
"Win": 0,
"Name": "I'm a Team",
"DtoPlayers": [
{
"$id": "7",
"Id": 1,
"Name": "I'm a Group",
"DtoTeams": null
}
],
"DtoGroups": null
}
]
}
],
"DtoGame": {
"$id": "8",
"Id": 1,
"Name": "Im a Game - Wars",
"DtoGenre": {
"$id": "9",
"Id": 1,
"Name": "I'm Genre Roleplaying",
"DtoGames": null
},
"DtoTournaments": null
}
}
My DB contains 3 players - note converted to json
[
{
"$id": "1",
"Id": 1,
"Name": "I'm player Søren",
"DtoTeams": [
{
"$id": "2",
"Id": 1,
"Draw": 0,
"Loss": 0,
"Win": 0,
"Name": "I'm a Team",
"DtoPlayers": null,
"DtoGroups": null
}
]
},
{
"$id": "3",
"Id": 2,
"Name": "I'm player Mark",
"DtoTeams": [
{
"$id": "4",
"Id": 1,
"Draw": 0,
"Loss": 0,
"Win": 0,
"Name": "I'm a Team",
"DtoPlayers": null,
"DtoGroups": null
}
]
},
{
"$id": "5",
"Id": 3,
"Name": "I'm player René",
"DtoTeams": [
{
"$id": "6",
"Id": 2,
"Draw": 0,
"Loss": 0,
"Win": 0,
"Name": "I'm a Team",
"DtoPlayers": null,
"DtoGroups": null
}
]
}
]
So my problem which I really can't figure out. How come my DtoPlayer.Name has the same name as DtoGroup.Name. Have a look at my includes.
This exception is thrown because you are trying to use a property that was not retrieved from the database after you have disposed the database context. You can see the data while debugging because the variable is defined inside the using scope. You should also fetch the Teams on Group class.
using (var context = new DragonLairContext())
{
Tournament tournament = context.Tournaments
.Include(a => a.Game)
.Include(g => g.Game.Genre)
.Include(b => b.Groups.Select(g => g.Teams))
.Include(c => c.TournamentType)
.FirstOrDefault(d => d.Id == id);
return tournament;
}
Since you said that you could see data in debug mode, try this method.
Tournament tournament = context.Tournaments
.Include(a => a.Game)
.Include(g => g.Game.Genre)
.Include(b => b.Groups)
.Include(c => c.TournamentType).ToList()
.FirstOrDefault(d => d.Id == id);

Categories

Resources