ActionConditionFailed. “The execution of template action ‘Condition’ is skipped” “Expected status values ‘Succeeded’ and actual value ‘Failed’.” Azure Logic Apps

I’ve been jumping into the Azure Logic Apps world.

On an Http Request Trigger (the Logic App one, not the Function app one), I wanted to reject the request if I received bad json.

Not only did I want to reject the request, I wanted the end user to get some “hints” as to why the json schema validation failed.

So I coded up a basic azure function (that I would later pull into my Logic App.

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;

using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;

namespace GranadaCoder.AzurePoc.AzureFunctionsOne
{
public static class SimpleJsonSchemaValidator
{
[FunctionName(“SimpleJsonSchemaValidatorFunctionName”)]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, “post”, Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info(string.Format(“C# HTTP trigger function SimpleJsonSchemaValidatorFunctionName about to process a request. (‘{0}’)”, DateTime.Now.ToLongTimeString()));

try
{
log.Info(string.Format(“SimpleJsonSchemaValidatorFunctionName HostingEnvironment.ApplicationPhysicalPath='{0}'”, System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath));

/* json schema straight from https://www.newtonsoft.com/json/help/html/JsonSchema.htm
you can get valid and invalid json from there as well) */

string jsonSchemaText = @”{
‘description’: ‘A person’,
‘type’: ‘object’,
‘properties’:
{
‘name’: {‘type’:’string’},
‘hobbies’: {
‘type’: ‘array’,
‘items’: {‘type’:’string’}
}
}
}”;

log.Info(string.Format(“SimpleJsonSchemaValidatorFunctionName jsonSchemaText='{0}'”, jsonSchemaText));

JSchema schema = JSchema.Parse(jsonSchemaText);

var content = req.Content;
string jsonContent = content.ReadAsStringAsync().Result;

log.Info(string.Format(“SimpleJsonSchemaValidatorFunctionName jsonContent='{0}'”, jsonContent));

JObject jobj = JObject.Parse(jsonContent);

IList<string> messages;
bool valid = jobj.IsValid(schema, out messages);
if (!valid)
{
string errorMsg = string.Join(“,”, messages);
throw new ArgumentOutOfRangeException(string.Format(“Not Cool Alert. ({0})”, errorMsg));
}

log.Info(“C# HTTP trigger function SimpleJsonSchemaValidatorFunctionName processed a request.”);
return req.CreateResponse(HttpStatusCode.OK, jsonContent, new JsonMediaTypeFormatter());
}
catch (Exception ex)
{
string errorMsg = GenerateFullFlatMessage(ex);
log.Error(errorMsg);
return req.CreateResponse(HttpStatusCode.BadRequest, errorMsg);
}
}

private static string GenerateFullFlatMessage(Exception ex)
{
return GenerateFullFlatMessage(ex, false);
}

private static string GenerateFullFlatMessage(Exception ex, bool showStackTrace)
{
string returnValue;

StringBuilder sb = new StringBuilder();
Exception nestedEx = ex;

while (nestedEx != null)
{
if (!string.IsNullOrEmpty(nestedEx.Message))
{
sb.Append(nestedEx.Message + System.Environment.NewLine);
}

if (showStackTrace && !string.IsNullOrEmpty(nestedEx.StackTrace))
{
sb.Append(nestedEx.StackTrace + System.Environment.NewLine);
}

nestedEx = nestedEx.InnerException;
}

returnValue = sb.ToString();

return returnValue;
}
}
}

Please note that I am getting my json and json schema from the example from newtonsoft.

https://www.newtonsoft.com/json/help/html/JsonSchema.htm

Ok, then I created a new Logic App.

FailedRequestResponse

My initial “Request” trigger was added.  No brainer on that.  Something has to be the trigger for the Logic App.

Then I added an action … an Azure Function, and wired up my “SimpleJsonSchemaValidatorFunctionName”.

Then I added a “Condition”.  The condition would check the StatusCode of the output of SimpleJsonSchemaValidatorFunctionName.

If the StatusCode was 200, then it would simple send a request back with the body equal to “Hooray Everything AOK  Hooray”.

The “Else” branch of the condition would send a request back with the body equal to the body from SimpleJsonSchemaValidatorFunctionName (which could contain all the json validations)

Everything via the Logic App Designer went as planned.

If I submitted good Json, I got back “Hooray Everything AOK  Hooray”.  Sweet!
The good json (from the newtonsoft website) was:

{
  'name': 'James',
  'hobbies': ['.NET', 'Blogging', 'Reading', 'Xbox', 'LOLCATS']
}

If I submitted bad Json……..I did NOT get what I expected. 😦  Boo!
The bad json (from the newtonsoft website) was:

{
   'name': null,
   'hobbies': ['Invalid content', 0.123456789]
 }

My client got a response back with below message

{
“error”: {
“code”: “NoResponse”,
“message”: “The server did not received a response from an upstream server. Request tracking id ‘00000000000000000000000000000’.”
}
}

In the Azure portal, I got the below error message.

ActionConditionFailed. The execution of template action ‘Condition’ is skipped: the ‘runAfter’ condition for action ‘SimpleJsonSchemaValidatorFunctionNameInstanceOne’ is not satisfied. Expected status values ‘Succeeded’ and actual value ‘Failed’.

The fix was simple.  Simply add “Failed” to a list of possible outcomes of that Logic App workflow step.
But you have to do it view the code view…….(aka, not in the Designer)

“runAfter”: {
“SimpleJsonSchemaValidatorFunctionNameInstanceOne”: [
“Failed”,     
“Succeeded”        ]

Now when I run my client, I got the proper response with the body text as seen below:

Specified argument was out of the range of valid values.
Parameter name: Not Cool Alert. (Invalid type. Expected String but got Null. Path ‘name’, line 2, position 15.,Invalid type. Expected String but got Number. Path ‘hobbies[1]’, line 3, position 45.)

(Again, my “bad” json is from the example from newtonsoft.  https://www.newtonsoft.com/json/help/html/JsonSchema.htm

Voila!  Now my Logic App Http Request Trigger will not only reject bad json, it will provide “hints” (aka, json schema error messages) back to the caller.  Now they can fix the json themselves without having to call me!

Below is my full LogicApp.json with my simple addition bolded

 

{
“$schema”: “https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#&#8221;,
“actions”: {
“SimpleJsonSchemaValidatorFunctionNameInstanceOne”: {
“type”: “Function”,
“inputs”: {
“body”: “@triggerBody()”,
“function”: {
“id”: “/subscriptions/yada/yada/yada/not/for/you/to/see/functions/SimpleJsonSchemaValidatorFunctionName”
}
},
“runAfter”: {}
},
“Condition”: {
“type”: “If”,
“expression”: “@equals(outputs(‘SimpleJsonSchemaValidatorFunctionNameInstanceOne’)[‘statusCode’], 200)”,
“actions”: {
“HoorayResponse”: {
“type”: “Response”,
“inputs”: {
“statusCode”: “@outputs(‘SimpleJsonSchemaValidatorFunctionNameInstanceOne’)[‘statusCode’]”,
“body”: “Hooray Everything AOK Hooray”
},
“runAfter”: {}
}
},
“runAfter”: {
“SimpleJsonSchemaValidatorFunctionNameInstanceOne”: [
“Failed”,
“Succeeded”
]
},
“else”: {
“actions”: {
“BooNoGoodResponse”: {
“type”: “Response”,
“inputs”: {
“statusCode”: “@outputs(‘SimpleJsonSchemaValidatorFunctionNameInstanceOne’)[‘statusCode’]”,
“body”: “@body(‘SimpleJsonSchemaValidatorFunctionNameInstanceOne’)”
},
“runAfter”: {}
}
}
}
}
},
“parameters”: {},
“triggers”: {
“manual”: {
“type”: “Request”,
“kind”: “Http”,
“inputs”: {
“schema”: {}
}
}
},
“contentVersion”: “1.0.0.0”,
“outputs”: {}
}

Advertisements
This entry was posted in Software Development and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s