I am working with some API in C# Winforms. Getting response successfully as a json. The problem is that when I deserialize it the output is just a big string like this:
{"orders": [
{
"id": 155971090,
"date_created": "2021-06-18T06:16:31.36202+03:00",
"date_modified": "2021-06-19T15:10:45.567327+03:00",
"client_first_name": "Олександр",
"client_second_name": "",
"client_last_name": "Бандура",
"client_id": 133374423,
"client_avg_rating": 5.0,
"email": "bandurao#ukr.net",
"phone": "+380996461421",
"delivery_option": {
"id": 13662439,
"name": "Доставка \"Нова Пошта\""
},
"delivery_address": "Ананьїв, №1: вул. Незалежності, 19",
"delivery_provider_data": {
"provider": "nova_poshta",
"type": "W2W",
"sender_warehouse_id": null,
"recipient_warehouse_id": "4049834c-e1c2-11e3-8c4a-0050568002cf",
"declaration_number": null
},
"delivery_cost": 0,
"payment_option": {
"id": 7451891,
"name": "Передоплата"
},
"payment_data": null,
"price": "169,72 грн.",
"full_price": "169,72 грн.",
"client_notes": "",
"products": [
{
"id": 1430223923,
"external_id": "513.4769",
"name": "Ремень 4L-240",
"name_multilang": {
"ru": "Ремень 4L-240",
"uk": "Ремінь 4L-240"
},
"sku": "4769",
"price": "21,76 грн.",
"quantity": 1.0,
"measure_unit": "шт.",
"image": "https://images.ua.prom.st/3169964688_w100_h100_remen-4l-240.jpg",
"url": "https://teomax.com.ua/p1430223923-remen-240.html",
"total_price": "21,76 грн.",
"cpa_commission": {
"amount": "1.00"
}
},
{
"id": 1430222732,
"external_id": "512.4825",
"name": "Ремень 240 PJ3",
"name_multilang": {
"ru": "Ремень 240 PJ3",
"uk": "Ремінь 240 PJ3"
},
"sku": "4825",
"price": "48,96 грн.",
"quantity": 1.0,
"measure_unit": "шт.",
"image": "https://images.ua.prom.st/3170015051_w100_h100_remen-240-pj3.jpg",
"url": "https://teomax.com.ua/p1430222732-remen-240-pj3.html",
"total_price": "48,96 грн.",
"cpa_commission": {
"amount": "2.25"
}
},
{
"id": 1430230819,
"external_id": "297.2885",
"name": "Масло \"двухтактное\" (2Т), 1л",
"name_multilang": {
"ru": "Масло \"двухтактное\" (2Т), 1л",
"uk": "Масло \"двотактне\" (2Т), 1л"
},
"sku": "2885",
"price": "99 грн.",
"quantity": 1.0,
"measure_unit": "шт.",
"image": "https://images.ua.prom.st/3169999571_w100_h100_maslo-dvuhtaktnoe-2t.jpg",
"url": "https://teomax.com.ua/p1430230819-maslo-dvuhtaktnoe.html",
"total_price": "99 грн.",
"cpa_commission": {
"amount": "4.55"
}
}
],
"status": "delivered",
"status_name": "Выполнен",
"source": "portal",
"price_with_special_offer": null,
"special_offer_discount": null,
"special_offer_promocode": null,
"has_order_promo_free_delivery": false,
"cpa_commission": {
"amount": "7.80",
"is_refunded": false
},
"utm": null
},
{
"id": 155896081,
"date_created": "2021-06-17T13:11:40.241146+03:00",
"date_modified": "2021-06-17T13:42:55.021203+03:00",
"client_first_name": "Антон",
"client_second_name": "",
"client_last_name": "Подосельник",
"client_id": 133299120,
"client_avg_rating": 5.0,
"email": "a.n.podoselnik#gmail.com",
"phone": "+380992764450",
"delivery_option": {
"id": 13662439,
"name": "Доставка \"Нова Пошта\""
},
"delivery_address": "Киев, №132 (до 30 кг): просп. Леся Курбаса, 16-А",
"delivery_provider_data": {
"provider": "nova_poshta",
"type": "W2W",
"sender_warehouse_id": null,
"recipient_warehouse_id": "51b6c251-7a06-11e4-acce-0050568002cf",
"declaration_number": null
},
"delivery_cost": 0,
"payment_option": {
"id": 7451890,
"name": "Готівкою"
},
"payment_data": null,
"price": "254,30 грн.",
"full_price": "254,30 грн.",
"client_notes": "",
"products": [
{
"id": 1430208419,
"external_id": "250.4391",
"name": "Подшипник шариковый 12*30*8",
"name_multilang": {
"ru": "Подшипник шариковый 12*30*8",
"uk": "Підшипник кульковий 12*30*8"
},
"sku": "4391",
"price": "50,86 грн.",
"quantity": 5.0,
"measure_unit": "шт.",
"image": "https://images.ua.prom.st/3169911780_w100_h100_podshipnik-sharikovyj-12308.jpg",
"url": "https://teomax.com.ua/p1430208419-podshipnik-sharikovyj-12308.html",
"total_price": "254,30 грн.",
"cpa_commission": {
"amount": "5.08"
}
}
],
"status": "canceled",
"status_name": "Отменен",
"source": "portal",
"price_with_special_offer": null,
"special_offer_discount": null,
"special_offer_promocode": null,
"has_order_promo_free_delivery": false,
"cpa_commission": {
"amount": "5.08",
"is_refunded": true
},
"utm": null
},
{
"id": 155881650,
"date_created": "2021-06-17T11:36:11.87828+03:00",
"date_modified": "2021-06-17T13:10:11.527256+03:00",
"client_first_name": "Антон",
"client_second_name": "",
"client_last_name": "Подосельник",
"client_id": 133299120,
"client_avg_rating": 5.0,
"email": "a.n.podoselnik#gmail.com",
"phone": "+380992764450",
"delivery_option": {
"id": 13662439,
"name": "Доставка \"Нова Пошта\""
},
"delivery_address": "Киев, №132 (до 30 кг): просп. Леся Курбаса, 16-А",
"delivery_provider_data": {
"provider": "nova_poshta",
"type": "W2W",
"sender_warehouse_id": null,
"recipient_warehouse_id": "51b6c251-7a06-11e4-acce-0050568002cf",
"declaration_number": null
},
"delivery_cost": 0,
"payment_option": {
"id": 7451890,
"name": "Готівкою"
},
"payment_data": null,
"price": "305,16 грн.",
"full_price": "305,16 грн.",
"client_notes": "",
"products": [
{
"id": 1430208419,
"external_id": "250.4391",
"name": "Подшипник шариковый 12*30*8",
"name_multilang": {
"ru": "Подшипник шариковый 12*30*8",
"uk": "Підшипник кульковий 12*30*8"
},
"sku": "4391",
"price": "50,86 грн.",
"quantity": 6.0,
"measure_unit": "шт.",
"image": "https://images.ua.prom.st/3169911780_w100_h100_podshipnik-sharikovyj-12308.jpg",
"url": "https://teomax.com.ua/p1430208419-podshipnik-sharikovyj-12308.html",
"total_price": "305,16 грн.",
"cpa_commission": {
"amount": "6.10"
}
}
],
"status": "canceled",
"status_name": "Отменен",
"source": "portal",
"price_with_special_offer": null,
"special_offer_discount": null,
"special_offer_promocode": null,
"has_order_promo_free_delivery": false,
"cpa_commission": {
"amount": "6.10",
"is_refunded": true
},
"utm": null
}
]}
My function to get this is like this:
public IRestResponse GetOrders()
{
var connection = new RestClient("https://my.prom.ua/api/v1/");
connection.UseNewtonsoftJson();
var request = new RestRequest("orders/list", Method.GET, DataFormat.None);
request.AddHeader("authorization", "Bearer token");
var response = connection.Get(request);
//var things = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.Content);
Console.WriteLine(response.Content);
return response;
}
Then I tried to make json object out of it and deserialize:
var jsonString = JToken.Parse(data.Content);
var obj = JObject.Parse(jsonString.ToString());
How can I make key value pair out of this and be able to put data into a db table?
Related
I'm trying to pull some data but it doesn't parse as json, how can i do this, is there anyone who can throw it as code?
my code
var begendurum = await client.GetStringAsync("https://eu.mspapis.com/profilegeneratedcontent/v2/profiles/" + gonderilecek + "/games/j68d/content");
var jsonContent = JObject.Parse(begendurum);
var sondurum = jsonContent[0]["id"].ToString();
Console.Write(sondurum);
json body:
[{
"addedDate": "2021-03-21T09:15:36.6030275+00:00",
"complexity": 0,
"defaultSnapshotType": "snapshot",
"gameId": "j68d",
"id": "4037c9a6ef8e45f18094bfaa570d2977",
"lastEditedDate": "2021-03-21T09:15:36.8996736+00:00",
"lifecycleStatus": "Active",
"owner": "00037853cc134d4cbe970b6aedebe21d",
"participantIds": ["00037853cc134d4cbe970b6aedebe21d"],
"privacyStatus": "Public",
"publishedDate": "2021-03-21T09:15:36.8996736+00:00",
"type": "WAYD",
"resources": [{
"id": "profiles/00037853cc134d4cbe970b6aedebe21d/j68d/wayd/4037c9a6ef8e45f18094bfaa570d2977/437e53a188414c7b96058a15790f660d",
"type": "PgcV1"
}]
}, {
"addedDate": "2021-03-21T09:13:06.0389296+00:00",
"complexity": 0,
"defaultSnapshotType": "snapshot",
"gameId": "j68d",
"id": "55335bca6496404587f90e0d4a1adb24",
"lastEditedDate": "2021-03-21T09:13:06.2070069+00:00",
"lifecycleStatus": "Active",
"owner": "00037853cc134d4cbe970b6aedebe21d",
"participantIds": ["00037853cc134d4cbe970b6aedebe21d"],
"privacyStatus": "Public",
"publishedDate": "2021-03-21T09:13:06.2070069+00:00",
"type": "WAYD",
"resources": [{
"id": "profiles/00037853cc134d4cbe970b6aedebe21d/j68d/wayd/55335bca6496404587f90e0d4a1adb24/37d1d9eb02a24842bd3f10b50bca2213",
"type": "PgcV1"
}]
}, {
"addedDate": "2021-03-21T08:58:37.6752327+00:00",
"complexity": 0,
"defaultSnapshotType": "snapshot",
"gameId": "j68d",
"id": "aa1f7e060c88418f9c7815665922d304",
"lastEditedDate": "2021-03-21T08:58:38.1642128+00:00",
"lifecycleStatus": "Active",
"owner": "00037853cc134d4cbe970b6aedebe21d",
"participantIds": ["00037853cc134d4cbe970b6aedebe21d"],
"privacyStatus": "Public",
"publishedDate": "2021-03-21T08:58:38.1642128+00:00",
"type": "WAYD",
"resources": [{
"id": "profiles/00037853cc134d4cbe970b6aedebe21d/j68d/wayd/aa1f7e060c88418f9c7815665922d304/6333938ca3114a56bcb150cd7b1d9bd5",
"type": "PgcV1"
}]
}, {
"addedDate": "2021-03-21T08:19:08.0288282+00:00",
"complexity": 0,
"defaultSnapshotType": "full",
"gameId": "j68d",
"id": "083b37b1c18c49228771e16183a88436",
"lastEditedDate": "2021-03-21T08:19:08.0288282+00:00",
"lifecycleStatus": "Active",
"owner": "00037853cc134d4cbe970b6aedebe21d",
"participantIds": [],
"privacyStatus": "Public",
"publishedDate": "2021-03-21T08:19:08.0288282+00:00",
"type": "avatar",
"resources": [{
"id": "profiles/00037853cc134d4cbe970b6aedebe21d/j68d/avatar/083b37b1c18c49228771e16183a88436/ad8ff2491104489da5a98ea31ee02fe4",
"type": "PgcV1"
}, {
"id": "profiles/00037853cc134d4cbe970b6aedebe21d/j68d/avatar/083b37b1c18c49228771e16183a88436/9e0298665ae6446ab80f8fe9bfb43a54.png",
"type": "face"
}, {
"id": "profiles/00037853cc134d4cbe970b6aedebe21d/j68d/avatar/083b37b1c18c49228771e16183a88436/6caeef28c90846bda5cf9a71470c2be0.png",
"type": "full"
}]
}]
Use Json.Parse(begendurum);
var begendurum = await client.GetStringAsync("https://eu.mspapis.com/profilegeneratedcontent/v2/profiles/" + gonderilecek + "/games/j68d/content");
var jsonContent = Json.Parse(begendurum);
var sondurum = jsonContent[0]["id"].ToString();
Console.Write(sondurum);
Intro to the problem
I have two different Azure AD B2C tenants one for dev and another for production. Both with two Applications a ROPC_AUTH App and an API app.
Both tenants have an ROPC User Flow.
Both tenants have the same subscription Id and the same Resource Group.
I use these tenants for Login, Registration (using GraphAPI POST), and Reset password (using GraphAPI PATCH).
Everything works ok for Login and Registration configuring Authentication and GraphAPI in my backend. However, Reset Password only works for one of my Tenant configurations; I'm getting 403 Insufficient Privileges for the other.
Configurations
The following are the manifests for the two apps in both tenants.
Tenant 1 API App Manifest
{
"id": "581c1a83-ff0c-49ed-8ace-aa5b63e9ea44",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": false,
"appId": "xxxxdf64-9136-4d2b-xxxx-e02ffxxxxe36",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2019-12-06T14:31:53Z",
"groupMembershipClaims": null,
"identifierUris": [
"https://domain-1.onmicrosoft.com/api"
],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "SameNameAPI",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [
{
"adminConsentDescription": "Read User Files",
"adminConsentDisplayName": "Read User Files",
"id": "38115032-56b3-xxxx-9d81-xxxx039xx73f",
"isEnabled": true,
"lang": null,
"origin": "Application",
"type": "Admin",
"userConsentDescription": "Read User Files",
"userConsentDisplayName": "Read User Files",
"value": "Files.Read"
}
],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2020-12-11T20:10:26.76Z",
"keyId": "d08800f2-ef0b-490d-9905-44fa82c1eab3",
"startDate": "2019-12-11T20:10:40.672Z",
"value": null,
"createdOn": "2019-12-11T20:10:23.7962051Z",
"hint": "U9L",
"displayName": "clientCreator"
}
],
"preAuthorizedApplications": [],
"publisherDomain": "domain-1.onmicrosoft.com",
"replyUrlsWithType": [],
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "37f7f235-527c-4136-accd-4a02d197296e",
"type": "Scope"
},
{
"id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
"type": "Scope"
},
{
"id": "dc5007c0-2d7d-4c42-879c-2dab87571379",
"type": "Role"
},
{
"id": "656f6061-f9fe-4807-9708-6a2e0934df76",
"type": "Role"
},
{
"id": "1b0c317f-dd31-4305-9932-259a8b6e8099",
"type": "Role"
},
{
"id": "65319a09-a2be-469d-8782-f6b07debf789",
"type": "Role"
},
{
"id": "405a51b5-8d8d-430b-9842-8be4b0e9f324",
"type": "Role"
},
{
"id": "09850681-111b-4a89-9bed-3f2cae46d706",
"type": "Role"
},
{
"id": "df021288-bdef-4463-88db-98f22de89214",
"type": "Role"
},
{
"id": "741f803b-c850-494e-b5df-cde7c675a1ca",
"type": "Role"
}
]
},
{
"resourceAppId": "00000002-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "5778995a-e1bf-45b8-affa-663a9f3f4d04",
"type": "Role"
},
{
"id": "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175",
"type": "Role"
}
]
},
{
"resourceAppId": "xxxxdf64-9136-4d2b-xxxx-e02ffxxxxe36",
"resourceAccess": [
{
"id": "38115032-56b3-xxxx-9d81-xxxx039xx73f",
"type": "Scope"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null,
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
Tenant 2 API App Manifest
{
"id": "ebexxxx-xxxx-41aa-80d4-512xxxxxx3ff",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": false,
"appId": "e633f406-xxxx-4c7a-85af-xxxxxxxxx436",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2020-06-05T16:19:02Z",
"groupMembershipClaims": null,
"identifierUris": [
"https://domain-2.onmicrosoft.com/api"
],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "SameNameAPI",
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [
{
"adminConsentDescription": "Read User Files",
"adminConsentDisplayName": "Read User Files",
"id": "7b95e412-c753-4611-xxxx-xxxxx7aa4d78",
"isEnabled": true,
"lang": null,
"origin": "Application",
"type": "Admin",
"userConsentDescription": "Read User Files",
"userConsentDisplayName": "Read User Files",
"value": "Files.Read"
}
],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [
{
"customKeyIdentifier": null,
"endDate": "2299-12-31T03:00:00Z",
"keyId": "99df4466-e1e7-4279-9699-063efacfbed7",
"startDate": "2020-06-05T16:45:24.082Z",
"value": null,
"createdOn": "2020-06-05T16:45:25.2186779Z",
"hint": "9b_",
"displayName": "clientCreator"
}
],
"preAuthorizedApplications": [],
"publisherDomain": "sgmembershipb2bdev.onmicrosoft.com",
"replyUrlsWithType": [],
"requiredResourceAccess": [
{
"resourceAppId": "e633f406-xxxx-4c7a-85af-xxxxxxxxx436",
"resourceAccess": [
{
"id": "7b95e412-c753-4611-xxxx-xxxxx7aa4d78",
"type": "Scope"
}
]
},
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "37f7f235-527c-4136-accd-4a02d197296e",
"type": "Scope"
},
{
"id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
"type": "Scope"
},
{
"id": "dc5007c0-2d7d-4c42-879c-2dab87571379",
"type": "Role"
},
{
"id": "656f6061-f9fe-4807-9708-6a2e0934df76",
"type": "Role"
},
{
"id": "1b0c317f-dd31-4305-9932-259a8b6e8099",
"type": "Role"
},
{
"id": "65319a09-a2be-469d-8782-f6b07debf789",
"type": "Role"
},
{
"id": "405a51b5-8d8d-430b-9842-8be4b0e9f324",
"type": "Role"
},
{
"id": "09850681-111b-4a89-9bed-3f2cae46d706",
"type": "Role"
},
{
"id": "df021288-bdef-4463-88db-98f22de89214",
"type": "Role"
},
{
"id": "741f803b-c850-494e-b5df-cde7c675a1ca",
"type": "Role"
}
]
},
{
"resourceAppId": "00000002-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "5778995a-e1bf-45b8-affa-663a9f3f4d04",
"type": "Role"
},
{
"id": "78c8a3c8-a07e-4b9e-af1b-b5ccab50a175",
"type": "Role"
}
]
}
],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null,
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
Tenant 1 Auth App Manifest
{
"id": "5a6e70fe-xxx-4687-b77c-xxxxxxxxx3cf",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": true,
"appId": "877fc335-xxxx-xxx-b175-xxxxxxxxxddb",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2019-12-09T13:09:50Z",
"groupMembershipClaims": null,
"identifierUris": [],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "ropc_auth2",
"oauth2AllowIdTokenImplicitFlow": false,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [],
"preAuthorizedApplications": [],
"publisherDomain": "domain-1.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "https://login.microsoftonline.com/tfp/oauth2/nativeclient",
"type": "InstalledClient"
},
{
"url": "https://domain-1.b2clogin.com/tfp/oauth2/nativeclient",
"type": "InstalledClient"
},
{
"url": "urn:ietf:wg:oauth:2.0:oob",
"type": "InstalledClient"
}
],
"requiredResourceAccess": [],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null,
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
Tenant 2 Auth App Manifest
{
"id": "7c3d8eeb-xxxx-xxxx-b901-xxxxxxxxxe07",
"acceptMappedClaims": null,
"accessTokenAcceptedVersion": 2,
"addIns": [],
"allowPublicClient": true,
"appId": "26c414be-xxxx-xxxx-b55d-xxxxxxxxxc40",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2020-06-05T15:08:34Z",
"groupMembershipClaims": null,
"identifierUris": [],
"informationalUrls": {
"termsOfService": null,
"support": null,
"privacy": null,
"marketing": null
},
"keyCredentials": [],
"knownClientApplications": [],
"logoUrl": null,
"logoutUrl": null,
"name": "ROPC_Auth_app",
"oauth2AllowIdTokenImplicitFlow": false,
"oauth2AllowImplicitFlow": true,
"oauth2Permissions": [],
"oauth2RequirePostResponse": false,
"optionalClaims": null,
"orgRestrictions": [],
"parentalControlSettings": {
"countriesBlockedForMinors": [],
"legalAgeGroupRule": "Allow"
},
"passwordCredentials": [],
"preAuthorizedApplications": [],
"publisherDomain": "domain-2.onmicrosoft.com",
"replyUrlsWithType": [
{
"url": "urn:ietf:wg:oauth:2.0:oob",
"type": "InstalledClient"
},
{
"url": "https://domain-2.b2clogin.com/tfp/oauth2/nativeclient",
"type": "InstalledClient"
},
{
"url": "https://login.microsoftonline.com/tfp/oauth2/nativeclient",
"type": "InstalledClient"
}
],
"requiredResourceAccess": [],
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADandPersonalMicrosoftAccount",
"tags": [],
"tokenEncryptionKeyId": null,
"verifiedPublisher": {
"displayName": null,
"verifiedPublisherId": null,
"addedDateTime": null
}
}
Usage
GraphAPI Client configuration
// Startup.cs --> ConfigureServices
services.AddScoped<IB2CGraphClient>(provider =>
{
var conf = provider.GetService<IConfigurationRoot>();
var section = conf.GetSection("AzureAd");
B2CGraphClient client = new B2CGraphClient(section.GetValue<string>("ClientId"),
section.GetValue<string>("ClientSecret"), section.GetValue<string>("Domain"));
return client;
});
User PATCH method
// GraphClient.cs
private async Task<string> SendGraphPatchRequest(string api, string json)
{
AuthenticationResult result = await
authContext.AcquireTokenAsync(Globals.aadGraphResourceId, credential);
HttpClient http = new HttpClient();
string url = Globals.aadGraphEndpoint + tenant + api + "?" + Globals.aadGraphVersion;
HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), URL);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await http.SendAsync(request);
if (!response.IsSuccessStatusCode)
{
string error = await response.Content.ReadAsStringAsync();
object formatted = JsonConvert.DeserializeObject(error);
throw new WebException("Error Calling the Graph API: \n" + JsonConvert.SerializeObject(formatted, Formatting.Indented));
}
return await response.Content.ReadAsStringAsync();
}
I have debugged these lines of codes, and changing the configuration in the app.settings is executing these methods with the correct tenant information.
Request and Response
Request Using Tenant 1
{
Method: PATCH,
RequestUri: 'https://graph.windows.net/domain-1.onmicrosoft.com/users/35761bb2-8729-xxxx-xxxx-xxxxxxxxxfe9?api-version=1.6',
Version: 1.1,
Content: System.Net.Http.StringContent,
Headers:
{
Authorization: Bearer some_token
Request-Context: appId=cid-v1:d6b30135-xxxx-xxxx-b5e2-xxxxxxxxxacf
Request-Id: |fbde7acc88133b4ab15e1ca11cd1cb64.xxxxxxxxxx.
traceparent: 00-fbde7acc88133b4ab15e1caxxxxxcb64-a99xxxxx8cfb9e4c-00
Content-Type: application/json; charset=utf-8
Content-Length: 172
}}
Token Payload Tenant 1
{
"aud": "https://graph.windows.net/",
"iss": "https://sts.windows.net/fa11ae53-fc0b-xxx-xxxx-xxxxxxxxx48a/",
"iat": 1592416988,
"nbf": 1592416988,
"exp": 1592420888,
"aio": "42dgYDDxxxxxx4Ut954+Lpope+noSwA=",
"appid": "d7fddf64-xxxx-4d2b-xxxx-xxxxxxxxxe36",
"appidacr": "1",
"idp": "https://sts.windows.net/fa11ae53-fc0b-xxxx-a575-xxxxxxxx48a/",
"oid": "b4eb0d70-2ad1-xxxx-a5a1-xxxxxxxxdfa",
"roles": [
"Directory.Read.All",
"Directory.ReadWrite.All"
],
"sub": "b4eb0d70-xxxx-4c37-xxxx-xxxxxxxxdfa",
"tenant_region_scope": "NA",
"tid": "fa11ae53-fc0b-xxxxx-xxxx-xxxxxxxx48a",
"uti": "xxxxxxxxxxxxxxxxbAA",
"ver": "1.0"
}
Response Using Tennant 1
{
StatusCode: 204,
ReasonPhrase: 'No Content',
Version: 1.1,
Content: System.Net.Http.HttpConnectionResponseContent,
Headers: {...}
}
Request Using Tenant 2
{
Method: PATCH,
RequestUri: 'https://graph.windows.net/domain-2.onmicrosoft.com/users/59ef7da0-xxxx-xxxx-8b05-xxxxxxxxxd13?api-version=1.6',
Version: 1.1,
Content: System.Net.Http.StringContent,
Headers:
{
Authorization: Bearer some_token
Request-Context: appId=cid-v1:d6b30135-b6ac-xxxx-b5e2-xxxxxxxxxacf
Request-Id: |8d281xxxxxxxxx4acef74298ec03dd1.79867ebb617a364c.
traceparent: 00-8d28xxxxxxxxb44acef74298ec03dd1-79867ebb617a364c-00
Content-Type: application/json; charset=utf-8
Content-Length: 172
}
}
Token Payload Tenant 2
{
"aud": "https://graph.windows.net/",
"iss": "https://sts.windows.net/06b0c6f1-7524-xxxx-xxxx-xxxxxxxxx731/",
"iat": 1592418325,
"nbf": 1592418325,
"exp": 1592422225,
"aio": "42dgYGxxxxxxxxxx8C3BWc6r6fbAwA=",
"appid": "e633f406-xxxx-4c7a-xxxx-xxxxxxxxx436",
"appidacr": "1",
"idp": "https://sts.windows.net/06b0c6f1-7524-xxxx-88be-xxxxxxxx731/",
"oid": "12d9a685-6083-xxxx-xxxx-xxxxxxxx4db",
"roles": [
"Directory.Read.All",
"Directory.ReadWrite.All"
],
"sub": "12d9a685-xxxx-47e1-xxxx-xxxxxxxxx4db",
"tenant_region_scope": "NA",
"tid": "06b0c6f1-7524-xxxx-xxxx-xxxxxxxxx731",
"uti": "xxxxxxxxxxxxxxxuAA",
"ver": "1.0"
}
Response Tenant 2
{
StatusCode: 403,
ReasonPhrase: 'Forbidden',
Version: 1.1,
Content: System.Net.Http.HttpConnectionResponseContent,
Headers:
{
...
}
}
// Content
{
"odata.error": {
"code": "Authorization_RequestDenied",
"message": {
"lang": "en",
"value": "Insufficient privileges to complete the operation."
},
"requestId": "9adf43b9-xxxx-xxxx-a393-xxxxxxxxxd54",
"date": "2020-06-17T17:47:19"
}
}
I am trying to find a way to sum the prices held in an array, the way I am doing it now is to save the document to CosmosDB then run an additional sum(foo) query on it but I am thinking there must be a way so simply do that directly before I save the document to CosmosDB to save the extra round trip to the DocumentDB.
Example Document below.
The values I want to summarise are under:
ApiInputObject.TransactionDetails.Items.Price and there can of course be many items in the array.
I can only figure out how to get a single value out but that seems very inefficient.
{
"InternalTransactionlId": "XXX",
"DocumentType": "order",
"ExternalTransactionId": "externalIdTest2",
"OrderBotResponse": {
"id": "XXX",
"status": "pending",
"checkoutUrl": "https://www.example.com",
"items": [
{
"attributes": {
"color": "Midnight blue",
"size": "L"
},
"price": "500",
"quantity": "1",
"shipping": "0.0",
"title": "ACME Title",
"url": "https://example.com",
"product_id": "XXX",
"imageUrl": "https://example.com/image.jpg",
"status": "pending",
"shippingMethod": "default",
"totalPrice": 500
}
],
"reference": "XXX",
"currency": "SEK",
"country": "SE",
"language": "sv-se",
"provider": "acme",
"callback": {
"refund": "http://example.com",
"success": "http://example.com"
},
"shippingAddress": {},
"logs": [
{
"t": "2019-08-24T20:58:04.844+08:00",
"m": "Created"
}
],
"meta": {
"error": 0
}
},
"ApiInputObject": {
"ApiKey": "XXX",
"OrderType": "directTransaction",
"SourceSystem": {
"SourceSystemName": "ACME"
},
"SourceSystemCountry": "SE",
"DestinationSystem": {
"DestinationSystemName": "acme.com"
},
"DestinationSystemCountry": {
"DestinationSystemCountryName": "SE"
},
"Brand": {
"BrandName": "ACME"
},
"RequestedFeatures": [
"NONE"
],
"ExternalTransactionId": "externalIdTest2",
"TransactionDetails": {
"callback": {
"refund": "http://example.com",
"success": "http://example.com"
},
"items": [
{
"attributes": {
"color": "Midnight blue",
"size": "L"
},
"price": "500",
"quantity": "1",
"shipping": "0.0",
"title": "ACME",
"url": "https://example.com"
}
],
"test": "true",
"reference": "XXX"
}
},
"id": "XXX",
"_rid": "XXX",
"_self": "XXX",
"_etag": "XXX",
"_attachments": "attachments/",
"_ts": 111
}
You can try to use SelectToken to get your JSON data value. then use linq SUM
JObject obj = JObject.Parse(data);
var value = obj.SelectToken("ApiInputObject.TransactionDetails.items").Sum(x=>((int)x["price"]));
c# online
I am using the results from json2csharp.com on the response below from a GET request within my MVC Model:
{
"Id": 1111111,
"CreateLocation": "xxxxxxxxEZ-V12",
"ConstituentType": {
"Description": "Individual",
"Id": 1,
"Inactive": false,
"ConstituentGroup": {
"Description": "Individual",
"Id": 1,
"Inactive": false
}
},
"DisplayName": "xxxxxxxx xxxxxxxx",
"FirstName": "xxxxxxxx",
"Inactive": {
"Id": 1,
"Description": "Active",
"Inactive": false
},
"InactiveReason": null,
"LastActivityDate": "2016-10-16T02:32:15Z",
"LastName": "xxxxxxxx",
"MailIndicator": {
"Description": "(none)",
"Id": 3,
"Inactive": false
},
"EmarketIndicator": {
"Description": "(none)",
"Id": 3,
"Inactive": false
},
"MiddleName": "",
"NameStatus": {
"Description": " ",
"Id": 1,
"Inactive": false
},
"OriginalSource": {
"Description": "Test Test",
"Id": 4,
"Inactive": false
},
"PhoneIndicator": {
"Description": "(none)",
"Id": 3,
"Inactive": false
},
"Prefix": {
"Description": "",
"Id": -1,
"Inactive": false
},
"Gender": null,
"Suffix": {
"Description": "",
"Id": -1,
"Inactive": false
},
"Salutation": {
"BusinessTitle": null,
"CreatedDateTime": "2016-05-21T16:47:52Z",
"CreateLocation": "xxxxxxxxEZ-V12",
"Constituent": {
"Id": 8775975
},
"CreatedBy": "xxxxxxxx",
"Id": 912925,
"DefaultIndicator": true,
"EnvelopeSalutation1": "xxxxxxxx xxxxxxxx",
"EnvelopeSalutation2": "",
"Label": true,
"UpdatedDateTime": "2016-05-21T16:47:52.937Z",
"UpdatedBy": "xxxxxxxx",
"LetterSalutation": "xxxxxxxx xxxxxxxx",
"SalutationType": {
"Description": "Default",
"Id": 0,
"Inactive": false
},
"EditIndicator": true,
"IsFromAffiliation": false
},
"Address": {
"Id": 9781315,
"AffiliatedConstituent": null,
"AltSalutationType": {
"Description": "Default",
"Id": 0,
"Inactive": false
},
"AddressType": {
"Description": "Home Address",
"Id": 3,
"Inactive": false
},
"City": "Brooklyn",
"CreatedDateTime": "2016-05-21T16:47:52Z",
"CreateLocation": "xxxxxxxxEZ-V12",
"CreatedBy": "xxxxxxxx",
"Constituent": {
"Id": 8775975
},
"DeliveryPoint": "",
"EndDate": null,
"GeoArea": 35,
"Inactive": false,
"Label": true,
"UpdatedDateTime": "2016-09-21T16:00:46.497Z",
"UpdatedBy": "NCOA$STD",
"Months": "YYYYYYYYYYYY",
"NcoaAction": 3,
"NcoaSession": 9,
"PostalCode": "12121212",
"PostalCodeFormatted": "11205-2348",
"PrimaryIndicator": true,
"StartDate": null,
"State": {
"Description": "New York",
"StateCode": "NY",
"Id": 51,
"Inactive": false,
"Country": {
"Description": "USA",
"Id": 1,
"Inactive": false
}
},
"Street1": "11 Fadeaddress Ave",
"Street2": null,
"Street3": null,
"Country": {
"Description": "USA",
"Id": 1,
"Inactive": false
},
"EditIndicator": true,
"IsFromAffiliation": false
},
"ElectronicAddress": {
"Address": "test#test.edu",
"AffiliatedConstituent": null,
"AltSalutationType": null,
"CreatedDateTime": "2016-05-21T16:47:53Z",
"CreateLocation": "xxxxxxxxEZ-V12",
"CreatedBy": "xxxxxxxx",
"Constituent": {
"Id": 8775975
},
"Id": 9781317,
"ElectronicAddressType": {
"Description": "Home Email",
"Id": 1,
"Inactive": false,
"IsEmail": true
},
"EndDate": null,
"AllowHtmlFormat": true,
"Inactive": false,
"UpdatedDateTime": "2016-05-21T16:47:53.03Z",
"UpdatedBy": "xxxxxxxx",
"AllowMarketing": true,
"Months": "YYYYYYYYYYYY",
"PrimaryIndicator": true,
"StartDate": null,
"EditIndicator": true,
"IsFromAffiliation": false,
"IsEmail": true
},
"PrimaryPhoneNumbers": [
{
"Address": {
"Id": 9781315,
"AddressType": {
"Description": "Home Address",
"Id": 3,
"Inactive": false
}
},
"AllowTelemarketing": true,
"DayEveningIndicator": " ",
"Constituent": {
"Id": 8775975
},
"Id": 9781316,
"Inactive": false,
"PhoneNumber": "11111111",
"PhoneFormatted": "(917) 561-0972 ",
"PhoneSearch": "11111111",
"PhoneType": {
"Description": "Phone 1",
"Id": 1,
"Inactive": false
},
"CreatedBy": "xxxxxxxx",
"CreateLocation": "xxxxxxxxEZ-V12",
"CreatedDateTime": "2016-05-21T16:47:53Z",
"UpdatedDateTime": "2016-05-21T16:47:53.027Z",
"UpdatedBy": "xxxxxxxx",
"EditIndicator": true
}
],
"CreatedDateTime": "2015-05-23T14:03:23Z",
"CreatedBy": "xxxxxxxx",
"UpdatedDateTime": "2016-10-16T02:32:15.527Z",
"UpdatedBy": "dbo ",
"SortName": "xxxxxxxx/xxxxxxxx",
"Affiliates": [],
"ProtectionType": null
}
But when I try to deserialize the JSON output and return the results to my View with
//Storing the response details recieved from web api
var json = Res.Content.ReadAsStringAsync().Result;
//Deserializing the response recieved from web api and storing into the Employee list
EmpInfo = JsonConvert.DeserializeObject<List<Constituent>>(json);
I get the error Cannot deserialize the current JSON object...because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array...that can be deserialized from a JSON object.
Your example response is a single object, not an array. I can't see your implementation of Constituent but assume it matches that definition?
In which case you should be able to deserialize the single result (rather than a list) using:
EmpInfo = JsonConvert.DeserializeObject<Constituent>(json);
var result = JsonConvert.DeserializeObject<dynamic>(JSONtext)
I have this JSON:
{
"total": 23695,
"total_pages": 1185,
"results": [{
"id": "r7bVvV7MLdQ",
"created_at": "2018-01-17T06:38:03-05:00",
"updated_at": "2018-05-09T03:35:24-04:00",
"width": 4032,
"height": 2526,
"color": "#F7EDE7",
"description": null,
"urls": {
"raw": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=8b6caac6353f390fbbabde8441dd1959",
"full": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026q=85\u0026fm=jpg\u0026crop=entropy\u0026cs=srgb\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=89ca725623d794116d3741907c93ceab",
"regular": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=666eb6ac25c7fec68d5994545b933726",
"small": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=400\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=3dbc611c97d323ff8b4b043cff19317b",
"thumb": "https://images.unsplash.com/photo-1516189050082-44d4deb5ceef?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=200\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjEyMDd9\u0026s=0c760185c35eadb31a7bba9b9794d424"
},
"links": {
"self": "https://api.unsplash.com/photos/r7bVvV7MLdQ",
"html": "https://unsplash.com/photos/r7bVvV7MLdQ",
"download": "https://unsplash.com/photos/r7bVvV7MLdQ/download",
"download_location": "https://api.unsplash.com/photos/r7bVvV7MLdQ/download"
},
"categories": [],
"sponsored": false,
"likes": 0,
"liked_by_user": false,
"current_user_collections": [],
"slug": "cloud-smoke-steam",
"user": {
"id": "G69mdFHx0X0",
"updated_at": "2018-05-03T14:00:07-04:00",
"username": "maxkuk",
"name": "Max Kukurudziak",
"first_name": "Max",
"last_name": "Kukurudziak",
"twitter_username": null,
"portfolio_url": "http://www.instagram.com/makckuk",
"bio": "Product Designer at MacPaw, Lecturer at Projector",
"location": "Kiev, Ukraine",
"links": {
"self": "https://api.unsplash.com/users/maxkuk",
"html": "https://unsplash.com/#maxkuk",
"photos": "https://api.unsplash.com/users/maxkuk/photos",
"likes": "https://api.unsplash.com/users/maxkuk/likes",
"portfolio": "https://api.unsplash.com/users/maxkuk/portfolio",
"following": "https://api.unsplash.com/users/maxkuk/following",
"followers": "https://api.unsplash.com/users/maxkuk/followers"
},
"profile_image": {
"small": "https://images.unsplash.com/profile-1518780839522-ee199eceaf8c?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=32\u0026w=32\u0026s=c37d2f2844b45f52c0f66cd580a200c8",
"medium": "https://images.unsplash.com/profile-1518780839522-ee199eceaf8c?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=64\u0026w=64\u0026s=93647049c20b6a323870fe0886eee329",
"large": "https://images.unsplash.com/profile-1518780839522-ee199eceaf8c?ixlib=rb-0.3.5\u0026q=80\u0026fm=jpg\u0026crop=faces\u0026cs=tinysrgb\u0026fit=crop\u0026h=128\u0026w=128\u0026s=aff2d13afe9fe418b562b85c226b7e8e"
},
"instagram_username": "makckuk",
"total_collections": 0,
"total_likes": 6,
"total_photos": 56
},
"tags": [{
"title": "cloud"
},
{
"title": "smoke"
},
{
"title": "steam"
},
{
"title": "mountain"
},
{
"title": "volcano"
},
{
"title": "blue"
},
{
"title": "rock"
},
{
"title": "glacier"
},
{
"title": "field"
},
{
"title": "geysir"
},
{
"title": "iceland"
}],
"photo_tags": [{
"title": "cloud"
},
{
"title": "smoke"
},
{
"title": "steam"
},
{
"title": "mountain"
},
{
"title": "volcano"
},
{
"title": "blue"
},
{
"title": "rock"
},
{
"title": "glacier"
},
{
"title": "field"
},
{
"title": "geysir"
},
{
"title": "iceland"
}]
},
I need to get results.profile_image.small I tried it on many ways but I never figured out how to access to profile_image fields.
Basically I want to do something like this:
dynamic array = JsonConvert.DeserializeObject(responz);
foreach (var itemx in array["results"])
{
MessageBox.Show(itemx.profile_image.small.ToString());
}
I spent last few hours figuring it out, searching searching StackOverflow. The last option is do this with regex which would be very stupid thing to do.
Based on your JSON, the actual path should be:
itemx.user.profile_image.small
So if you modify your code to include the missing "user" portion:
dynamic array = JsonConvert.DeserializeObject(responz);
foreach (var itemx in array["results"])
{
MessageBox.Show(itemx.user.profile_image.small.ToString());
}
That should solve your problem.
However, this problem would likely not have presented itself if you were using a concrete class to deserialize into. You would have type safety and the assistance of Intelisense if you use a concrete class. You can easily convert your JSON sample into a concrete class using Json2CSharp or using the "Paste as Class" function of modern Visual Studio versions.