how to add a node if it doesn't exist' - c#

I'm attempting to run some patch operations:
ItemResponse<dynamic> response = await _container.PatchItemAsync<dynamic>(
id: loanParent.LoanNumber,
partitionKey: new PartitionKey(loanParent.LoanNumber),
patchOperations: new[] {
PatchOperation.Replace("/loandetails/loanname", loanParent.Loan.LoanDetails.LoanName),
PatchOperation.Replace("/loandetails/loandescription", loanParent.Loan.LoanDetails.LoanDescription)
}
);
However, I'm getting this exception because those nodes do not exist yet. Here's the full document:
{
"loannumber": "abc123",
"id": "abc123",
"participants": [
{
"firstname": "alex",
"lastname": "gordon"
},
{
"firstname": "liza",
"lastname": "gordon"
}
],
"_rid": "1sAyAggggggA==",
"_self": "dbs/1sAyAA=gggggAAAAAAAA==/",
"_etag": "\"d900c069-0000-4440-0000-63642d840000\"",
"_attachments": "attachments/",
"_ts": 1ddd636
}
Microsoft.Azure.Cosmos.CosmosException : Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: a6ab67d6-f73e-4b3c-b03e-1d9b6cc54dba; Reason: (Message: {"Errors":["For Operation(1): Given Operation can only create a child object of an existing node(array or object) and cannot create path recursively, no path found beyond: 'loandetails'. Learn more: https://aka.ms/cosmosdbpatchdocs"]}
How do we create the node structure if it does not exist?

Patch works on an existing document, you need to make sure the object exists before you perform any operations such as add,remove,replace,set and increment.
In this case first you can use Add operator to create the loandetails and then the subsequent operations can be performed

Related

C# How to get exact error message from Logic App triggered by HttpRequest instead of default error message?

I have a simple console application and it calls a Logic App by HttpRequest.
When the Logic App fails at any step I want to get exact the error message saying why it fails.
In the Logic App I can see the error.
Example: in the image, it fails at step 2 which it can't convert a string into an int. It's saying:
InvalidTemplate. Unable to process template language expressions in action 'Parse_JSON' inputs at line '0' and column '0': 'Required property 'content' expects a value but got null. Path ''.'.
which is what's I expect.
Here is my Logic App design:
But when I debug in a console application, it gives me a message "The server did not receive a response from an upstream server. Request tracking id 'some random Ids'." which is not very useful.
Here is my console application:
var obj = new
{
Age = "Twenty",
Name = "James"
};
using (var client = new HttpClient())
{
var content = new StringContent(JsonConvert.SerializeObject(obj));
content.Headers.ContentType.MediaType = "application/json";
var response = await client.PostAsync(url, content);
var errorMessage = await response.Content.ReadAsStringAsync();
//errorMessage: {"error":{"code":"NoResponse","message":"The server did not receive a response from an upstream server. Request tracking id 'some random Ids'."}}
}
So is there anyway to make the C# response return the error message in the step 2 of the Logic App?
What I expect is:
InvalidTemplate. Unable to process template language expressions in action 'Parse_JSON' inputs at line '0' and column '0': 'Required property 'content' expects a value but got null. Path ''.'.
Not:
{"error":{"code":"NoResponse","message":"The server did not receive a response from an upstream server. Request tracking id 'some random Ids'."}}
Thank you in advanced.
You can use actions('<Your_Previous_Step>')['error'] in your case actions('Parse_JSON')['error'] doing so you can able to retrieve the error message of that particular action.
Here is my logic app
I'm testing this through postman. Below is the response I received in postman.
Make sure you set Configure run after options to make the flow work even after it gets failed.
Updated Answer (General Solution)
In this case you can initialise a string variable and then add Append to string variable for each step so that it can catch the previous steps error. Below is the screenshot of my logic app.
Response in my postman
NOTE: Make sure you set Configure run after property for each action.
You can use the Scope action to encase the vast majority of other actions and then if something fails, you can catch the step for which it fails at.
You can load this JSON definition into your own tenant and see a working version.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Filter_array": {
"inputs": {
"from": "#variables('Result')",
"where": "#equals(item()['status'], 'Failed')"
},
"runAfter": {
"Initialize_Result": [
"Succeeded"
]
},
"type": "Query"
},
"Initialize_Error_Message": {
"inputs": {
"variables": [
{
"name": "Error Message",
"type": "string",
"value": "#{body('Filter_array')[0]['error']['message']}"
}
]
},
"runAfter": {
"Filter_array": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_Integer_Variable": {
"inputs": {
"variables": [
{
"name": "Integer Variable",
"type": "integer",
"value": 1
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"Initialize_Result": {
"inputs": {
"variables": [
{
"name": "Result",
"type": "array",
"value": "#result('Scope')"
}
]
},
"runAfter": {
"Scope": [
"Succeeded",
"FAILED"
]
},
"type": "InitializeVariable"
},
"Scope": {
"actions": {
"Set_Integer_Variable_(Step_1)": {
"inputs": {
"name": "Integer Variable",
"value": 2
},
"runAfter": {},
"type": "SetVariable"
},
"Set_Integer_Variable_(Step_2)": {
"inputs": {
"name": "Integer Variable",
"value": "#string('Test')"
},
"runAfter": {
"Set_Integer_Variable_(Step_1)": [
"Succeeded"
]
},
"type": "SetVariable"
},
"Set_Integer_Variable_(Step_3)": {
"inputs": {
"name": "Integer Variable",
"value": 3
},
"runAfter": {
"Set_Integer_Variable_(Step_2)": [
"Succeeded"
]
},
"type": "SetVariable"
}
},
"runAfter": {
"Initialize_Integer_Variable": [
"Succeeded"
]
},
"type": "Scope"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"Recurrence": {
"evaluatedRecurrence": {
"frequency": "Month",
"interval": 12
},
"recurrence": {
"frequency": "Month",
"interval": 12
},
"type": "Recurrence"
}
}
},
"parameters": {}
}
Naturally, it's a little more intensive and follows the same principals as a normal flow for continuing to the next step after a failure but this will help you with larger flows.
This is what the test flow looks like ...
To explain it quickly, the middle steps are simple Set Variable actions that can be changed to cause the failure.
In the definition I've given you, step 2 will fail but you can change it to step 1 or 3 and you should still see the error come out at the end regardless of the step in the scope action that fails.
I suggest playing with it and looking at the output to the scope action, which is written to variable Result in the Initialize Result step.
For reference, this is the sort of information that comes out of the Scope action that you can use to determine what has failed.
{
"variables": [
{
"name": "Result",
"type": "Array",
"value": [
{
"name": "Set_Integer_Variable_(Step_1)",
"inputs": {
"name": "Integer Variable",
"value": 2
},
"outputs": {
"body": {
"name": "Integer Variable",
"value": 2
}
},
"startTime": "2022-04-22T06:55:57.8965917Z",
"endTime": "2022-04-22T06:55:57.9281959Z",
"trackingId": "0c93fa70-a552-4776-bce1-8ac889933de9",
"clientTrackingId": "08585509963278112157168286283CU11",
"status": "Succeeded"
},
{
"name": "Set_Integer_Variable_(Step_2)",
"startTime": "2022-04-22T06:55:57.9434709Z",
"endTime": "2022-04-22T06:55:57.9434709Z",
"trackingId": "f82b494b-0ecd-412b-887a-d4b08f4a5751",
"clientTrackingId": "08585509963278112157168286283CU11",
"code": "BadRequest",
"status": "Failed",
"error": {
"code": "BadRequest",
"message": "The variable 'Integer Variable' of type 'Integer' cannot be initialized or updated with value of type 'String'. The variable 'Integer Variable' only supports values of types 'Integer'."
}
},
{
"name": "Set_Integer_Variable_(Step_3)",
"startTime": "2022-04-22T06:55:57.9590957Z",
"endTime": "2022-04-22T06:55:57.9590957Z",
"trackingId": "f761d71f-8ec0-4a29-9a8a-a39a81faf660",
"clientTrackingId": "08585509963278112157168286283CU11",
"code": "ActionSkipped",
"status": "Skipped",
"error": {
"code": "ActionConditionFailed",
"message": "The execution of template action 'Set_Integer_Variable_(Step_3)' is skipped: the 'runAfter' condition for action 'Set_Integer_Variable_(Step_2)' is not satisfied. Expected status values 'Succeeded' and actual value 'Failed'."
}
}
]
}
]
}
Take note, you still need to apply the Configure run after properties to ensure it continues on after the Scope action finishes ...
You'd need to put some more error checking in but my suggestion would be to wrap all of that functionality into another LogicApp that you can reuse across your tenant. That's the thinking anyway.

500 Internal server error while counting dynamic json data in Azure http trigger post method

I am creating a Azure function http trigger post method where i am receiving json data in body and then i am mapping it and store it in blob storage.It is working well in local but in Azure environment it gets failed.In application insight i have created a custom log events where i see the error is due to counting of json dynamic data.
error:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
Cannot perform runtime binding on a null reference
Here is my sample code
public async Task Run([ HttpTrigger( AuthorizationLevel.Anonymous, "get", "post", Route = null) ] HttpRequest req )
{
try
{
StringBuilder csveventcontent = new StringBuilder();
string requestBody =
await new StreamReader(req.Body).ReadToEndAsync();
dynamic json = JsonConvert.DeserializeObject(requestBody);
int eventsDataloopCount = json["body"]["data"].Count;
Sample http reqst data
{
"functionName": "abc",
"method": "POST",
"headers": {},
"body": {
"data": [
{
"item1": 1,
"created_at": "2021-02-10T21:07:08Z",
"item2":"b",
"item3": -1,
"item4": null,
"item5": null,
"arrayitem": {
"item1": "1",
"item2": "2",
"item3": "3"
},
"data": {},
"arrayevent": {
"abc": 1
}
},
I can see there are two issues in your JSON.
It should be "item2": "b" not "item2": b.
There are two keys for "item1" for value "1" and "3". so you have to remove one of them.
So my suggestion is to first fix the JSON and then proceed further.
Got the issue, you should use json["body"]["data"].Count not json["body"]["data"].count. Newtonsoft.Json.Linq.JArray has no count method.

Microsoft Graph API - Approve Moderation Request

I want to be able approve a moderation request through Graph API. I have referred to Approve Moderation Request. I was not able to get it to work. Although, there is a PowerShell script available at EWS Managed API and Powershell How-To Series Part 11 Moderation that I managed to get working.
This is not a supported feature in Graph API and therefore requires some tinkering. I would like some guidance on how to do this.
This is the JSON I am sending to the end point https://graph.microsoft.com/v1.0/me/sendMail
{
"message": {
"subject": "Approve:MessageName"
},
"toRecipients": [
{
"emailAddress": {
"name": "Microsoft Exchange",
"address": "systemmailbox#domain.com"
}
}
],
"singleValueExtendedProperties": [
{
"id": "Binary 0x31",
"value": "7gd324tgcxJJNkEuxk2DP2Xk+M/fxw=="
},
{
"id": "String 0x001A",
"value": "IPM.Note.Microsoft.Approval.Reply.Approve"
}
]
}
This is the response I receive
{
"error": {
"code": "ErrorInvalidRecipients",
"message": "At least one recipient isn't valid., A message can't be sent because it contains no recipients.",
"innerError": {
"date": "2020-08-19T23:40:07",
"request-id": "7g5h732v-6uhb-3212-b6f1-43f6eeb139wq"
}
}
}
Any help would be appreciated.
You have a syntax issue in your Json request eg look closely at the Message after subject you have a closing } which means the only thing your posting is the subject of the message it should be
{
"message": {
"subject": "Approve:MessageName",
"toRecipients": [
{
"emailAddress": {
"name": "Microsoft Exchange",
"address": "address.com"
}
}
],
"singleValueExtendedProperties": [
{
"id": "Binary 0x31",
"value": "7gd324tgcxJJNkEuxk2DP2Xk+M/fxw=="
},
{
"id": "String 0x001A",
"value": "IPM.Note.Microsoft.Approval.Reply.Approve"
}
]
}
}
Additional
To make this work correctly you need to get the Approval Request from an app rovers mailbox for the Graph a query like this
https://graph.microsoft.com/v1.0/me/mailFolders('Inbox')/messages?$filter=singleValueExtendedProperties/any(ep:ep/id eq 'String 0x001a' and ep/value eq 'IPM.Note.Microsoft.Approval.Request')&$expand=singleValueExtendedProperties($filter%3D(Id eq 'Binary 0x0031') or (Id eq 'String 0x0E1D'))
This will give you the report tag 0x0031 value that you need to use in your Send and you also need to include the Approve Verb Extended property
{
id = "String {00062008-0000-0000-C000-000000000046} Id 0x8524"
value = "Approve"
}
I converted the script from my blog which I'll get around to posting this week that just approves the last email in a Mailbox you can look at it https://github.com/gscales/Powershell-Scripts/blob/master/Graph101/Moderation.ps1 (look at Invoke-ApproveModerationRequest)

How to know the interactions happened with the feed in stream?

My query goes like this: If I have a feedItem (an image posted on facebook), how can I verify that I have liked it or not? Can I verify all the interactions which I have done to the feedItem or the interactions other people have done to it (like, dislike, pin, share)? Is there any way in getstream.io to retrieve these interactions?
Thanks in advance...
Graph API provides all functions you need. Here are some examples:
Read shares[it's a field of an object]: https://developers.facebook.com/docs/graph-api/reference/v3.1/post#read
Read Shared posts: https://developers.facebook.com/docs/graph-api/reference/v3.1/object/sharedposts
read likes:
https://developers.facebook.com/docs/graph-api/reference/v3.1/object/likes#read
/likes returns only the profile for the current user if read with a
user access token:
Album, Photo, Post, Video
all returns are JSON, which you can directly Deserialize Anonymous Type without using stream, for example, likes:
{
"likes": {
"data": [
{
"name": "Bill the Cat",
"id": "155111347875779",
"created_time": "2017-06-18T18:21:04+0000"
},
{
"name": "Calvin and Hobbes",
"id": "257573197608192",
"created_time": "2017-06-18T18:21:02+0000"
},
{
"name": "Berkeley Breathed's Bloom County",
"id": "108793262484769",
"created_time": "2017-06-18T18:20:58+0000"
}
],
"paging": {
"cursors": {
"before": "Nzc0Njg0MTQ3OAZDZD",
"after": "NTcxODc1ODk2NgZDZD"
},
"next": "https://graph.facebook.com/vX.X/me/likes?access_token=user-access-token&pretty=0&summary=true&limit=25&after=NTcxODc1ODk2NgZDZD"
},
"summary": {
"total_count": 136
}
},
"id": "user-id"
}

Can't access Procedure.reason in FHIR model

I'm using the Fhir-net-api with DSTU2 to parse JSON objects to C# models. Everything works well, except that I can't access the Reason element of the resource type Procedure. As an example, I parse following JSON object to the Procedure model using the FhirParser:
{
"resourceType": "Procedure",
"identifier": [
{
"system": "https://mrd2.melanoma.org.au/fhir",
"value": "100200199664802"
}
],
"subject": { "reference": "Patient/10101000001733" },
"status": "completed",
"category": {
"coding": [
{
"system": "https://mrd2.melanoma.org.au/fhir/RootType",
"code": "3004"
}
],
"text": "Primary Surgery"
},
"bodySite": [
{
"coding": [
{
"system": "http://snomed.info/sct",
"code": "7771000"
}
],
"text": "Left Forearm, Anterior"
}
],
"reasonReference": { "reference": "/Condition/10106000001807" },
"performedDateTime": "1968-03-11",
"report": [ { "reference": "/DiagnosticReport/100200199664828" } ]
}
and the generated object has following entries (excerpt):
Procedure
I can access Report[0].Reference just fine but it won't work with Reason.Reference. Is the data in my JSON object wrong?
I've seen that Reason is of type Hl7.Fhir.Model.Element and Report of type Hl7.Fhir.Model.ResourceReference. Is there a way to change Reason to Hl7.Fhir.Model.ResourceReference and then access the Reference element?
Would be grateful for any hints. Thanks.
Regards,
Trammy
As you noticed, the type of reasonReference is Model.Element, while the type of report is ResourceReference. This difference has its origin in the definition of these elements in the FHIR specification for Procedure, where report is fixed to the type Reference but reason (or rather reason[x]) can either be a CodeableConcept or a Reference.
When elements can be of multiple types (we call this a "choice element", and you can recognize them because their name ends with [x] in the specification), we have created a C# member that is of type Model.Element (the base class for both Reference and CodeableConcept).
Now, depending on the instance you have just parsed or received, the contents of the reason member can be one of both types. So, you'll have to check in your code:
if(Reports[0].reason is ResourceReference)
{
var reference = (ResourceReference)Reports[0].reason;
//handle the case where this is a reference
//doing reference.Reference will now work as expected
}
else if(Reports[0].reason is CodeableConcept)
{
var concept = (CodeableConcept)Reports[0].reason;
//handle the case where this is a codeable concept
}
else
{
// Oops! Should not happen unless the standard has changed
}
Of course, if you are sure you can only receive instances where reason is a ResourceReference, you can do a cast directly:
var myReference = (ResourceReference)Reports[0].Reference;
// myReference.Reference and myReference.Display will now work

Categories