<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Brandon @ Microsoft</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/brandonh/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/brandonh/feed.xml</link>
    <description>Think. And code. Sometimes in that order, sometimes not</description>
    <lastBuildDate>Fri, 01 Jun 2018 16:16:11 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Make Serverless Music - Orchestrate your workflow with Azure [Part 4 - Durable Functions]</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/make-serverless-music-orchestrate-your-workflow-with-azure-part-4-durable-functions</link>
      <pubDate>Fri, 01 Jun 2018 02:14:00 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=325</guid>
      <description><![CDATA[At this point you've seen 3 relatively straightforward ways to orchestrate operations for a workflow...]]></description>
      <content:encoded><![CDATA[<p>At this point you've seen 3 relatively straightforward ways to orchestrate operations for a workflow in a severless manner:</p>
<ol>
<li>Microsoft Flow: ideally for Business Users but powerful enough to tackle simple orchestration tasks</li>
<li>Logic Apps: Azure's purpose-built workflow engine with robust retry &amp; failure capabilities, running on the same execution layer as your Azure deployments</li>
<li>Azure Functions + Logic Apps: for when your tasks are more complex than a simple Logic App can handle</li>
</ol>
<p>And one pretty involved approach - using Azure Functions in conjunction with state storage and messaging for resilient execution of a chained or parallel workflow across many Azure Functions.</p>
<p>Now let's have a look at the newest kid on the block: <a href="https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-overview" target="_blank">Azure Functions' Durable Functions extension</a>. Just announced at build but in preview for a few months prior, it's a code-first approach to workflow and orchestration using Azure Functions.</p>
<blockquote>
<p>Durable Functions is only GA on Azure Functions v1. Therefore many of the constructs it uses are from the v1 namespaces (eg: <code>HttpRequestMessage</code>, <code>HttpResponseMessage</code>) however you are free to use these in a v2 Function without issue.</p>
</blockquote>
<p>Durable Functions sits on top of Azure Functions and is available simply as a nuget package. What you get with this is a set of Function Trigger bindings and attributes that serve to abstract away the state management and queuing you saw in the Functions + Messaging approach from Part 3. Let's dive in.</p>
<h3>Step 1: Augment our current Azure Function in to a Durable Function</h3>
<p>Every Durable Function workflow has a Starter, one or more Orchestrators, and one or more Activity functions. As we saw in the last installment, our <code>/Validate</code> function serves as our starter here, so let's change it in to a Durable Functions Orchestration Client (aka Starter):</p>
<ol>
<li>Add an <code>[OrchestrationClient]</code> parameter</li>
</ol>
<pre><code class="language-csharp">public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]Person req,
    [OrchestrationClient]DurableOrchestrationClient client,
    [ServiceBus(@&quot;function-a&quot;, Connection = @&quot;ServiceBusOrchestrationConnection&quot;)]out QueueMessage functionAmsg,
    TraceWriter log)
</code></pre>
<ol start="2">
<li>Add a call to kick off the new orchestration:</li>
</ol>
<pre><code class="language-csharp">var orchestrationInstanceId = await client.StartNewAsync(@&quot;Start&quot;, req);
</code></pre>
<ol start="3">
<li>Return either an <code>HTTP 202 ACCEPTED</code> &quot;check for status&quot; response:</li>
</ol>
<pre><code class="language-csharp">return client.CreateCheckStatusResponse(req, orchestrationInstanceId);
</code></pre>
<p>At this point you'll need to convert this starter function to an <code>async</code> method which will leave you with a couple of issues:</p>
<pre><code>Error	CS1988	Async methods cannot have ref or out parameters	Functions
</code></pre>
<p>This is because of that leftover <code>out</code> parameter for the Service Bus queue message. With DF we don't need this (it handles the queuing for you) so you're free to remove this parameter.</p>
<p>The other thing you'll notice is the call to <code>CreateCheckStatusResponse</code> takes an <code>HttpRequestMessage</code> as its first parameter which we don't have. You need to forego the &quot;auto-deserialize&quot; of the request body in to a <code>Person</code> object now, and field the actual request, then manually deserialize it in to a <code>Person</code> to send on to the orchestration function. At the end of the day, our new <code>/Validate</code> should look like this:</p>
<pre><code class="language-csharp">[FunctionName(&quot;Validate&quot;)]
public static async Task&lt;HttpResponseMessage&gt; RunAsync([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]HttpRequestMessage req,
    [OrchestrationClient]DurableOrchestrationClient client,
    TraceWriter log)
{
    var body = await req.Content.ReadAsStringAsync();
    var personObj = Newtonsoft.Json.JsonConvert.DeserializeObject&lt;Person&gt;(body);
    log.Info($@&quot;Person request received: 
{body}&quot;);
    var orchestrationInstanceId = await client.StartNewAsync(@&quot;Start&quot;, personObj);

    return client.CreateCheckStatusResponse(req, orchestrationInstanceId);
}
</code></pre>
<h3>Step 2: Write the new Orchestrator function</h3>
<p>As you saw above, our Starter executes a <code>StartNewAsync</code> with a <code>string</code> parameter for an orchestrator Function name. Well, behind the scenes DF looks for a Function with a matching name and an <code>OrchestrationTrigger</code> attribute. So we need to create one of these. This function will then be orchestrating the actual work of executing all the necessary activities.</p>
<p>Here's what just such a function looks like when it's defined</p>
<pre><code class="language-csharp">[FunctionName(nameof(Start))]
public static void Start([OrchestrationTrigger]DurableOrchestrationContext context)
{

}
</code></pre>
<p>There's a pretty important catch when writing Durable Functions and here's where it comes in to play. You might think that you could write all your calls to other functions within this orchestrator as</p>
<pre><code class="language-csharp">_client.PostAsync(...
</code></pre>
<p>calls but you'd be wrong. DF will blow up at runtime with a TPL error complaining you're trying to do an asynchronous operation. <strong>Any <code>async</code> method call not present on the Durable Functions API surface must be done in DF <em>Activity</em> functions and nowhere else</strong> (you can read more on this and other code constraints <a href="https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-checkpointing-and-replay#orchestrator-code-constraints" target="_blank">in the docs here</a>).</p>
<h3>Step 3: Write the worker &quot;Activity Function&quot;</h3>
<p>So let's transform <code>CheckFirstName</code> in to an Activity function:</p>
<p>The first step is to change the trigger type to be an <code>ActivityTrigger</code> which gets a <code>DurableActivityContext</code> instance. You'll also notice that this activity function <strong>can return a value</strong> right back to the caller; not having to store it elsewhere; much more idiomatic, don't you think?</p>
<pre><code class="language-csharp">[FunctionName(&quot;CheckFirstName&quot;)]
public static Error CheckFirstName([ActivityTrigger]DurableActivityContext context, TraceWriter log)
{
</code></pre>
<p>Next, get the input passed to our activity (a <code>Person</code> object if you recall) via the context's <code>GetInput&lt;T&gt;</code> function call:</p>
<pre><code class="language-csharp">var person = context.GetInput&lt;Person&gt;();
</code></pre>
<blockquote>
<p>As an added convenience you can also use the strong type of the input value instead of a context object (eg: <code>Person</code> instead of <code>DurableActivityContext</code>). Downside is you can't get the InstanceId from that, so I stuck with <code>DurableActivityContext</code> here.</p>
</blockquote>
<p>And of course now do the processing &amp; return a new <code>Error</code> object (or <code>null</code>). The whole activity function ends up looking like this:</p>
<pre><code class="language-csharp">[FunctionName(&quot;CheckFirstName&quot;)]
public static Error CheckFirstName([ActivityTrigger]DurableActivityContext context, TraceWriter log)
{
    var person = context.GetInput&lt;Person&gt;();
    log.Info($@&quot;Message received: {context.InstanceId}&quot;);
    if ((person?.Name?.First?.Length &gt; 1) == false)
    {
        var err = new Error { id = 1, message = &quot;First name is null or not longer than 1 character&quot; };
        log.Info($@&quot; - Error found: {err.message}&quot;);
        return err;
    }
    else
    {
        log.Info($@&quot; - No error found&quot;);
        return null;
    }
}
</code></pre>
<p>Notice how, where before we had defined a session id on our own and decorated our incoming request with it, Durable Functions has the instance id for the orchestration as part of the context it passes around; so we can use this in any log messages to correlate activity together.</p>
<h3>Step 4: Tie it all together</h3>
<p>Now that we have a worker, our orchestrator needs to call it. Back in <code>Start</code>, fill it out with a call to our activity function passing the request <code>Person</code> object we got in:</p>
<pre><code class="language-csharp">[FunctionName(nameof(Start))]
public static async Task&lt;IList&lt;Error&gt;&gt; Start([OrchestrationTrigger]DurableOrchestrationContext context)
{
    var person = context.GetInput&lt;Person&gt;();
    var firstNameError = await context.CallActivityAsync&lt;Error&gt;(nameof(CheckFirstName), person);

    return new[] { firstNameError };
}
</code></pre>
<p>A few things happened here:</p>
<ol>
<li>We had to make the method <code>async</code> because we're executing <code>CallActivityAsync</code> to kick off the activity function</li>
<li>Our orchestration returns a list of Errors, like our API expects, so the return value becomes <code>Task&lt;IList&lt;Error&gt;&gt;</code></li>
<li>We get the input to send to our activity from the input that came in to the orchestrator; namely the <code>Person</code> object we deserialized in the starter.</li>
</ol>
<p>At this point our DF is fully testable. Let's give it a run and observe the output:</p>
<pre><code>[5/31/2018 4:09:00 PM] Generating 3 job function(s)
[5/31/2018 4:09:00 PM] Found the following functions:
[5/31/2018 4:09:00 PM] Functions.Function1.RunAsync
[5/31/2018 4:09:00 PM] Functions.Function1.Start
[5/31/2018 4:09:00 PM] Functions.Function1.CheckFirstName

...

Http Functions:

        Validate: https://localhost:7071/api/Validate
</code></pre>
<p>Note that the host found 3 functions - good - but only exposed one via HTTP. That's because the other 2 are used only internally by DF to conduct the orchestration; an outside party has no business invoking them. Awesome. Let's kick off <code>/Validate</code> and see what happens:</p>
<pre><code>POST /api/Validate HTTP/1.1
Host: localhost:7071
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 64700bdc-69d4-4faa-abc2-6628f5790715

{
    &quot;Name&quot; : {
        &quot;First&quot; : &quot;J&quot;,
        &quot;Last&quot; : &quot;Doe&quot;,
        &quot;Title&quot; : &quot;Mr&quot;
    },
    &quot;Address&quot; : {
        &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
        &quot;Line2&quot; : null,
        &quot;City&quot; : &quot;Somewhere&quot;,
        &quot;State&quot; : &quot;OR&quot;,
        &quot;Zip&quot; : &quot;12345&quot;,
        &quot;Country&quot; : &quot;United States of America&quot;
    }
}
</code></pre>
<p>Which kicks off our DF execution and the host starts spitting out log data:</p>
<pre><code>[5/31/2018 4:20:30 PM] Executing 'Validate' (Reason='This function was programmatically called via the host APIs.', Id=b2969100-d67e-4725-9545-7c017ff19923)
[5/31/2018 4:20:30 PM] Person request received:
[5/31/2018 4:20:30 PM] {
[5/31/2018 4:20:30 PM]     &quot;Name&quot; : {
[5/31/2018 4:20:30 PM]         &quot;First&quot; : &quot;J&quot;,
[5/31/2018 4:20:30 PM]         &quot;Last&quot; : &quot;Doe&quot;,
[5/31/2018 4:20:30 PM]         &quot;Title&quot; : &quot;Mr&quot;
[5/31/2018 4:20:30 PM]     },
[5/31/2018 4:20:30 PM]     &quot;Address&quot; : {
[5/31/2018 4:20:30 PM]         &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
[5/31/2018 4:20:30 PM]         &quot;Line2&quot; : null,
[5/31/2018 4:20:30 PM]         &quot;City&quot; : &quot;Somewhere&quot;,
[5/31/2018 4:20:30 PM]         &quot;State&quot; : &quot;OR&quot;,
[5/31/2018 4:20:30 PM]         &quot;Zip&quot; : &quot;12345&quot;,
[5/31/2018 4:20:30 PM]         &quot;Country&quot; : &quot;United States of America&quot;
[5/31/2018 4:20:30 PM]     }
[5/31/2018 4:20:30 PM] }
[5/31/2018 4:20:30 PM] 35ec223e3c2f4aff91d7d9727a894a83: Function 'Start (Orchestrator)' scheduled. Reason: NewInstance. IsReplay: False. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 0.
[5/31/2018 4:20:34 PM] Executed 'Validate' (Succeeded, Id=b2969100-d67e-4725-9545-7c017ff19923)
[5/31/2018 4:20:37 PM] Executing 'Start' (Reason='', Id=4956f975-380b-4e75-86ec-bd86225512d2)
[5/31/2018 4:20:37 PM] 35ec223e3c2f4aff91d7d9727a894a83: Function 'Start (Orchestrator)' started. IsReplay: False. Input: (1188 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 1.
[5/31/2018 4:20:37 PM] 35ec223e3c2f4aff91d7d9727a894a83: Function 'CheckFirstName (Activity)' scheduled. Reason: Start. IsReplay: False. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 2.
[5/31/2018 4:20:37 PM] Executed 'Start' (Succeeded, Id=4956f975-380b-4e75-86ec-bd86225512d2)
[5/31/2018 4:20:37 PM] 35ec223e3c2f4aff91d7d9727a894a83: Function 'Start (Orchestrator)' awaited. IsReplay: False. State: Awaited. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 3.
[5/31/2018 4:20:39 PM] 35ec223e3c2f4aff91d7d9727a894a83: Function 'CheckFirstName (Activity)' started. IsReplay: False. Input: (1196 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 4.
[5/31/2018 4:20:39 PM] Executing 'CheckFirstName' (Reason='', Id=2ddb9093-2588-489e-a39e-a83a266971d7)
[5/31/2018 4:20:39 PM] Message received: 35ec223e3c2f4aff91d7d9727a894a83
[5/31/2018 4:20:39 PM]  - Error found: First name is null or not longer than 1 character
[5/31/2018 4:20:39 PM] Executed 'CheckFirstName' (Succeeded, Id=2ddb9093-2588-489e-a39e-a83a266971d7)
[5/31/2018 4:20:39 PM] 35ec223e3c2f4aff91d7d9727a894a83: Function 'CheckFirstName (Activity)' completed. ContinuedAsNew: False. IsReplay: False. Output: (280 bytes). State: Completed. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 5.
[5/31/2018 4:20:40 PM] Executing 'Start' (Reason='', Id=9d968ad5-6d88-4d9b-ba99-c266a0adbac9)
[5/31/2018 4:20:40 PM] 35ec223e3c2f4aff91d7d9727a894a83: Function 'Start (Orchestrator)' started. IsReplay: True. Input: (1188 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 6.
[5/31/2018 4:20:40 PM] 35ec223e3c2f4aff91d7d9727a894a83: Function 'CheckFirstName (Activity)' scheduled. Reason: Start. IsReplay: True. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 7.
[5/31/2018 4:20:40 PM] 35ec223e3c2f4aff91d7d9727a894a83: Function 'Start (Orchestrator)' completed. ContinuedAsNew: False. IsReplay: False. Output: (288 bytes). State: Completed. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 8.
[5/31/2018 4:20:40 PM] Executed 'Start' (Succeeded, Id=9d968ad5-6d88-4d9b-ba99-c266a0adbac9)
</code></pre>
<p>After all is said and done, Postman gets this back for a response:</p>
<pre><code>Content-Length →788
Content-Type →application/json; charset=utf-8
Date →Thu, 31 May 2018 16:20:34 GMT
Location →https://localhost:7071/runtime/webhooks/DurableTaskExtension/instances/35ec223e3c2f4aff91d7d9727a894a83?taskHub=DurableFunctionsHub&amp;connection=Storage&amp;code=oGDC2qyC2H8gWrNUjpHAZxgj8CiF44hLxN5nebJZmAbCDo6nouIxag==
Retry-After →10
Server →Kestrel

{
    &quot;id&quot;: &quot;35ec223e3c2f4aff91d7d9727a894a83&quot;,
    &quot;statusQueryGetUri&quot;: &quot;https://localhost:7071/runtime/webhooks/DurableTaskExtension/instances/35ec223e3c2f4aff91d7d9727a894a83?taskHub=DurableFunctionsHub&amp;connection=Storage&amp;code=oGDC2qyC2H8gWrNUjpHAZxgj8CiF44hLxN5nebJZmAbCDo6nouIxag==&quot;,
    &quot;sendEventPostUri&quot;: &quot;https://localhost:7071/runtime/webhooks/DurableTaskExtension/instances/35ec223e3c2f4aff91d7d9727a894a83/raiseEvent/{eventName}?taskHub=DurableFunctionsHub&amp;connection=Storage&amp;code=oGDC2qyC2H8gWrNUjpHAZxgj8CiF44hLxN5nebJZmAbCDo6nouIxag==&quot;,
    &quot;terminatePostUri&quot;: &quot;https://localhost:7071/runtime/webhooks/DurableTaskExtension/instances/35ec223e3c2f4aff91d7d9727a894a83/terminate?reason={text}&amp;taskHub=DurableFunctionsHub&amp;connection=Storage&amp;code=oGDC2qyC2H8gWrNUjpHAZxgj8CiF44hLxN5nebJZmAbCDo6nouIxag==&quot;
}
</code></pre>
<p>which seems confusing, but if you look at the <code>Location</code> header and punch that in to Postman as an HTTP GET request you receive:</p>
<pre><code class="language-js">{
    &quot;runtimeStatus&quot;: &quot;Completed&quot;,
    &quot;input&quot;: {
        &quot;$type&quot;: &quot;Functions.Person, Functions&quot;,
        &quot;Name&quot;: {
            &quot;$type&quot;: &quot;Functions.Name, Functions&quot;,
            &quot;First&quot;: &quot;J&quot;,
            &quot;Last&quot;: &quot;Doe&quot;,
            &quot;Title&quot;: &quot;Mr&quot;
        },
        &quot;Address&quot;: {
            &quot;$type&quot;: &quot;Functions.Address, Functions&quot;,
            &quot;Line1&quot;: &quot;1234 Anywhere St.&quot;,
            &quot;Line2&quot;: null,
            &quot;City&quot;: &quot;Somewhere&quot;,
            &quot;State&quot;: &quot;OR&quot;,
            &quot;Zip&quot;: &quot;12345&quot;,
            &quot;Country&quot;: &quot;United States of America&quot;
        }
    },
    &quot;customStatus&quot;: null,
    &quot;output&quot;: [
        {
            &quot;id&quot;: 1,
            &quot;message&quot;: &quot;First name is null or not longer than 1 character&quot;
        }
    ],
    &quot;createdTime&quot;: &quot;2018-05-31T16:20:30Z&quot;,
    &quot;lastUpdatedTime&quot;: &quot;2018-05-31T16:20:40Z&quot;
}
</code></pre>
<p>and have a look at that <code>output</code> property - huzzah!</p>
<p>For more information on the URLs given to you by the response from a POST to a Durable Functions starter, you can <a href="https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-http-api" target="_blank">read the docs here</a>.</p>
<p>Let's evolve our workflow, though, in to something more complex by first &quot;chaining&quot; our functions together, and then running them in parallel (fan out/in)</p>
<h3>Function chaining with Durable Functions</h3>
<p>As you might've guessed by now, you can chain functions together by simply coordinating their inputs and outputs. If we add in the Last Name validation to our flow, we end up with a new Activity function:</p>
<pre><code class="language-csharp">[FunctionName(nameof(CheckLastName))]
public static async Task&lt;InputOutput&gt; CheckLastName([ActivityTrigger]DurableActivityContext context, TraceWriter log)
{
    await Task.Delay(1400);

    var io = context.GetInput&lt;InputOutput&gt;();
    if ((io?.Input?.Name?.Last?.Length &gt; 1) == false)
    {
        io.Output.Add(new Error { id = 2, message = &quot;Last name is null or not longer than 1 character&quot; });
    }

    return io;
}
</code></pre>
<p>Here we've set up the input to our 2nd function to be and <code>InputOutput</code> type that looks like this:</p>
<pre><code class="language-csharp">public class InputOutput
{
    public IList&lt;Error&gt; Output { get; set; } = new Error[0];

    public Person Input { get; set; }
}
</code></pre>
<p>So each function can augment it as they see fit, and at the end of the orchestration we'll simply store <code>Output</code> as the result.</p>
<p>This changes our implementation of the Starter and CheckFirstName as well, but only slightly:</p>
<pre><code class="language-csharp">[FunctionName(nameof(CheckFirstName))]
public static async Task&lt;InputOutput&gt; CheckFirstName([ActivityTrigger]DurableActivityContext context, TraceWriter log)
{
    await Task.Delay(1300);
    var person = context.GetInput&lt;Person&gt;();
    log.Info($@&quot;Message received: {context.InstanceId}&quot;);
    if ((person?.Name?.First?.Length &gt; 1) == false)
    {
        var err = new Error { id = 1, message = &quot;First name is null or not longer than 1 character&quot; };
        log.Info($@&quot; - Error found: {err.message}&quot;);
        return new InputOutput { Output = new[] { err }, Input = person };
    }
    else
    {
        log.Info($@&quot; - No error found&quot;);
        return new InputOutput { Input = person };
    }
}
</code></pre>
<pre><code class="language-csharp">[FunctionName(nameof(Start))]
public static async Task&lt;IList&lt;Error&gt;&gt; Start([OrchestrationTrigger]DurableOrchestrationContext context)
{
    var person = context.GetInput&lt;Person&gt;();

    var chainedInputOutput = await context.CallActivityAsync&lt;InputOutput&gt;(nameof(CheckFirstName), person);
    chainedInputOutput = await context.CallActivityAsync&lt;InputOutput&gt;(nameof(CheckLastName), chainedInputOutput);

    return chainedInputOutput.Output;
}
</code></pre>
<p>Let's give it a run and observe the output from our Functions host:</p>
<pre><code>[5/31/2018 4:36:06 PM] Executing 'Validate' (Reason='This function was programmatically called via the host APIs.', Id=ba7a080e-a701-451f-971b-d7ea9670ce60)
[5/31/2018 4:36:07 PM] Person request received:
[5/31/2018 4:36:07 PM] {
[5/31/2018 4:36:07 PM]     &quot;Name&quot; : {
[5/31/2018 4:36:07 PM]         &quot;First&quot; : &quot;J&quot;,
[5/31/2018 4:36:07 PM]         &quot;Last&quot; : &quot;Doe&quot;,
[5/31/2018 4:36:07 PM]         &quot;Title&quot; : &quot;Mr&quot;
[5/31/2018 4:36:07 PM]     },
[5/31/2018 4:36:07 PM]     &quot;Address&quot; : {
[5/31/2018 4:36:07 PM]         &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
[5/31/2018 4:36:07 PM]         &quot;Line2&quot; : null,
[5/31/2018 4:36:07 PM]         &quot;City&quot; : &quot;Somewhere&quot;,
[5/31/2018 4:36:07 PM]         &quot;State&quot; : &quot;OR&quot;,
[5/31/2018 4:36:07 PM]         &quot;Zip&quot; : &quot;12345&quot;,
[5/31/2018 4:36:07 PM]         &quot;Country&quot; : &quot;United States of America&quot;
[5/31/2018 4:36:07 PM]     }
[5/31/2018 4:36:07 PM] }
[5/31/2018 4:36:07 PM] ebc3b429c89942429046ce54c54eaccb: Function 'Start (Orchestrator)' scheduled. Reason: NewInstance. IsReplay: False. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 0.
[5/31/2018 4:36:09 PM] Executed 'Validate' (Succeeded, Id=ba7a080e-a701-451f-971b-d7ea9670ce60)
[5/31/2018 4:36:10 PM] Executing 'Start' (Reason='', Id=4cfd7beb-89f8-4b84-b738-a47b1d6e8c13)
[5/31/2018 4:36:10 PM] ebc3b429c89942429046ce54c54eaccb: Function 'Start (Orchestrator)' started. IsReplay: False. Input: (1188 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 1.
[5/31/2018 4:36:10 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckFirstName (Activity)' scheduled. Reason: Start. IsReplay: False. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 2.
[5/31/2018 4:36:10 PM] Executed 'Start' (Succeeded, Id=4cfd7beb-89f8-4b84-b738-a47b1d6e8c13)
[5/31/2018 4:36:10 PM] ebc3b429c89942429046ce54c54eaccb: Function 'Start (Orchestrator)' awaited. IsReplay: False. State: Awaited. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 3.
[5/31/2018 4:36:13 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckFirstName (Activity)' started. IsReplay: False. Input: (1196 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 4.
[5/31/2018 4:36:13 PM] Executing 'CheckFirstName' (Reason='', Id=6a1dbbe1-2ac6-4a6e-84c4-3e506d94615b)
[5/31/2018 4:36:14 PM] Message received: ebc3b429c89942429046ce54c54eaccb
[5/31/2018 4:36:14 PM]  - Error found: First name is null or not longer than 1 character
[5/31/2018 4:36:15 PM] Executed 'CheckFirstName' (Succeeded, Id=6a1dbbe1-2ac6-4a6e-84c4-3e506d94615b)
[5/31/2018 4:36:15 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckFirstName (Activity)' completed. ContinuedAsNew: False. IsReplay: False. Output: (1104 bytes). State: Completed. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 5.
[5/31/2018 4:36:16 PM] Executing 'Start' (Reason='', Id=ccae9c2c-4243-48f1-bbee-5926687350fc)
[5/31/2018 4:36:16 PM] ebc3b429c89942429046ce54c54eaccb: Function 'Start (Orchestrator)' started. IsReplay: True. Input: (1188 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 6.
[5/31/2018 4:36:16 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckFirstName (Activity)' scheduled. Reason: Start. IsReplay: True. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 7.
[5/31/2018 4:36:16 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckLastName (Activity)' scheduled. Reason: Start. IsReplay: False. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 8.
[5/31/2018 4:36:16 PM] Executed 'Start' (Succeeded, Id=ccae9c2c-4243-48f1-bbee-5926687350fc)
[5/31/2018 4:36:16 PM] ebc3b429c89942429046ce54c54eaccb: Function 'Start (Orchestrator)' awaited. IsReplay: False. State: Awaited. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 9.
[5/31/2018 4:36:18 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckLastName (Activity)' started. IsReplay: False. Input: (1964 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 10.
[5/31/2018 4:36:18 PM] Executing 'CheckLastName' (Reason='', Id=aff38799-8268-435b-934c-d94dff88d931)
[5/31/2018 4:36:20 PM] Executed 'CheckLastName' (Succeeded, Id=aff38799-8268-435b-934c-d94dff88d931)
[5/31/2018 4:36:20 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckLastName (Activity)' completed. ContinuedAsNew: False. IsReplay: False. Output: (1104 bytes). State: Completed. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 11.
[5/31/2018 4:36:21 PM] Executing 'Start' (Reason='', Id=e7f8047e-eccc-4a75-aab0-9ac085f03b72)
[5/31/2018 4:36:21 PM] ebc3b429c89942429046ce54c54eaccb: Function 'Start (Orchestrator)' started. IsReplay: True. Input: (1188 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 12.
[5/31/2018 4:36:21 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckFirstName (Activity)' scheduled. Reason: Start. IsReplay: True. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 13.
[5/31/2018 4:36:21 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckFirstName (Activity)' completed. ContinuedAsNew: False. IsReplay: True. Output: (replayed). State: Completed. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 14.
[5/31/2018 4:36:21 PM] ebc3b429c89942429046ce54c54eaccb: Function 'CheckLastName (Activity)' scheduled. Reason: Start. IsReplay: True. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 15.
[5/31/2018 4:36:21 PM] ebc3b429c89942429046ce54c54eaccb: Function 'Start (Orchestrator)' completed. ContinuedAsNew: False. IsReplay: False. Output: (288 bytes). State: Completed. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 16.
[5/31/2018 4:36:22 PM] Executed 'Start' (Succeeded, Id=e7f8047e-eccc-4a75-aab0-9ac085f03b72)
</code></pre>
<p>Notice in our activity functions I had added a couple of <code>await Task.Delay</code> calls. Also notice that our full execution took around 15 seconds, but in Postman I had a response back from the endpoint within 5.</p>
<p>A subsequent call to the <code>Location</code> header value of the <code>202 ACCEPTED</code> response I got back yielded:</p>
<pre><code class="language-js">{
    &quot;runtimeStatus&quot;: &quot;Completed&quot;,
    &quot;input&quot;: {
        &quot;$type&quot;: &quot;Functions.Person, Functions&quot;,
        &quot;Name&quot;: {
            &quot;$type&quot;: &quot;Functions.Name, Functions&quot;,
            &quot;First&quot;: &quot;J&quot;,
            &quot;Last&quot;: &quot;Doe&quot;,
            &quot;Title&quot;: &quot;Mr&quot;
        },
        &quot;Address&quot;: {
            &quot;$type&quot;: &quot;Functions.Address, Functions&quot;,
            &quot;Line1&quot;: &quot;1234 Anywhere St.&quot;,
            &quot;Line2&quot;: null,
            &quot;City&quot;: &quot;Somewhere&quot;,
            &quot;State&quot;: &quot;OR&quot;,
            &quot;Zip&quot;: &quot;12345&quot;,
            &quot;Country&quot;: &quot;United States of America&quot;
        }
    },
    &quot;customStatus&quot;: null,
    &quot;output&quot;: [
        {
            &quot;id&quot;: 1,
            &quot;message&quot;: &quot;First name is null or not longer than 1 character&quot;
        }
    ],
    &quot;createdTime&quot;: &quot;2018-05-31T16:36:07Z&quot;,
    &quot;lastUpdatedTime&quot;: &quot;2018-05-31T16:36:22Z&quot;
}
</code></pre>
<p>exactly what we expected.</p>
<p>What happens if we call the location endpoint before the run's completed? Get your ninja copy/paste skills ready and give it a shot:</p>
<pre><code class="language-js">{
    &quot;runtimeStatus&quot;: &quot;Running&quot;,
    &quot;input&quot;: {
        &quot;$type&quot;: &quot;Functions.Person, Functions&quot;,
        &quot;Name&quot;: {
            &quot;$type&quot;: &quot;Functions.Name, Functions&quot;,
            &quot;First&quot;: &quot;J&quot;,
            &quot;Last&quot;: &quot;Doe&quot;,
            &quot;Title&quot;: &quot;Mr&quot;
        },
        &quot;Address&quot;: {
            &quot;$type&quot;: &quot;Functions.Address, Functions&quot;,
            &quot;Line1&quot;: &quot;1234 Anywhere St.&quot;,
            &quot;Line2&quot;: null,
            &quot;City&quot;: &quot;Somewhere&quot;,
            &quot;State&quot;: &quot;OR&quot;,
            &quot;Zip&quot;: &quot;12345&quot;,
            &quot;Country&quot;: &quot;United States of America&quot;
        }
    },
    &quot;customStatus&quot;: null,
    &quot;output&quot;: null,
    &quot;createdTime&quot;: &quot;2018-05-31T16:39:22Z&quot;,
    &quot;lastUpdatedTime&quot;: &quot;2018-05-31T16:39:28Z&quot;
}
</code></pre>
<p>notice the first property, <code>runtimeStatus</code> with a value of <code>Running</code> and how our <code>output</code> property is still <code>null</code>. This indicates the DF is in progress and the caller should check back later. Waiting a few more seconds to call it and we get back</p>
<pre><code class="language-js">{
    &quot;runtimeStatus&quot;: &quot;Completed&quot;,
    &quot;input&quot;: {
        &quot;$type&quot;: &quot;Functions.Person, Functions&quot;,
        &quot;Name&quot;: {
            &quot;$type&quot;: &quot;Functions.Name, Functions&quot;,
            &quot;First&quot;: &quot;J&quot;,
            &quot;Last&quot;: &quot;Doe&quot;,
            &quot;Title&quot;: &quot;Mr&quot;
        },
        &quot;Address&quot;: {
            &quot;$type&quot;: &quot;Functions.Address, Functions&quot;,
            &quot;Line1&quot;: &quot;1234 Anywhere St.&quot;,
            &quot;Line2&quot;: null,
            &quot;City&quot;: &quot;Somewhere&quot;,
            &quot;State&quot;: &quot;OR&quot;,
            &quot;Zip&quot;: &quot;12345&quot;,
            &quot;Country&quot;: &quot;United States of America&quot;
        }
    },
    &quot;customStatus&quot;: null,
    &quot;output&quot;: [
        {
            &quot;id&quot;: 1,
            &quot;message&quot;: &quot;First name is null or not longer than 1 character&quot;
        }
    ],
    &quot;createdTime&quot;: &quot;2018-05-31T16:39:22Z&quot;,
    &quot;lastUpdatedTime&quot;: &quot;2018-05-31T16:39:37Z&quot;
}
</code></pre>
<p>as expected.</p>
<p>So now you can see that chaining functions, or executing them sequentially is as simple as async/await elsewhere in .Net. But what about running them in parallel (aka Fan out/in pattern)?</p>
<h4>Parallel execution (Fan out/in pattern)</h4>
<p>Well, believe it or not you've already seen how this is done, it's just got a bit of a DF twist on it. Much like our Azure function, the trick here is to put all the <code>CallActivityAsync&lt;&gt;</code> calls in to a <code>Task[]</code> collection and then <code>WaitAll</code> on the collection. As you also might have figured out, our current <code>InputOutput</code> construct won't work here due to the parallel nature so instead let's just have each function put out its error (or <code>null</code>) and we'll aggregate when we're done.</p>
<p>Let's get started.</p>
<p>First, change our Starter to call the activities in parallel and wait on the collection:</p>
<pre><code class="language-csharp">var tasks = new[]
{
    context.CallActivityAsync&lt;Error&gt;(nameof(CheckFirstName), person),
    context.CallActivityAsync&lt;Error&gt;(nameof(CheckLastName), person)
};

var errors = await Task.WhenAll(tasks);
</code></pre>
<p>You see, also, here that we're now just giving our <code>Person</code> object to everybody, which changes our implementation of the activities slightly:</p>
<pre><code class="language-csharp">[FunctionName(nameof(CheckFirstName))]
public static async Task&lt;Error&gt; CheckFirstName([ActivityTrigger]DurableActivityContext context, TraceWriter log)
{
    await Task.Delay(1300);
    var person = context.GetInput&lt;Person&gt;();
    log.Info($@&quot;Message received: {context.InstanceId}&quot;);
    if ((person?.Name?.First?.Length &gt; 1) == false)
    {
        var err = new Error { id = 1, message = &quot;First name is null or not longer than 1 character&quot; };
        log.Info($@&quot; - Error found: {err.message}&quot;);
        return err;
    }

    log.Info($@&quot; - No error found&quot;);
    return null;
}

[FunctionName(nameof(CheckLastName))]
public static async Task&lt;Error&gt; CheckLastName([ActivityTrigger]DurableActivityContext context, TraceWriter log)
{
    await Task.Delay(1400);

    var person = context.GetInput&lt;Person&gt;();
    if ((person?.Name?.Last?.Length &gt; 1) == false)
    {
        var err = new Error { id = 2, message = &quot;Last name is null or not longer than 1 character&quot; };
        log.Info($@&quot; - Error found: {err.message}&quot;);
        return err;
    }

    log.Info($@&quot; - No error found&quot;);
    return null;
}
</code></pre>
<p>And finally, we need to return the results from our orchestrator:</p>
<pre><code class="language-csharp">var errors = await Task.WhenAll(tasks);

return errors.Where(e =&gt; e != null).ToList();
</code></pre>
<p>Let's give it a run, paying attention to the output as we should see both Activity Functions executing simultaneously.
And sure enough:</p>
<pre><code>[5/31/2018 4:49:13 PM] Executing 'Validate' (Reason='This function was programmatically called via the host APIs.', Id=4496dbf0-d09e-44fc-95d2-2445ea612bbb)
[5/31/2018 4:49:13 PM] Person request received:
[5/31/2018 4:49:13 PM] {
[5/31/2018 4:49:13 PM]     &quot;Name&quot; : {
[5/31/2018 4:49:13 PM]         &quot;First&quot; : &quot;J&quot;,
[5/31/2018 4:49:13 PM]         &quot;Last&quot; : &quot;Doe&quot;,
[5/31/2018 4:49:13 PM]         &quot;Title&quot; : &quot;Mr&quot;
[5/31/2018 4:49:13 PM]     },
[5/31/2018 4:49:13 PM]     &quot;Address&quot; : {
[5/31/2018 4:49:13 PM]         &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
[5/31/2018 4:49:13 PM]         &quot;Line2&quot; : null,
[5/31/2018 4:49:13 PM]         &quot;City&quot; : &quot;Somewhere&quot;,
[5/31/2018 4:49:13 PM]         &quot;State&quot; : &quot;OR&quot;,
[5/31/2018 4:49:13 PM]         &quot;Zip&quot; : &quot;12345&quot;,
[5/31/2018 4:49:13 PM]         &quot;Country&quot; : &quot;United States of America&quot;
[5/31/2018 4:49:13 PM]     }
[5/31/2018 4:49:13 PM] }
[5/31/2018 4:49:13 PM] 4e580cf9c1f841a6b820eb030e6c37bf: Function 'Start (Orchestrator)' scheduled. Reason: NewInstance. IsReplay: False. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 13.
[5/31/2018 4:49:14 PM] Executed 'Validate' (Succeeded, Id=4496dbf0-d09e-44fc-95d2-2445ea612bbb)
[5/31/2018 4:49:17 PM] Executing 'Start' (Reason='', Id=2c80b880-6062-4a04-a2c3-5b2f6fc0490e)
[5/31/2018 4:49:17 PM] 4e580cf9c1f841a6b820eb030e6c37bf: Function 'Start (Orchestrator)' started. IsReplay: False. Input: (1188 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 14.
[5/31/2018 4:49:18 PM] 4e580cf9c1f841a6b820eb030e6c37bf: Function 'CheckFirstName (Activity)' scheduled. Reason: Start. IsReplay: False. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 15.
[5/31/2018 4:49:18 PM] 4e580cf9c1f841a6b820eb030e6c37bf: Function 'CheckLastName (Activity)' scheduled. Reason: Start. IsReplay: False. State: Scheduled. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 16.
[5/31/2018 4:49:18 PM] Executed 'Start' (Succeeded, Id=2c80b880-6062-4a04-a2c3-5b2f6fc0490e)
[5/31/2018 4:49:18 PM] 4e580cf9c1f841a6b820eb030e6c37bf: Function 'Start (Orchestrator)' awaited. IsReplay: False. State: Awaited. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 17.
[5/31/2018 4:49:19 PM] 4e580cf9c1f841a6b820eb030e6c37bf: Function 'CheckFirstName (Activity)' started. IsReplay: False. Input: (1196 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 18.
[5/31/2018 4:49:19 PM] Executing 'CheckFirstName' (Reason='', Id=c1607f15-607d-40e1-a14e-74a1c0046c13)
[5/31/2018 4:49:20 PM] 4e580cf9c1f841a6b820eb030e6c37bf: Function 'CheckLastName (Activity)' started. IsReplay: False. Input: (1196 bytes). State: Started. HubName: DurableFunctionsHub. AppName: . SlotName: . ExtensionVersion: 1.4.1.0. SequenceNumber: 19.
[5/31/2018 4:49:20 PM] Executing 'CheckLastName' (Reason='', Id=8a38bb91-4c3b-431a-bfb9-66e8c6f259bd)

...
</code></pre>
<p>Notice that <code>CheckFirstName</code> has not completed before <code>CheckLastName</code> kicked off. And yet, we waited for all to be done before our <code>output</code> value arrived at our endpoint and was populated correctly.</p>
<h3>The implementation</h3>
<p>So how is Durable Functions managing all this? It's all done within the storage account you specify for <code>AzureWebJobsStorage</code>; required by Azure Functions. If you open Storage Explorer and have a look, you'll see a number of Durable Functions-created containers, tables, and queues:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/31/46c26209.png" alt=""></p>
<p>and it is within these that DF manages the state of each orchestration including inputs/outputs to/from Activity functions and where each orchestration instance is in its execution.</p>
<p>In short, DF manages execution by using Storage Queues to pass messages to/from Activity Functions and the Orchestrator. The Orchestrator maintains the state of an individual orchestration within Table storage and that's what you're getting when you hit the <code>Location</code> endpoint returned by the 202 ACCEPTED response to the Starter.</p>
<p>Because Storage Queues only have polling capability today w/in Functions, this is also why this particular set up takes longer to run than the Service Bus or Logic Apps approach shown in Step 3. My hope for the future is this will eventually be driven by Event Grid for near-instantaneous execution of activities &amp; orchestrations.</p>
<hr>
<p>That concludes the series! I hope you've found this insightful and educational as you plan to move your workflows to the cloud and take advantage of the microbilling and autoscaling that Azure Serverless has to offer!</p>]]></content:encoded>
    </item>
    <item>
      <title>Make Serverless Music - Orchestrate your workflow with Azure [Part 3 - Azure Functions]</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/make-serverless-music-orchestrate-your-workflow-with-azure-part-3-azure-functions</link>
      <pubDate>Thu, 31 May 2018 02:03:51 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=225</guid>
      <description><![CDATA[At this point we've seen the declarative way to define a workflow orchestration using both Microsoft...]]></description>
      <content:encoded><![CDATA[<p>At this point we've seen the declarative way to define a workflow orchestration using both Microsoft Flow and Azure Logic Apps but hey, this is .Netitude and here we write .Net, right? Let's get to it then!</p>
<p>You've likely already heard of Azure Functions (otherwise hey <a href="https://azure.microsoft.com/en-us/services/functions/" target="_blank">click here</a>!), Azure's serverless web execution allowing you to do thousands, even millions, of executions for <a href="https://blogs.msdn.microsoft.com/webdev/2018/05/21/a-penny-saved-is-a-ton-of-serverless-compute-earned/" target="_blank">merely pennies per run</a>. In many cases you can get away with a serverless implementation <a href="https://azure.microsoft.com/en-us/pricing/details/functions/" target="_blank">completely free</a>!</p>
<p>With that in mind, let's implement our solution from earlier in this series in Azure Functions. As a reminder here are the requirements:</p>
<p>When I receive a request to my Function, I want to</p>
<ol>
<li>Validate the schema of the incoming JSON request.</li>
<li>Validate the content of the JSON request against business rules.</li>
<li>Return a response indicating which validations failed and which ones passed.</li>
</ol>
<p>We've defined our schema as a Person schema like so:</p>
<pre><code class="language-javascript">{
    &quot;Name&quot; : {
        &quot;First&quot; : &quot;John&quot;,
        &quot;Last&quot; : &quot;Doe&quot;,
        &quot;Title&quot; : &quot;Mr&quot;
    },
    &quot;Address&quot; : {
        &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
        &quot;Line2&quot; : null,
        &quot;City&quot; : &quot;Somewhere&quot;,
        &quot;State&quot; : &quot;OR&quot;,
        &quot;Zip&quot; : &quot;12345&quot;,
        &quot;Country&quot; : &quot;United States of America&quot;
    }
}
</code></pre>
<p>For our business rules, we'll enforce:</p>
<ol>
<li>First &amp; Last name must be present &amp; longer than 1 character</li>
<li>If Address Line 2 is not null, Line 1 must also not be null</li>
<li>City must be present</li>
<li>State must be present &amp; only a 2-letter abbreviation</li>
<li>Zip must be present and 5 characters</li>
</ol>
<h4>Step 1: Create an Azure Functions project</h4>
<p>If you haven't already, install VS 2017 (Community Edition is fine) with the Azure Workload option.
Next,</p>
<ol>
<li>Click File | New Project</li>
<li>Choose Cloud | Azure Function</li>
<li>Choose Azure Functions v2, HTTP Trigger, Storage Emulator, Function authentication</li>
</ol>
<h4>Step 2: Validate the schema</h4>
<p>Like most things, Visual Studio makes this cake with the 'Paste JSON as code' feature. Simply highlight the JSON above, go to VS 2017, create a new class file (let's call it <code>Person.cs</code>), click 'Edit' | 'Paste Special' | 'Paste JSON as classes' and voila:</p>
<pre><code class="language-csharp">namespace Functions
{
    public class Rootobject
    {
        public Name Name { get; set; }
        public Address Address { get; set; }
    }

    public class Name
    {
        public string First { get; set; }
        public string Last { get; set; }
        public string Title { get; set; }
    }

    public class Address
    {
        public string Line1 { get; set; }
        public object Line2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Zip { get; set; }
        public string Country { get; set; }
    }
}
</code></pre>
<p>for readability, rename <code>Rootobject</code> to <code>Person</code>. Because we put <code>null</code> in the sample for <code>Line2</code>, we need to fix that up by changing it to</p>
<pre><code class="language-csharp">public *string* Line2 { get; set; }
</code></pre>
<p>Back in <code>Function1</code> now, we can enforce the validation of the incoming JSON by simply telling the HttpTrigger binding that it should be of type <code>Person</code> instead of <code>HttpRequest</code>:</p>
<pre><code class="language-csharp">public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, &quot;get&quot;, &quot;post&quot;, Route = null)]Person req, TraceWriter log)
</code></pre>
<p>Let's also clean this up by allowing only POST requests, not GET requests:</p>
<pre><code class="language-csharp">public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]Person req, TraceWriter log)
</code></pre>
<p>and finally, let's name the function <code>Validate</code>:</p>
<pre><code class="language-csharp">[FunctionName(&quot;Validate&quot;)]
public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]Person req, TraceWriter log)
</code></pre>
<p>Now our function will ensure any incoming POST request to /Validate has a body that can be deserialized to our <code>Person</code> object.</p>
<h4>Step 3: Run the validations</h4>
<h5>&quot;Chained&quot; approach</h5>
<p>Our validations are stored in an array (more than one can fail) so let's fab that code up now and see how to return it as part of an HTTP 200 response from the Function:</p>
<pre><code class="language-csharp">var errors = new List&lt;Error&gt;();

return new OkObjectResult(errors);
</code></pre>
<p>Where we've defined <code>Error</code> to be:</p>
<pre><code class="language-csharp">private class Error
{
    public int id { get; set; }
    public string message { get; set; }
};
</code></pre>
<p>Functions will, by default, return JSON payloads for all types output to the <code>*ObjectResult</code> types returned from a Function method.</p>
<p>Obviously the validations we have can be done in straight .Net pretty simply:</p>
<pre><code class="language-csharp">if ((req?.Name?.First?.Length &gt; 1) == false)
{
    errors.Add(new Error { id = 1, message = &quot;First name is null or not longer than 1 character&quot; });
}

if ((req?.Name?.Last?.Length &gt; 1) == false)
{
    errors.Add(new Error { id = 2, message = &quot;Last name is null or not longer than 1 character&quot; });
}

if (!string.IsNullOrEmpty(req?.Address?.Line2) &amp;&amp; string.IsNullOrEmpty(req?.Address?.Line1))
{
    errors.Add(new Error { id = 3, message = &quot;Address line 2 is populated but line 1 is empty&quot; });
}

if (string.IsNullOrEmpty(req?.Address?.City))
{
    errors.Add(new Error { id = 4, message = &quot;City is empty&quot; });
}

if ((req?.Address?.State?.Length == 2) == false)
{
    errors.Add(new Error { id = 5, message = &quot;State is null or not a 2-letter abbreviation&quot; });
}

if ((req?.Address?.Zip?.Length == 5) == false)
{
    errors.Add(new Error { id = 6, message = &quot;Zip is null or not 5 digits&quot; });
}
</code></pre>
<p>and it works splendidly:</p>
<pre><code>POST /api/Validate HTTP/1.1
Host: localhost:7071
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: db88214a-8699-4766-bd48-d1a6d1fd495b

{
    &quot;Name&quot; : {
        &quot;First&quot; : &quot;J&quot;,
        &quot;Last&quot; : &quot;Doe&quot;,
        &quot;Title&quot; : &quot;Mr&quot;
    },
    &quot;Address&quot; : {
        &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
        &quot;Line2&quot; : null,
        &quot;City&quot; : &quot;Somewhere&quot;,
        &quot;State&quot; : &quot;OR&quot;,
        &quot;Zip&quot; : &quot;12345&quot;,
        &quot;Country&quot; : &quot;United States of America&quot;
    }
}
</code></pre>
<pre><code>Content-Type →application/json; charset=utf-8
Date →Wed, 30 May 2018 04:30:29 GMT
Server →Kestrel
Transfer-Encoding →chunked

[
    {
        &quot;id&quot;: 1,
        &quot;message&quot;: &quot;First name is null or not longer than 1 character&quot;
    }
]
</code></pre>
<h5>Fan out/in approach</h5>
<p>The previous code roughly corresponds to the sequential Flow set up in the first post of this series. But let's be real, we'd most certainly be doing something a bit more complex than these operations in real life, right? So let's <code>async</code> this work, and go on to extend it even further.</p>
<p>The body of our Function becomes:</p>
<pre><code class="language-csharp">var errors = new List&lt;Error&gt;();

// Fan Out
var checks = new List&lt;Task&lt;Error&gt;&gt;
{
    CheckFirstName(req, errors),
    CheckLastName(req, errors),
    CheckAddressLines(req, errors),
    CheckCity(req, errors),
    CheckState(req, errors),
    CheckZip(req, errors)
};

// wait for all checks to complete (Fan In)
await Task.WhenAll(checks);

// Add any non-null values to our errors list
errors.AddRange(checks.Select(t =&gt; t.Result).Where(r =&gt; r != null));

return new OkObjectResult(errors);
</code></pre>
<p>In this approach we kick off all the <code>Check*</code> methods to do their work and add the resulting <code>Task&lt;Error&gt;</code> object to a collection which we then wait for <strong>all</strong> tasks to complete. Once they do, any that have a non-null result have returned an <code>Error</code> object and we should add that to our list to return back to the caller as the JSON body of our HTTP 200 response.</p>
<p>Each <code>Check*</code> method looks like this:</p>
<pre><code class="language-csharp">private static async Task&lt;Error&gt; CheckZip(Person req)
{
    await Task.Delay(1000);
    if ((req?.Address?.Zip?.Length == 5) == false)
    {
        return new Error { id = 6, message = &quot;Zip is null or not 5 digits&quot; };
    }

    return null;
}

private static async Task&lt;Error&gt; CheckState(Person req)
{
    await Task.Delay(1100);
    if ((req?.Address?.State?.Length == 2) == false)
    {
        return new Error { id = 5, message = &quot;State is null or not a 2-letter abbreviation&quot; };
    }

    return null;
}

private static async Task&lt;Error&gt; CheckCity(Person req)
{
    await Task.Delay(1200);
    if (string.IsNullOrEmpty(req?.Address?.City))
    {
        return new Error { id = 4, message = &quot;City is empty&quot; };
    }

    return null;
}

private static async Task&lt;Error&gt; CheckAddressLines(Person req)
{
    await Task.Delay(1300);
    if (!string.IsNullOrEmpty(req?.Address?.Line2) &amp;&amp; string.IsNullOrEmpty(req?.Address?.Line1))
    {
        return new Error { id = 3, message = &quot;Address line 2 is populated but line 1 is empty&quot; };
    }

    return null;
}

private static async Task&lt;Error&gt; CheckLastName(Person req)
{
    await Task.Delay(1400);
    if ((req?.Name?.Last?.Length &gt; 1) == false)
    {
        return new Error { id = 2, message = &quot;Last name is null or not longer than 1 character&quot; };
    }

    return null;
}

private static async Task&lt;Error&gt; CheckFirstName(Person req)
{
    await Task.Delay(1500);
    if ((req?.Name?.First?.Length &gt; 1) == false)
    {
        return new Error { id = 1, message = &quot;First name is null or not longer than 1 character&quot; };
    }

    return null;
}
</code></pre>
<p>Notice that I've put in <code>Task.Delay()</code> calls to artificially make the execution of the methods take some time; emulating real-world behavior.</p>
<p>What if our calls were other Azure Functions, though? Well, not a whole lot changes except for the signatures of our validation methods and how we call them. Let's take a look:</p>
<pre><code class="language-csharp">[FunctionName(&quot;CheckZip&quot;)]
public static async Task&lt;IActionResult&gt; CheckZip([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]Person req)
{
    await Task.Delay(1000);
    if ((req?.Address?.Zip?.Length == 5) == false)
    {
        return new OkObjectResult(new Error { id = 6, message = &quot;Zip is null or not 5 digits&quot; });
    }

    return new NoContentResult();
}
</code></pre>
<p>We label the method as a Function, denote it's triggered via HTTP, and return an Http <code>IActionResult</code> instead of an object.</p>
<p>We also need to add an HttpClient to our Function:</p>
<pre><code class="language-csharp">private static HttpClient _client = new HttpClient { BaseAddress = new System.Uri(@&quot;https://localhost:7071/api/&quot;) };
</code></pre>
<blockquote>
<p>I set the BaseAddress here to make the <code>PostAsync()</code> calls cleaner later</p>
</blockquote>
<p>With those changes made to all the Check methods, let's look at the body of our &quot;orchestrator&quot; and how it changes:</p>
<pre><code class="language-csharp">var errors = new List&lt;Error&gt;();

var personPostContent = new StringContent(JsonConvert.SerializeObject(req), Encoding.Default, @&quot;application/json&quot;);
// Fan Out
var checks = new List&lt;Task&lt;HttpResponseMessage&gt;&gt;
{
    _client.PostAsync(@&quot;CheckFirstName&quot;, personPostContent),
    _client.PostAsync(@&quot;CheckLastName&quot;, personPostContent),
    _client.PostAsync(@&quot;CheckAddressLines&quot;, personPostContent),
    _client.PostAsync(@&quot;CheckCity&quot;, personPostContent),
    _client.PostAsync(@&quot;CheckState&quot;, personPostContent),
    _client.PostAsync(@&quot;CheckZip&quot;, personPostContent)
};

// wait for all checks to complete (Fan In)
var responses = await Task.WhenAll(checks);

// Add any non-null values to our errors list
foreach (var response in responses)
{
    var err = await response.Content.ReadAsAsync&lt;Error&gt;();
    if (err != null)
    {
        errors.Add(err);
    }
}

return new OkObjectResult(errors);
</code></pre>
<blockquote>
<p>I wasn't able to get <code>PostAsJsonAsync</code> methods on <code>HttpClient</code> to work successfully; the payload kept coming to the Functions as <code>null</code> instead of being properly serialized/deserialized to a <code>Person</code> object. Hence the need for the <code>personPostContent</code> line.</p>
</blockquote>
<p>Debugging the Function now, you see many Functions indexed by the host, and their execution all kicked off in parallel. But at the end of the day they all &quot;fan back in&quot; and we process their results and return it back to the caller.</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/b93f1639.png" alt=""></p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/c6964002.png" alt=""></p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/a03d6857.png" alt=""></p>
<p>There's are a couple of problems with this implementation, though.</p>
<ol>
<li>We're now distributed across Azure Functions or even disparate web services. This means latency problems, connection issues, and the like.</li>
<li>Azure Functions, in the Consumption plan, is limited to 5-minutes per execution by default (you can increase it to 10 if you like with some host.json editing). What if our total orchestration takes longer than this?</li>
</ol>
<p>How can we solve these?</p>
<h5>Tackling it with Logic Apps</h5>
<p>One way to handle this issue is to orchestrate our Function calls with Azure's purpose-build orchestration offering: Logic Apps. As you might expect, its integration with Functions is first-class; let's take a look.</p>
<p>First, deploy the Functions we wrote above (the orchestrator and all the sub-task functions) out to Azure so we can use them from our Logic App.</p>
<p>Next, create a new Logic App in Azure, and head to the designer surface.</p>
<p>The first step of our Logic App is going to be the same as it was for Flow (and the subsequent LA import); a 'Request' trigger with JSON schema in it matching what we expect from our caller. If you did the Microsoft Flow part of this series, it should look familiar when you're done:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/88b24374.png" alt=""></p>
<p>Next, let's orchestrate the call to the first Function. Click 'Add an action' and type 'functions' in the search area. Choose 'Azure Function - Choose an Azure Function'</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/11da14c5.png" alt=""></p>
<p>Next, choose the Azure Functions <em>instance</em> to which you deployed all the functions, and select the first of our validation functions:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/173975cf.png" alt=""></p>
<p>In the request body for this function, you'll pass the same body that came in to the Logic App:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/1f3ab1b9.png" alt=""></p>
<p>Using the same actions as before, we need to create a variable, initialize it to empty, then append the responses from each function on to it and, finally, send that back as the Response from the Logic App. By the time you're done, it should look like this:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/2018-05-30_16-18-20.png" alt=""></p>
<p>&quot;That's great&quot; you might be wondering, &quot;but how does this help the retry/reliability of my orchestration?&quot;</p>
<p>For a glimpse in to this, click the '...' in the upper right of any of the Functions actions and choose 'Settings'</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/2018-05-30_16-20-28.png" alt=""></p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/7379db7b.png" alt=""></p>
<p>Notice the 'Timeout' and 'Retry Policy' options. Also make note of the 'Asynchronous pattern' handling built-in. With these 3 options, you can achieve extreme resilience in your orchestration. I encourage you to try them out as you experiment more with serverless workflow orchestration.</p>
<blockquote>
<p>Logic Apps enforces a limit of 120s on any single HTTP-based action. So your orchestration steps <strong>must</strong> come back w/in that timeframe or LA will kill them.</p>
</blockquote>
<h5>Messaging approach</h5>
<p>There's another way we could string our Azure Functions together, or fan out/in their execution, using <a href="https://docs.microsoft.com/en-us/azure/event-grid/compare-messaging-services">Azure's Messaging offerings: Service Bus, Event Hubs, and Event Grid</a>. For reliable orchestration, I recommend going with Service Bus as it provides queues with de-duplication, partitioning, and dead-lettering capabilities. In general, SB is recommended for &quot;transactional&quot; systems where delivery is critical. Since we wouldn't want any part of our orchestration to fall over, it fits here.</p>
<p>The usual design of this type of setup is to put &quot;messages&quot; for each Azure Function in to a Service Bus queue and set up each &quot;worker&quot; of the orchestration to pick off their own queue for work. This isn't too complex to set up, but the back side of our orchestration - fanning back in from a fan out design - can be. Consider this: How do you ensure that an execution that's part of a fan out comes back in to the same execution?</p>
<p>However, if you're not doing parallel execution, then the path is more simple; you just put things in queue A for worker A, then worker A puts them in queue B for worker B and so on until you're done and you put the result in a queue for the &quot;receiver&quot; which ends the orchestration.</p>
<p>In both cases, you will be making use of the &quot;Asynchronous Pattern&quot; shown off by Logic Apps where you return an HTTP 202 Accepted back to the caller with a 'Location' endpoint they can &quot;ping&quot; to get back the result. You can read more about the async pattern served by HTTP 202 <a href="https://restcookbook.com/Resources/asynchroneous-operations/" target="_blank">here at the REST cookbook</a>.</p>
<p>Azure Function Bindings make the &quot;serial&quot; orchestration really easy: the &quot;starter&quot; function usually binds to <code>HttpTrigger</code> and has a <code>ServiceBus</code> output binding. All subsequent functions have a <code>ServiceBusTrigger</code> and <code>ServiceBus</code> output binding. The final function has a <code>ServiceBusTrigger</code> and another output binding in which to &quot;store&quot; the final result. Optionally, this last function could output to another endpoint (callback, Event Grid, etc) with the final result.</p>
<p>Typically this approach is implemented as follows:</p>
<ul>
<li>&quot;Start&quot; Function receives a request</li>
<li>Decorate the request with a unique ID (eg: GUID)</li>
<li>For the &quot;serial&quot; execution path:
<ul>
<li>Queue the payload of the request (with new Unique ID) in to a Service Bus queue for Function 1</li>
<li>Function 1 does work, queues for Function 2</li>
<li>...</li>
<li>Function N does work, drops result where <code>/result/&lt;id&gt;</code> will find it</li>
</ul>
</li>
<li>For the &quot;parallel&quot; (fan out/in) execution path
<ul>
<li>Enqueue the payload of the request (with new Unique ID) in to Service Bus queues for Functions 1...N</li>
<li>Function X does work on the payload, drops result where <code>/result/&lt;id&gt;</code> will find it</li>
<li><strong>Important</strong>: In this case, a call to <code>/result/&lt;id&gt;</code> only returns once it has information from Functions 1...N available</li>
</ul>
</li>
<li>Send back 202 with Location of <code>/result/&lt;id&gt;</code></li>
</ul>
<blockquote>
<p>The operation of the <code>/result/&lt;id&gt;</code> endpoint is up to you. I like to do something where it returns a 2xx code (but not 200) until the result is there, then returns 200 with the result when it's available. Ultimately the logic for what to do w/ the response from <code>/result/&lt;id&gt;</code> will be implemented by the caller that kicked off the Start function, so pick your poison here.</p>
</blockquote>
<p>For the sake of brevity, I'll walk through coding up a Function that gets a request &amp; drops the message, decorated with ID, in to a Service Bus queue and then another Function which picks up off the queue, does work, and drops the result in to Table Storage. Let's get started!</p>
<p><strong>Step 1</strong> - Create, of course, a Service Bus instance</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/31/f6b2b4da.png" alt=""></p>
<p>Use the Standard tier for now.</p>
<p><strong>Step 2</strong> - Create a queue for <em>each worker function</em> in our workflow</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/31/e0a44169.png" alt=""></p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/31/ca372f40.png" alt=""></p>
<p>It's up to you how you want to set up your queue but I would recommend enforcing duplicate detection and dead lettering upon expiration.</p>
<blockquote>
<p>With dead-lettering on, the usual practice is to have a &quot;watchdog&quot; on the dead-letter box for any SB queue and do something with things that end up in there. You could re-queue them in to the same queue, log something, any number of things.</p>
</blockquote>
<blockquote>
<p>I've found sessions less-than-easy to work with inside Functions so, while they'd be something we would typically use for this approach (set the session id on the message to the unique id the orchestration function generates), I won't be using them in this sample.</p>
</blockquote>
<p>Now we're ready for
<strong>Step 3</strong> - Set the Orchestrator to drop messages in to the queue</p>
<p>To get this started, let's take the <code>Validate</code> Function and get its bindings and return values set up for the procedure I outlined above.</p>
<p>First, add a <code>[ServiceBus]</code> parameter like so:</p>
<pre><code class="language-csharp">public static async Task&lt;IActionResult&gt; Run([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]Person req,
    [ServiceBus(@&quot;function-a&quot;, Connection = @&quot;ServiceBusOrchestrationConnection&quot;)]out QueueMessage functionAmsg,
    TraceWriter log)
</code></pre>
<blockquote>
<p>The ServiceBus connection string <strong>must not</strong> contain any queue/topic information; it needs to be to the top level Service Bus instance or you'll get a runtime error. You can get this connection string by going to the Service Bus instance, clicking the <code>RootManageSharedAccessKey</code>, then copying either of the Connection Strings available. If you want to make your own Shared Access Key, that's fine too but it needs to have Manage permissions so the trigger can wire up as a listener and the output binding can send. Separate keys w/ these permissions are also acceptable.</p>
</blockquote>
<p>What you'll immediately find is the binding for one parameter can only go to one queue. This means you either need to use multiple output parameters (eg: <code>functionAmsg</code>, <code>functionBmsg</code>, <code>functionCmsg</code> ...) or forego using the bindings altogether and just use a ServiceBus client object in your Function; I'll leave that up to you.</p>
<p>The other thing you'll notice is a new type, <code>QueueMessage</code>, that I've injected here. I did this so I had a place to put the unique id I'll assign the messages for retrieval later. This class is simple, and looks like this:</p>
<pre><code class="language-csharp">public class QueueMessage
{
    public string id { get; set; }
    public Person data { get; set; }
}
</code></pre>
<p>Now, when a new request comes in to the trigger (orchestrator), it needs to create a new guid, put it in the <code>id</code> property of a new <code>QueueMessage</code> object, and send that to our ServiceBus instance. Thanks to our bindings, this is just a handful of code:</p>
<pre><code class="language-csharp">var id = Guid.NewGuid().ToString();
log.Info($@&quot;New orchestration started: {id}&quot;);
functionAmsg = new QueueMessage { id = id, data = req };
</code></pre>
<p>and off it goes.</p>
<p>But we also want to give back an HTTP 202 ACCEPTED response with a new function URL the caller can use to get the result</p>
<pre><code class="language-csharp">return new AcceptedResult($@&quot;/api/GetResult?id={id}&quot;, functionAmsg);
</code></pre>
<p>does the trick nicely (we'll implement this later);</p>
<p>Next, let's configure the <code>CheckFirstName</code> Function to get messages from the new ServiceBus queue we've set up. In my configuration I called it <code>function-a</code>.</p>
<p>This changes our <code>HttpTrigger</code> for this function to <code>ServiceBusTrigger</code> and looks like so:</p>
<pre><code class="language-csharp">[FunctionName(&quot;CheckFirstName&quot;)]
public static IActionResult CheckFirstName([ServiceBusTrigger(@&quot;function-a&quot;, Connection = @&quot;ServiceBusOrchestrationConnection&quot;)]QueueMessage msg,
    TraceWriter log)
{
    if ((msg?.data?.Name?.First?.Length &gt; 1) == false)
    {
        // store the error result
    }
    else
    {
        // store an empty error result
    }
}
</code></pre>
<p>For storage, we could choose to spin up a CosmosDB instance and store the JSON as documents there, or we could use the Table Storage that our Azure Functions already require (check out the <code>AzureWebJobsStorage</code> app setting). Functions makes both of these equally easy thanks to bindings, but for simplicity let's just go w/ the Table Storage we already have as part of our Functions.</p>
<p>To configure this as output for our <code>CheckFirstName</code> Function, change its signature to this:</p>
<pre><code class="language-csharp">public static void CheckFirstName([ServiceBusTrigger(@&quot;function-a&quot;, Connection = @&quot;ServiceBusOrchestrationConnection&quot;)]QueueMessage msg,
    [Table(@&quot;checkfirstnameoutput&quot;, Connection = @&quot;AzureWebJobsStorage&quot;)]out ErrorTableEntity err,
    TraceWriter log)
</code></pre>
<p>Notice we had to create a type that inherits from <code>ITableEntity</code> in order to use this. Our new <code>ErrorTableEntity</code> type simply wraps up our previous one:</p>
<pre><code class="language-csharp">public class ErrorTableEntity : TableEntity
{
    public ErrorTableEntity() { }

    public ErrorTableEntity(Error err, string sessionId)
    {
        this.PartitionKey = this.RowKey = sessionId;

        this.Error = err;
    }

    public Error Error { get; set; }
}
</code></pre>
<p>With this we can now fill out the rest of our <code>CheckFirstName</code> Function:</p>
<pre><code class="language-csharp">log.Info($@&quot;Message received: {msg.id}&quot;);
if ((msg?.data?.Name?.First?.Length &gt; 1) == false)
{
    err = new ErrorTableEntity(new Error { id = 1, message = &quot;First name is null or not longer than 1 character&quot; }, msg.id);
    log.Info($@&quot; - Error logged: {err.Error.message}&quot;);
}
else
{
    err = new ErrorTableEntity(new Error { id = 0 }, msg.id);
    log.Info($@&quot; - NoError logged&quot;);
}

return new OkResult();
</code></pre>
<p>So at this point, with a request to our HTTP-triggered function we should see:</p>
<ul>
<li>The message gets decorated with a new GUID</li>
<li>It's put in to the pipeline for our <code>CheckFirstName</code> function</li>
<li><code>CheckFirstName</code> kicks off with that message
<ul>
<li>... processes its validity</li>
<li>... drops the appropriate error in Table Storage for our session</li>
</ul>
</li>
</ul>
<p>The logging messages we put in place will help trace things. If you haven't already, now's a good time to go download the <a href="https://azure.microsoft.com/en-us/features/storage-explorer/" target="_blank">Azure Storage Explorer</a> so you can have a look at the table storage in the emulator (if that's what you're local.settings.json is pointing to) when we test this out next!</p>
<p>Let's give 'er a whirl and see what happens!</p>
<p>Postman sends:</p>
<pre><code>POST /api/Validate HTTP/1.1
Host: localhost:7071
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: b995b4d7-63fb-4b12-b021-4f469089c61c

{
    &quot;Name&quot; : {
        &quot;First&quot; : &quot;J&quot;,
        &quot;Last&quot; : &quot;Doe&quot;,
        &quot;Title&quot; : &quot;Mr&quot;
    },
    &quot;Address&quot; : {
        &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
        &quot;Line2&quot; : null,
        &quot;City&quot; : &quot;Somewhere&quot;,
        &quot;State&quot; : &quot;OR&quot;,
        &quot;Zip&quot; : &quot;12345&quot;,
        &quot;Country&quot; : &quot;United States of America&quot;
    }
}
</code></pre>
<p>And gets back:</p>
<pre><code>Content-Type →application/json; charset=utf-8
Date →Thu, 31 May 2018 04:57:30 GMT
Location →/api/GetResult?id=d6b07382-3fdb-4f06-b9a9-ab0fbdf15594
Server →Kestrel
Transfer-Encoding →chunked

{
    &quot;id&quot;: &quot;d6b07382-3fdb-4f06-b9a9-ab0fbdf15594&quot;,
    &quot;data&quot;: {
        &quot;Name&quot;: {
            &quot;First&quot;: &quot;J&quot;,
            &quot;Last&quot;: &quot;Doe&quot;,
            &quot;Title&quot;: &quot;Mr&quot;
        },
        &quot;Address&quot;: {
            &quot;Line1&quot;: &quot;1234 Anywhere St.&quot;,
            &quot;Line2&quot;: null,
            &quot;City&quot;: &quot;Somewhere&quot;,
            &quot;State&quot;: &quot;OR&quot;,
            &quot;Zip&quot;: &quot;12345&quot;,
            &quot;Country&quot;: &quot;United States of America&quot;
        }
    }
}
</code></pre>
<p>And our Function spits out</p>
<pre><code>[5/31/2018 5:04:50 AM] Executing 'Validate' (Reason='This function was programmatically called via the host APIs.', Id=39ff9db3-03b6-4252-8429-0bd30f4ed6a1)
[5/31/2018 5:04:50 AM] New orchestration started: d6b07382-3fdb-4f06-b9a9-ab0fbdf15594
[5/31/2018 5:04:51 AM] Executed 'Validate' (Succeeded, Id=39ff9db3-03b6-4252-8429-0bd30f4ed6a1)
[5/31/2018 5:04:51 AM] Executing 'CheckFirstName' (Reason='New ServiceBus message detected on 'function-a'.', Id=9665e73b-f945-48df-82a5-8258d45b4787)
[5/31/2018 5:04:51 AM] Message received: d6b07382-3fdb-4f06-b9a9-ab0fbdf15594
[5/31/2018 5:04:54 AM]  - Error logged: First name is null or not longer than 1 character
[5/31/2018 5:04:55 AM] Executed 'CheckFirstName' (Succeeded, Id=9665e73b-f945-48df-82a5-8258d45b4787)
</code></pre>
<p>And if we take a look in our Storage account:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/31/3451575c.png" alt=""></p>
<p>A row for our session, with its output! Now we can write our <code>GetResult</code> function like this:</p>
<pre><code class="language-csharp">[FunctionName(&quot;GetResult&quot;)]
public static async Task&lt;IActionResult&gt; GetResultAsync([HttpTrigger(AuthorizationLevel.Function, &quot;get&quot;, Route = null)]HttpRequest req, [Table(@&quot;checkfirstnameoutput&quot;, Connection = @&quot;AzureWebJobsStorage&quot;)]CloudTable firstnameoutputTable)
{
    string targetId = null;

    if (req.GetQueryParameterDictionary()?.TryGetValue(@&quot;id&quot;, out targetId) == true)
    {
        var queryResult = await firstnameoutputTable.ExecuteAsync(TableOperation.Retrieve&lt;ErrorTableEntity&gt;(targetId, targetId));
        if (queryResult.Result != null)
        {
            return new OkObjectResult(queryResult.Result);
        }

        return new NotFoundResult();
    }
    else
    {
        return new BadRequestObjectResult(@&quot;'id' parameter is required&quot;);
    }
}
</code></pre>
<p>And just like that:</p>
<pre><code>GET /api/GetResult?id=d6b07382-3fdb-4f06-b9a9-ab0fbdf15594 HTTP/1.1
Host: localhost:7071
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: cced7ca9-a039-43d9-ae30-6c7d14c306de
</code></pre>
<p>Gets back</p>
<pre><code>{
    &quot;ErrorId&quot;: 1,
    &quot;ErrorMessage&quot;: &quot;First name is null or not longer than 1 character&quot;,
    &quot;PartitionKey&quot;: &quot;d6b07382-3fdb-4f06-b9a9-ab0fbdf15594&quot;,
    &quot;RowKey&quot;: &quot;d6b07382-3fdb-4f06-b9a9-ab0fbdf15594&quot;,
    &quot;Timestamp&quot;: &quot;2018-05-31T05:04:55.297+00:00&quot;,
    &quot;ETag&quot;: &quot;W/\&quot;datetime'2018-05-31T05%3A04%3A55.297Z'\&quot;&quot;
}
</code></pre>
<p>So we now have:</p>
<ul>
<li>An orchestration function delegating work to one or more workers and returning back to the caller where it can find the results</li>
<li>A &quot;lookup&quot; Function to return results based on the session ID created by the orchestration function</li>
<li>One or more worker functions each placing its ending state in the location where the lookup function can find it</li>
</ul>
<p>If you were to do a Fan out/in process using this same architecture, your lookup function would - instead of checking one spot for output - handle the work of checking to make sure all applicable Functions have placed their stuff where it needs to be, or comes back with 404/204 to let the caller know &quot;not done yet&quot;.</p>
<p>Tune in next time for the final part in the series where I cover a handy library shipped by a group within the Azure Functions team, Durable Functions, and how it helps abstract some of this work away for you!</p>]]></content:encoded>
    </item>
    <item>
      <title>Make Serverless Music - Orchestrate your workflow with Azure [Part 2 - Logic Apps]</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/make-serverless-music-orchestrate-your-workflow-with-azure-part-2-logic-apps</link>
      <pubDate>Wed, 30 May 2018 02:19:25 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=215</guid>
      <description><![CDATA[Ready for a 30 second tutorial? Because Microsoft recognizes the needs of its users often grow and...]]></description>
      <content:encoded><![CDATA[<p>Ready for a 30 second tutorial? Because Microsoft recognizes the needs of its users often grow and evolve outside your initial estimates, they've made it a 2-step (<strong>I've</strong> made it in to 4 steps for verbosity) process:</p>
<ol>
<li>Read &amp; work through Part 1 of this series</li>
<li>When you're done, go to your Flow dashboard and click the Flow you just created</li>
<li>Click <code>... More</code> near the top of the screen</li>
<li>Choose 'Export' | 'Logic Apps template (.json)'</li>
</ol>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/3e8bd93a.png" alt=""></p>
<p>DONE!</p>
<p>Ok not quite, let's walk through importing this in to Azure's IT-Pro Enterprise-grade workflow orchestration offering: <a href="https://azure.microsoft.com/en-us/services/logic-apps/" target="_blank">Logic Apps</a>. As of the time of this writing it's pretty well known in the integration/orchestration space that MSIT itself has migrated over 1000 backend processes at Microsoft from various systems, scripts, etc in to Logic Apps. This product is no joke, y'all. The execution engine for Logic Apps is the <strong>exact same one</strong> you're sending requests to when you submit a Azure resource deployment request (ARM Template, Portal, or otherwise); it's robust, resilient, and reliable.</p>
<h3>Importing a Microsoft Flow in to Logic Apps</h3>
<p>First thing's first, fire up your Azure Portal.</p>
<p>Now, because what you've exported is essentially the JSON definition for a Logic App that will do everything your Flow did, we need to deploy it as such. To do this in the portal, click &quot;Create a resource&quot; and search for, aptly named, &quot;Template deployment&quot;</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/30b423bd.png" alt=""></p>
<p>Go ahead and click Create New and choose 'Build your own template in the editor':</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/c7270944.png" alt=""></p>
<p>Choose, as you might've guessed, 'Load File' and pick your exported Flow JSON file. You'll get the JSON loaded in, not formatted, so you just have to trust it 😉 Click 'Save' and behold some more Azure magic.</p>
<p>The next screen asks you for the Azure resource Basics, but also asks you to fill out any custom parameters your Flow needs! In our case, it only needs to know the name of the Flow and its location - easy peasy:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/2018-05-29_20-39-25.png" alt=""></p>
<p>Once deployment is complete, head to the created Logic App. First thing's first, we have to turn it on by clicking the 'Enable' button.</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/566c8cc6.png" alt=""></p>
<p>Once you've done that, go ahead and click the 'Logic App Designer'. You should be met with a familiar site:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/7853693c.png" alt=""></p>
<p>Let's check out our HTTP endpoint - this URL will be different from the one in Flow - and give it a quick test to make sure it's all kosher:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/9855425a.png" alt=""></p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/bce40a43.png" alt=""></p>
<p>And that's all there is to &quot;<a href="https://flow.microsoft.com/en-us/blog/grow-up-to-logic-apps/" target="_blank">growing up to Logic Apps</a>&quot; from Microsoft Flow. The designer experience is exactly the same if you want to start from scratch and, as I alluded to at the end of the Flow blog post, Logic Apps has a much richer DevOps story as you can <a href="https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-create-deploy-template" target="_blank">deploy them from ARM Templates using Visual Studio Team Services</a> and even <a href="https://marketplace.visualstudio.com/items?itemName=VinaySinghMSFT.AzureLogicAppsToolsforVisualStudio-18551" target="_blank">author them within Visual Studio 2017 using the Logic Apps Extension</a>.</p>
<p>Next up, checking out this same implementation with Azure Functions!</p>]]></content:encoded>
    </item>
    <item>
      <title>Make Serverless Music - Orchestrate your workflow with Azure [Part 1 - Microsoft Flow]</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/make-serverless-music-orchestrate-your-workflow-with-azure-part-1-microsoft-flow</link>
      <pubDate>Tue, 29 May 2018 06:53:28 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=205</guid>
      <description><![CDATA[In this series we take an in-depth look at how you can orchestrate and coordinate processes...]]></description>
      <content:encoded><![CDATA[<blockquote>
<p>In this series we take an in-depth look at how you can orchestrate and coordinate processes throughout your system using a variety of offerings on Microsoft's Azure platform. You'll get an overview, pros, cons, and how-tos for each product.</p>
</blockquote>
<p><a href="https://flow.microsoft.com/" target="_blank">Microsoft Flow</a> stepped on the scene along with a public preview of Microsoft PowerApps back in <a href="https://powerapps.microsoft.com/en-us/blog/introducing-microsoft-flow-and-announcing-the-public-preview-of-powerapps/" target="_blank">April, 2016</a>. Primarily targeted at business users, trust me it can be <strong>so</strong> much more than just a tool to manage to get alerts from Sharepoint or your Inbox 😉</p>
<p>With the same suite of logical operators as Logic Apps (we'll talk more about these later), Flow can if/else, execute in parallel, loop, and retry with the best of them. And best of all, <strong>it has a free tier</strong>. Here's their current pricing model:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/ed68b9af.png" alt=""></p>
<p>The best news? <strong>Everything you're about to see is possible within the Flow Free plan</strong>.</p>
<p>Let's get started with a problem statement:
When I receive a request to my Flow, I want to</p>
<ol>
<li>Validate the schema of the incoming JSON request.</li>
<li>Validate the content of the JSON request against business rules.</li>
<li>Return a response indicating which validations failed and which ones passed.</li>
</ol>
<p>This seems pretty straightforward and something that might be reasonably common in any business environment. Put it on a <code>/validate</code> endpoint, send requests to it, and you've got a decoupled validation service. So let's see a few ways to skin this cat with Microsoft Flow:</p>
<h2>Simple checks done in sequence</h2>
<h4>Step 1: Define our schema</h4>
<p>Let's define our schema as a Person schema like so:</p>
<pre><code class="language-javascript">{
    &quot;Name&quot; : {
        &quot;First&quot; : &quot;John&quot;,
        &quot;Last&quot; : &quot;Doe&quot;,
        &quot;Title&quot; : &quot;Mr&quot;
    },
    &quot;Address&quot; : {
        &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
        &quot;Line2&quot; : null,
        &quot;City&quot; : &quot;Somewhere&quot;,
        &quot;State&quot; : &quot;OR&quot;,
        &quot;Zip&quot; : &quot;12345&quot;,
        &quot;Country&quot; : &quot;United States of America&quot;
    }
}
</code></pre>
<p>For our business rules, we'll enforce:</p>
<ol>
<li>First &amp; Last name must be present &amp; longer than 1 character</li>
<li>If Address Line 2 is not null, Line 1 must also not be null</li>
<li>City must be present</li>
<li>State must be present &amp; only a 2-letter abbreviation</li>
<li>Zip must be present and 5 characters</li>
</ol>
<p>And we'll return back a JSON that looks like:</p>
<pre><code class="language-js">{
    &quot;Errors&quot; : [
        {
            &quot;id&quot; : 1,
            &quot;message&quot; : &quot;First name is empty or less than 1 character&quot;
        },
        { 
            &quot;id&quot; : 3,
            &quot;message&quot; : &quot;Address line 2 is not empty but line 1 is empty&quot;
        },
        ...
    ]
}
</code></pre>
<h4>Step 2: Make the Flow respond to an HTTP POST request containing a JSON body of a specific schema</h4>
<p>This can be done with the <code>HTTP - Request</code> connector:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/bab74e1a.png" alt=""></p>
<p>Upon choosing it, you'll notice something interesting (1):</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/2018-05-29_14-17-21.png" alt=""></p>
<p>Once you save your Flow, this area will be populated with the HTTP endpoint for you to hit. Simply copy it (2) and you're off to the races.
For now, we'll use this step in the Flow to perform requirement #1: Validate the JSON schema.</p>
<p>Using the sample input shown prior, we can generate the JSON schema by clicking <code>Use sample payload to generate schema</code> (3) and pasting in the JSON body from above:
<img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/3d3914e8.png" alt=""></p>
<p>After clicking 'Done', you'll see a generated JSON schema show up in the HTTP - Request connector.</p>
<blockquote>
<p>You can hand-type the JSON schema, but Flow won't validate that it's correct before Saving. You'll only know if you messed something up at runtime.</p>
</blockquote>
<h4>Step 3: Prep the return JSON value</h4>
<p>Since we'll be executing a sequence of steps and putting the result for each validation in to a body to send back, we need to have a sort of &quot;accumulator&quot; variable. Remember we said ours would be an array. Lucky for us, Flow has just the thing.</p>
<p>Click 'New step' then 'Add an action'</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/61aa859.png" alt=""></p>
<p>type 'variable' in the search box and choose 'Initialize variable'</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/579f02a2.png" alt=""></p>
<p>Next, name the variable and set it to be an Array type</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/2018-05-29_14-23-52.png" alt=""></p>
<p>Now we have an Array in to which we can add output from our validators as they run!</p>
<h4>Step 4: Execute our first validation</h4>
<p><em>First &amp; Last name must be present &amp; longer than 1 character</em></p>
<p>Let's tackle the First name, since this will just repeat for Last name.</p>
<p>Click 'New step' 'Add a condition' now:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/977faad4.png" alt=""></p>
<p>Voila, you're met with a condition box, and spots to put both the &quot;if true&quot; and &quot;if false&quot; steps of your choosing. Perfect!
For this check, the condition will simply be <code>len(Name.First) &gt; 1</code> (in rough pseudocode). Let's knock it out:</p>
<p>Click 'Choose a value' in the Condition box and note what happens. The JSON schema has been used to provide you an &quot;intellisense&quot; of sorts with the properties on the payload that are readily available for inspection. However, we need the <strong>length</strong> of one of these, not just the property value. So flip over to the 'Expressions' tab and notice what we have under 'Collections':</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/7eb9f060.png" alt=""></p>
<p><code>length()</code> is exactly what we want. Click it. While the cursor is inside the <code>()</code>, flip back over to 'Dynamic content' and choose 'First'. You should end up with something like this:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/3760f172.png" alt=""></p>
<p>Click 'OK' and fill out the rest of the condition:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/62d603d3.png" alt=""></p>
<p>If this fails, we want to append to our output array, so in the 'If no' area of our condition, click 'Add an action'. Type 'variable' in the search, and choose 'Append to array variable'. Add our first failure code:</p>
<p><code>{ &quot;id&quot; : 1, &quot;message&quot; : &quot;First name is null or less than 2 characters in length&quot; }</code></p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/d65a9c7.png" alt=""></p>
<p>Since the rest will just be &quot;rinse, repeat&quot; let's give our Flow a run. Click 'Save' in the upper right and note that you now have a valid URL in our HTTP - Request trigger action at the top:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/a7373abd.png" alt=""></p>
<p><strong>Heed the warning here</strong>! Since we've given a JSON schema to validate against, <strong>all requests coming in to our Flow <em>must</em> have <code>Content-Type: application/json</code> in their headers</strong>.</p>
<p>Fire up <a href="https://www.getpostman.com" target="_blank">Postman</a> and</p>
<ol>
<li>Copy your URL in to a new request.</li>
<li>Switch the HTTP Method to POST</li>
<li>Add the Content-Type header</li>
<li>Fill out a raw body with the sample from the start of this post</li>
</ol>
<p><strong>Before you click 'Send'</strong> go to your Flow and click the 'Test' button in the upper right. Choose 'I'll perform the trigger action':</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/83f995b0.png" alt=""></p>
<p>Flow is now waiting for a request to come in so it can show you how it executes through the path. Click 'Send' in Postman. You should be met with something like this back in Flow:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/f2229e29.png" alt=""></p>
<p>Awesome. It ran, checked the length, found it was &gt; 1 and no-op'd as we expected. Let's set the First Name to <code>null</code>, set Flow to wait for another request (hit Edit, then Test again), and see what happens:</p>
<pre><code class="language-js">{
    &quot;Name&quot; : {
        &quot;First&quot; : null,
        &quot;Last&quot; : &quot;Doe&quot;,
        &quot;Title&quot; : &quot;Mr&quot;
    },
    &quot;Address&quot; : {
        &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
        &quot;Line2&quot; : null,
        &quot;City&quot; : &quot;Somewhere&quot;,
        &quot;State&quot; : &quot;OR&quot;,
        &quot;Zip&quot; : &quot;12345&quot;,
        &quot;Country&quot; : &quot;United States of America&quot;
    }
}
</code></pre>
<p>Ruh roh</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/c150de5f.png" alt=""></p>
<p>Looks like we need to null check before <code>length()</code>. No problem. Click 'Edit' on your Flow, and click the '(+)' that appears above the Condition block when you hover between it and 'Initialize Variable'. Choose 'Add a condition':</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/2018-05-29_14-43-49.png" alt=""></p>
<p>This time, for our condition expression we need to check out <code>First</code> JSON property against <code>null</code>. We do this with the <code>equals()</code> expression, like so:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/ab7759f4.png" alt=""></p>
<p>And now we can say if this is <strong>true</strong>, add an error message, otherwise move on to the other validation. To get 'true' you also must use the 'Expression' panel, just search for 'true'</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/c818abed.png" alt=""></p>
<p>So let's put our error message add in to the 'If yes' part just like we did the previous one:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/1564e526.png" alt=""></p>
<p>but now we want our previous condition (length check) <strong>inside</strong> the 'false' condition for this check. Easy peasy, simply grab <strong>the icon</strong> for the length condition, and drag it in to the 'If no' space:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/2018-05-29_14-49-02.png" alt=""></p>
<p>You should now have something that looks like this:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/e23c1851.png" alt=""></p>
<p>Let's give it another run with that same null input:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/d7523016.png" alt=""></p>
<p><strong>HUZZAH!</strong></p>
<p>Now to inspect the outcome. If you click on the 'Append to array variable 2' step, you should see:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/a2e4fa5.png" alt=""></p>
<p>So we got a null First name, then we appended on to the array variable a new JSON object definition for the null failure. Sweet.</p>
<p>Now let's do a 1-character first name to watch it go:</p>
<pre><code class="language-js">{
    &quot;Name&quot; : {
        &quot;First&quot; : &quot;J&quot;,
        &quot;Last&quot; : &quot;Doe&quot;,
        &quot;Title&quot; : &quot;Mr&quot;
    },
    &quot;Address&quot; : {
        &quot;Line1&quot; : &quot;1234 Anywhere St.&quot;,
        &quot;Line2&quot; : null,
        &quot;City&quot; : &quot;Somewhere&quot;,
        &quot;State&quot; : &quot;OR&quot;,
        &quot;Zip&quot; : &quot;12345&quot;,
        &quot;Country&quot; : &quot;United States of America&quot;
    }
}
</code></pre>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/b2836ea4.png" alt=""></p>
<p>Perfect! That 2nd error message can now just say &quot;less than 2 characters&quot; but otherwise we're golden!</p>
<p>Now go through and implement the other validations we need.</p>
<blockquote>
<p><strong>TIP</strong>: You can rename any step in your Flow to be more readable, but only before another step takes a dependency on it. Try this to make your conditions more digestable instead of 'Condition X' all over the place 😉</p>
</blockquote>
<p>You should end up with a Flow that looks something like this:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/2018-05-29_15-08-18.png" alt=""></p>
<p>Now for the last part, returning the result to the caller.</p>
<p>Add a new action at the bottom, and search for 'Response'. Click 'See more' and choose 'Request':</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/2018-05-29_15-10-06.png" alt=""></p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/2018-05-29_15-10-55.png" alt=""></p>
<p>Then choose 'Request - Response' and spit out our <code>output</code> variable:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/29/705a8a34.png" alt=""></p>
<p>Let's give 'er a run! Using our same request as before we should now get a response in Postman:</p>
<pre><code class="language-js">[
    {
        &quot;id&quot;: 1,
        &quot;message&quot;: &quot;First name is null or less than 2 characters in length&quot;
    }
]
</code></pre>
<p>PERFECT!</p>
<p>Tweak your request to trigger some/all of the other validations and watch the failures come back.</p>
<p>But, what if we want <em>moar speed</em>?? Let's do it all <strong>in parallel</strong> (aka <em>Fan out/in pattern</em>)!</p>
<p>Click the '+' under the 'Initialize variable' step and choose 'Add a condition'</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/2018-05-29_19-46-45.png" alt=""></p>
<p>Take condition #2 from your list, and drag it above the newly-created parallel condition:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/2018-05-29_19-47-58.png" alt=""></p>
<p>Repeat for the other remaining conditions until you have a Flow that looks like this:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/8f4a986.png" alt=""></p>
<p>Now we just need to get the 'Response' action to show up <strong>after</strong> all the parallel executions have completed.
Click 'New step' at the very bottom of the Flow and choose 'Add an action'. With the &quot;Choose an action&quot; dialog open, drag the existing 'Response' object to just below it:</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/30/2018-05-29_19-53-55.png" alt=""></p>
<p>This will create it <em>outside</em> the parallel executions. You can click 'Cancel' on the &quot;Choose an action&quot; dialog now.</p>
<p>Give our Flow an execution, and you'll see the validations are processed in parallel and can show up in our resulting array object in any order, depending on who completed execution first.</p>
<blockquote>
<p>You can rename your Flow to something more intuitive by simply clicking its given name in the upper-left corner while editing</p>
</blockquote>
<hr>
<p>Hopefully you've found this an interesting foray in to the power of serverless computing and Microsoft's business-class serverless offering, Flow. It's certainly more powerful than it's given credit for (in my mind)!</p>
<p>At this point you're probably wondering &quot;Ok so... what <em>can't</em> I use Flow for?&quot; or &quot;When <em>shouldn't</em> I use this tool, it's awesome!&quot;. Here's the thing, Flow is <strong>intended for business users</strong> to be used in a <strong>self-service</strong> manner. You can't do any of the more advanced business workflow operations like use an Integration Account to read schemas, etc with Flow. Also, as I showed earlier, Flow's <em>fastest</em> checks are at 1-minute intervals. This may not be adequate for higher-priority business operations. You only get the in-browser editor and as a result the ALM story is much more limited (test, prod only). From the administration side, Flow offers only DLP &amp; licensing controls as well as O365 Sec &amp; Compliance logs and DLP.</p>
<p>If you want to take Flow to the next level, stay tuned for next time when I show how to do the same process using Flow's IT Pro-grade offering: Logic Apps. More detail between these two can be found <a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-compare-logic-apps-ms-flow-webjobs#compare-microsoft-flow-and-azure-logic-apps" target="_blank">here</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Creating an XML  JSON Converter in Azure Functions</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/creating-an-xml-json-converter-in-azure-functions</link>
      <pubDate>Fri, 25 May 2018 08:22:28 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=255</guid>
      <description><![CDATA[Your first thought is probably &quot;but why?&quot; and that's fair. So let me explain. I'm a heavy...]]></description>
      <content:encoded><![CDATA[<p>Your first thought is probably &quot;but why?&quot; and that's fair. So let me explain. I'm a heavy user of Microsoft Flow and Azure Logic Apps, and both of those offerings have <strong>really good</strong> build in support for JSON, but not for XML. In fact you can't even really parse XML in to objects you can then reference in either of these. So, enter my desire to want to convert XML to JSON so I can pass it to the <code>Parse JSON</code> step of these and use it later on. Some endpoints I want to query only give me back XML. So here I am. That said, doing this with Azure Functions wasn't as straightforward as I had hoped so here I am sharing with you, dear reader. Let's get started. Create an HTTP Trigger Azure Function project in Visual Studio</p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/25/2018-05-25_10-16-48.png" alt=""></p>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/25/2018-05-25_10-23-02.png" alt=""></p>
<p>I recommend sticking with <code>Function</code> access rights (vs Anonymous) for this one because it'd be an easy Function to abuse should anybody discover the URL. Once you've got that, here's the content to use to create two functions, one to convert JSON to XML and another to convert XML to JSON:</p>
<pre><code>[FunctionName(&quot;ConvertToJson&quot;)]
public static IActionResult RunToJson([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]HttpRequest req, TraceWriter log)
{
    if (req.ContentType.IndexOf(@&quot;/xml&quot;, 0, System.StringComparison.OrdinalIgnoreCase) == -1)
    {
        return new BadRequestObjectResult(@&quot;Content-Type header must be an XML content type&quot;);
    }

    XmlDocument doc = new XmlDocument();
    doc.Load(req.Body);

    return new OkObjectResult(doc);
}

[FunctionName(&quot;ConvertToXml&quot;)]
public static async Task&lt;HttpResponseMessage&gt; RunToXmlAsync([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]HttpRequest req, TraceWriter log)
{
    if (req.ContentType.IndexOf(@&quot;/json&quot;, 0, System.StringComparison.OrdinalIgnoreCase) == -1)
    {
        return new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
        {
            Content = new StringContent(@&quot;Content-Type header must be a JSON content type&quot;)
        };
    }

    var json = await req.ReadAsStringAsync();
    XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

    StringBuilder output = new StringBuilder();
    using (var sw = new StringWriter(output))
        doc.WriteTo(new XmlTextWriter(sw));

    return new HttpResponseMessage(System.Net.HttpStatusCode.OK)
    {
        Content = new StringContent(output.ToString(), Encoding.Default, @&quot;application/xml&quot;),
    };
}
</code></pre>
<h2>Dissecting ConvertToJson</h2>
<p>As a set up for later, let's check out how simple it was to get XML -&gt; JSON: Let's review some of the gymnastics and how I arrived at the XML -&gt; JSON code shown above:</p>
<pre><code>if (req.ContentType.IndexOf(@&quot;/xml&quot;, 0, System.StringComparison.OrdinalIgnoreCase) == -1)
{
    return new BadRequestObjectResult(@&quot;Content-Type header must be an XML content type&quot;);
}

XmlDocument doc = new XmlDocument();
doc.Load(req.Body);

return new OkObjectResult(doc);
</code></pre>
<p>Here was my test request in Postman:</p>
<pre><code>POST /api/ConvertToJson HTTP/1.1
Host: localhost:7071
Content-Type: application/xml
Cache-Control: no-cache
Postman-Token: a5dc4ca4-b6dd-4193-b590-d15982219da7

&lt;root&gt;
	&lt;this att=&quot;x&quot;&gt;
		&lt;underthis&gt;val&lt;/underthis&gt;
	&lt;/this&gt;
	&lt;that&gt;
		&lt;withval&gt;x&lt;/withval&gt;
		&lt;bigval&gt;
			&lt;![CDATA[
			something something
			]]&gt;
		&lt;/bigval&gt;
	&lt;/that&gt;
&lt;/root&gt;
</code></pre>
<p>And here's what you get back:</p>
<pre><code>Content-Type →application/json; charset=utf-8
Date →Fri, 25 May 2018 18:01:16 GMT
Server →Kestrel
Transfer-Encoding →chunked

{
    &quot;root&quot;: {
        &quot;this&quot;: {
            &quot;@att&quot;: &quot;x&quot;,
            &quot;underthis&quot;: &quot;val&quot;
        },
        &quot;that&quot;: {
            &quot;withval&quot;: &quot;x&quot;,
            &quot;bigval&quot;: {
                &quot;#cdata-section&quot;: &quot;\n\t\t\tsomething something\n\t\t\t&quot;
            }
        }
    }
}
</code></pre>
<p>Because Functions automatically takes any <code>object</code> given to <code>OkObjectResult</code> and runs it through JSON deserialization, simply giving it the <code>XmlDocument</code> resulting from <code>LoadXml</code> gives us exactly what we want! But this comes with some baggage...</p>
<h2>Dissecting ConvertToXml</h2>
<p>This one was even more bizarre.</p>
<pre><code>if (req.ContentType.IndexOf(@&quot;/json&quot;, 0, System.StringComparison.OrdinalIgnoreCase) == -1)
{
    return new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
    {
        Content = new StringContent(@&quot;Content-Type header must be a JSON content type&quot;)
    };
}

var json = await req.ReadAsStringAsync();
XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

StringBuilder output = new StringBuilder();
using (var sw = new StringWriter(output))
    doc.WriteTo(new XmlTextWriter(sw));

return new HttpResponseMessage(System.Net.HttpStatusCode.OK)
{
    Content = new StringContent(output.ToString(), Encoding.Default, @&quot;application/xml&quot;),
};
</code></pre>
<p>The general approach to getting JSON in to XML is to take it and just serialize it to an <code>XmlNode</code> using Newtonsoft.Json's constructs. No biggie there, I did that. For starters, here's the Postman request we're going to be sending to <code>ConvertToXml</code>:</p>
<pre><code>POST /api/ConvertToXml HTTP/1.1
Host: localhost:7071
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: 7e55a73f-1d94-46b2-b93f-e7d1297c0c30

{
    &quot;root&quot;: {
        &quot;this&quot;: {
            &quot;@att&quot;: &quot;x&quot;,
            &quot;underthis&quot;: &quot;val&quot;
        },
        &quot;that&quot;: {
            &quot;withval&quot;: &quot;x&quot;,
            &quot;bigval&quot;: {
                &quot;#cdata-section&quot;: &quot;\n\t\t\tsomething something\n\t\t\t&quot;
            }
        }
    }
}
</code></pre>
<p>So now let's investigate why we can't just take the resulting <code>XmlDocument</code> object and write it out to the <code>OkObjectResult</code>. The first thing we have to change to experiment here is the return value of <code>ConvertToXml</code>. You'll notice it's set to <code>HttpResponseMessage</code> which is the type used, typically, in a <strong>v1</strong> Azure Function, not a v2. More on that later, but change it back to <code>IActionResult</code> so the signature now looks like:</p>
<pre><code>public static async Task&lt;IActionResult&gt; RunToXmlAsync([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]HttpRequest req, TraceWriter log)
</code></pre>
<p>Now, change the body to this:</p>
<pre><code>if (req.ContentType.IndexOf(@&quot;/json&quot;, 0, System.StringComparison.OrdinalIgnoreCase) == -1)
{
    return new BadRequestObjectResult(@&quot;Content-Type header must be an JSON content type&quot;);
}

var json = await req.ReadAsStringAsync();
XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

return new OkObjectResult(doc);
</code></pre>
<p>and give 'er a go, only to see JSON come out:</p>
<pre><code>Content-Type →application/json; charset=utf-8
Date →Fri, 25 May 2018 17:44:59 GMT
Server →Kestrel
Transfer-Encoding →chunked

{
    &quot;root&quot;: {
        &quot;this&quot;: {
            &quot;@att&quot;: &quot;x&quot;,
            &quot;underthis&quot;: &quot;val&quot;
        },
        &quot;that&quot;: {
            &quot;withval&quot;: &quot;x&quot;,
            &quot;bigval&quot;: {
                &quot;#cdata-section&quot;: &quot;\n\t\t\tsomething something\n\t\t\t&quot;
            }
        }
    }
}
</code></pre>
<p>At this point, I tried adding <code>[Produces(@&quot;application/xml&quot;)]</code> to the signature of my Function but it had no effect whatsoever. Functions must not respect those ASP.Net Core attributes, unfortunately (yet?). Let's try forcing the output to be XML using the <code>MediaTypeFormatters</code> collection again:</p>
<pre><code>return new OkObjectResult(doc) { ContentTypes = new Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection { @&quot;application/xml&quot; } };
</code></pre>
<p>Nada. This time we get <code>HTTP 406 NOT ACCEPTABLE</code> as the output of our Function. OK. Let's take the XML document, write it to a string, and spit that out.</p>
<pre><code>XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

StringBuilder sb = new StringBuilder();
using (var sw = new StringWriter(sb))
    doc.WriteTo(new XmlTextWriter(sw));

return new OkObjectResult(sb.ToString());
</code></pre>
<p>Gives us:</p>
<pre><code>Content-Type →text/plain; charset=utf-8
Date →Fri, 25 May 2018 17:51:16 GMT
Server →Kestrel
Transfer-Encoding →chunked

&lt;root&gt;&lt;this att=&quot;x&quot;&gt;&lt;underthis&gt;val&lt;/underthis&gt;&lt;/this&gt;&lt;that&gt;&lt;withval&gt;x&lt;/withval&gt;&lt;bigval&gt;&lt;![CDATA[
			something something
			]]&gt;&lt;/bigval&gt;&lt;/that&gt;&lt;/root&gt;
</code></pre>
<p>Close! But I really want that <code>Content-Type</code> header to be accurate, darnit! Let's add our <code>MediaTypeFormatter</code> back in:</p>
<pre><code>return new OkObjectResult(sb.ToString()) { ContentTypes = new Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection { @&quot;application/xml&quot; } };
</code></pre>
<p>Giving us.....</p>
<pre><code>Content-Type →application/xml; charset=utf-8
Date →Fri, 25 May 2018 17:52:58 GMT
Server →Kestrel
Transfer-Encoding →chunked

&lt;string xmlns=&quot;https://schemas.microsoft.com/2003/10/Serialization/&quot;&gt;&amp;lt;root&amp;gt;&amp;lt;this att=&quot;x&quot;&amp;gt;&amp;lt;underthis&amp;gt;val&amp;lt;/underthis&amp;gt;&amp;lt;/this&amp;gt;&amp;lt;that&amp;gt;&amp;lt;withval&amp;gt;x&amp;lt;/withval&amp;gt;&amp;lt;bigval&amp;gt;&amp;lt;![CDATA[
			something something
			]]&amp;gt;&amp;lt;/bigval&amp;gt;&amp;lt;/that&amp;gt;&amp;lt;/root&amp;gt;&lt;/string&gt;
</code></pre>
<p>DAG NABBIT! (not even close to the actual words I was uttering at this point) Clearly ASP.Net Core and/or Functions is doing something automatic under the covers that I'm just not able to control. I <strong>knew</strong> ASP.Net MVC handles this kind of stuff beautifully; maybe .Net Core is just pushing us all to a JSON-only world? ¯_(ツ)_/¯ As a last-ditch effort I converted <em>this</em> Function to use the ASP.Net MVC constructs for response messages. Starting with the signature:</p>
<pre><code>public static async Task&lt;HttpResponseMessage&gt; RunToXmlAsync([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]HttpRequest req, TraceWriter log)
</code></pre>
<p>Then each response I was sending back:</p>
<pre><code>return new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
{
    Content = new StringContent(@&quot;Content-Type header must be a JSON content type&quot;)
};

return new HttpResponseMessage(System.Net.HttpStatusCode.OK)
{
    Content = new StringContent(output.ToString(), Encoding.Default, @&quot;application/xml&quot;),
};
</code></pre>
<p>and wouldn't you know...</p>
<pre><code>Content-Length →149
Content-Type →application/xml; charset=utf-8
Date →Fri, 25 May 2018 17:57:08 GMT
Server →Kestrel

&lt;root&gt;
    &lt;this att=&quot;x&quot;&gt;
        &lt;underthis&gt;val&lt;/underthis&gt;
    &lt;/this&gt;
    &lt;that&gt;
        &lt;withval&gt;x&lt;/withval&gt;
        &lt;bigval&gt;
            &lt;![CDATA[
			something something
			]]&gt;
        &lt;/bigval&gt;
    &lt;/that&gt;
&lt;/root&gt;
</code></pre>
<p>TADA! We've got a body in XML, and we've got the header set to indicate it. Perfect! Having one function using the ASP.Net Core constructs (<code>ConvertToJson</code>) and one using ASP.Net MVC constructs doesn't seem to hurt matters at all, either. Enjoy! And hey, if you're an ASP.Net Core expert and see what I might be doing wrong in trying to get the desired headers &amp; output for my Functions, please let me know in the comments!</p>
<h1>Update</h1>
<p>I posted my experience <a href="https://github.com/Azure/azure-functions-host/issues/2896">as a bug/feedback issue over on the Azure Functions Host repo</a> and got a response from the (awesome) product team. They directed me to, instead, use one of two options:</p>
<ul>
<li><code>Accept</code> header to trigger content negotiation between my Function and the Client (eg: send <code>Accept: application/xml</code> and the Function should return XML as both <code>content-type</code> header and the body payload)</li>
<li>Use <code>ContentResult</code> instead of <code>OkObjectResult</code> and set the appropriate properties.</li>
</ul>
<p>Let's walk through each of these.</p>
<p>For the <code>Accept</code> header, I changed my code for the XML part of the Function to look like this:</p>
<pre><code>if (req.ContentType.IndexOf(@&quot;/json&quot;, 0, System.StringComparison.OrdinalIgnoreCase) == -1)
{
    return new BadRequestObjectResult(@&quot;Content-Type header must be a JSON content type&quot;);
}

var json = await req.ReadAsStringAsync();
XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

return new OkObjectResult(doc);
</code></pre>
<p>Then my Postman requests becomes:</p>
<pre><code>POST /api/ConvertToXml HTTP/1.1
Host: localhost:7071
Content-Type: application/json
Accept: application/xml
Cache-Control: no-cache
Postman-Token: a37ba05f-ae2a-4541-b44f-9d23edf44616

{
    &quot;root&quot;: {
        &quot;this&quot;: {
            &quot;@att&quot;: &quot;x&quot;,
            &quot;underthis&quot;: &quot;val&quot;
        },
        &quot;that&quot;: {
            &quot;withval&quot;: &quot;x&quot;,
            &quot;bigval&quot;: {
                &quot;#cdata-section&quot;: &quot;\n\t\t\tsomething something\n\t\t\t&quot;
            }
        }
    }
}
</code></pre>
<p>But unfortunately I didn't see what I expected:</p>
<pre><code>{
    &quot;root&quot;: {
        &quot;this&quot;: {
            &quot;@att&quot;: &quot;x&quot;,
            &quot;underthis&quot;: &quot;val&quot;
        },
        &quot;that&quot;: {
            &quot;withval&quot;: &quot;x&quot;,
            &quot;bigval&quot;: {
                &quot;#cdata-section&quot;: &quot;\n\t\t\tsomething something\n\t\t\t&quot;
            }
        }
    }
}
</code></pre>
<p>If I change the function to, instead of returning the <code>XmlDocument</code> object to returning the string we built up previously:</p>
<pre><code>XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

StringBuilder output = new StringBuilder();
using (var sw = new StringWriter(output))
    doc.WriteTo(new XmlTextWriter(sw));

return new OkObjectResult(output.ToString());
</code></pre>
<p>I get back:</p>
<pre><code>&lt;string xmlns=&quot;https://schemas.microsoft.com/2003/10/Serialization/&quot;&gt;&amp;lt;root&amp;gt;&amp;lt;this att=&quot;x&quot;&amp;gt;&amp;lt;underthis&amp;gt;val&amp;lt;/underthis&amp;gt;&amp;lt;/this&amp;gt;&amp;lt;that&amp;gt;&amp;lt;withval&amp;gt;x&amp;lt;/withval&amp;gt;&amp;lt;bigval&amp;gt;&amp;lt;![CDATA[
			something something
			]]&amp;gt;&amp;lt;/bigval&amp;gt;&amp;lt;/that&amp;gt;&amp;lt;/root&amp;gt;&lt;/string&gt;
</code></pre>
<p>which looks familiar, but is still incorrect.</p>
<p>Let's check out this <code>ContentResult</code> response. Our code now becomes:</p>
<pre><code>XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

StringBuilder output = new StringBuilder();
using (var sw = new StringWriter(output))
    doc.WriteTo(new XmlTextWriter(sw));

return new ContentResult
{
    Content = output.ToString(),
    ContentType = @&quot;application/xml&quot;,
    StatusCode = StatusCodes.Status200OK
};
</code></pre>
<p>and we get back:</p>
<pre><code>&lt;root&gt;
    &lt;this att=&quot;x&quot;&gt;
        &lt;underthis&gt;val&lt;/underthis&gt;
    &lt;/this&gt;
    &lt;that&gt;
        &lt;withval&gt;x&lt;/withval&gt;
        &lt;bigval&gt;
            &lt;![CDATA[
			something something
			]]&gt;
        &lt;/bigval&gt;
    &lt;/that&gt;
&lt;/root&gt;
</code></pre>
<p>Yay! We're now fully within the .Net Core arena and returning back XML. It's also worth noting that with the <code>ContentResult</code> approach the <code>Accept</code> header on the request is inconsequential.</p>]]></content:encoded>
    </item>
    <item>
      <title>Azure and Alexa, creating conversation with ease</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/azure-and-alexa-creating-conversation-with-ease</link>
      <pubDate>Fri, 27 Apr 2018 02:56:20 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=245</guid>
      <description><![CDATA[It might surprise you to know that I own an Alexa device, being the Microsoft die-hard that I...]]></description>
      <content:encoded><![CDATA[<p>It might surprise you to know that I own an Alexa device, being the Microsoft die-hard that I am.</p>
<p>As you know, <a href="https://netitude.bc3tech.net/2016/11/03/on-schedule-and-on-demand-azure-vms-using-runbooks-microsoft-flow/" target="_blank">I wrote a blog post a while back about creating a Microsoft Flow integration that starts up a Minecraft server in Azure</a> for my kids. After a few months of using this setup, I became annoyed by how many times the kids had to send me a message, call me, etc just to ask me to start the server for them. After being involved in our Bot Framework space for a while and now focusing on our Serverless platform the thought occurred to me - why not just make this a bot they can ask to start the server??</p>
<p>By making my MS Flow accessible via an HTTP request, this becomes quite easy. Simply architect your conversation, ship it to a place it can be hit from Bot Framework (Azure App Service, etc), and you're done!</p>
<p>But what if we wanted to take it a step further, what if we wanted to quickly &amp; easily ship an Alexa Skill that turns on a server in Azure? Turns out with Azure Functions and <a href="https://www.nuget.org/packages/alexa.net">a great Alexa .Net package</a> from my colleague <a href="https://github.com/timheuer">Tim Heuer</a> this is incredibly quick and easy!</p>
<h2>Create your Azure Function</h2>
<p>Fire up Visual Studio 2017, and create a new Azure Function
<img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/04/27/2018-04-27_11-05-28.png" alt=""></p>
<p>For Alexa integration, your Azure Function needs to be an HTTP Endpoint (a v2 Function works great since it's based on .Net Standard):
<img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/04/27/2018-04-27_11-11-16.png" alt=""></p>
<p>After your project is set up, you need to add only one additional nuget package to it:</p>
<blockquote>
<p>Install-Package Alexa.NET</p>
</blockquote>
<h2>Implement Alexa's handshake protocol</h2>
<p>Now we're ready to integrate with Alexa. If you've ever of or done Alexa Skill development, you know there's a pretty rigorous authentication path that an Alexa Skill takes to validate that your endpoint is good to communicate with the Alexa Skill backend and <em>is</em> the endpoint that's supposed to be handling the requests. Fortunately, Alexa.NET makes this easy as pie to handle!</p>
<p>Modify the signature of your function method to accept Function-authorized POST requests (it's easy to embed the query string parameter in to your Alexa Skill's configuration):</p>
<pre><code class="language-csharp">public static async Task&lt;IActionResult&gt; RunAsync([HttpTrigger(AuthorizationLevel.Function, &quot;post&quot;, Route = null)]HttpRequest req, TraceWriter log)
</code></pre>
<p>Next, clear out the content of your Function's handler, and replace it with this:</p>
<pre><code class="language-csharp">if (!(await IsValid(req)))
{
    return new BadRequestResult();
}

return new OkResult();
</code></pre>
<p>and add an IsValid method in to your Function class that looks like this:</p>
<pre><code class="language-csharp">private static async Task&lt;bool&gt; IsValid(HttpRequest request, TraceWriter log)
{
    // Verify SignatureCertChainUrl is present
    request.Headers.TryGetValue(&quot;SignatureCertChainUrl&quot;, out var signatureChainUrl);
    if (String.IsNullOrWhiteSpace(signatureChainUrl))
    {
        log.Error(@&quot;Alexa - empty Signature Cert Chain Url header&quot;);
        return false;
    }

    Uri certUrl;
    try
    {
        certUrl = new Uri(signatureChainUrl);
    }
    catch
    {
        log.Error($@&quot;Alexa - Unable to put sig chain url in to Uri: {signatureChainUrl}&quot;);
        return false;
    }

    // Verify SignatureCertChainUrl is Signature
    request.Headers.TryGetValue(&quot;Signature&quot;, out var signature);
    if (String.IsNullOrWhiteSpace(signature))
    {
        log.Error(@&quot;Alexa - empty Signature header&quot;);
        return false;
    }

    // rewind body so we get the full payload
    request.Body.Position = 0;
    var body = await request.ReadAsStringAsync();

    // rewind so caller gets body back at the beginning
    request.Body.Position = 0;

    if (String.IsNullOrWhiteSpace(body))
    {
        log.Error(@&quot;Alexa - empty Body&quot;);
        return false;
    }

    var valid = await RequestVerification.Verify(signature, certUrl, body);

    if (!valid)
    {
        log.Error(@&quot;Alexa - RequestVerification.Verify failed&quot;);
    }
    return valid;
}
</code></pre>
<p>With this done, your Skill will now properly respond to requests from Alexa and validate them when appropriate (eg: whether in testing, beta, or production).</p>
<h2>Write the conversation</h2>
<p>Now let's get to the meat of implementing your conversation.</p>
<p>There was one interesting thing I learned while I was developing my first Alexa Skill which I didn't anticipate: <strong>a skill can <em>never</em> take more than 8 seconds to end its turn, period. While you can add &quot;progress&quot; responses to what Alexa sends back, these don't extend the amount of time you get to &quot;complete&quot; the ask from the user.</strong></p>
<p>For me this meant I needed to rethink how I was executing my task. Initially, I wanted Alexa to tell my kids when the server was finally up and running, or when the shutdown was complete. The Azure Automation task in a Logic App has the &quot;Wait for Finish&quot; option but of course this task almost never completes in under 8 seconds.
This meant I had to change how I executed my Start/Stop asks to instead use the Azure Management REST API; a much quicker approach. But I digress.</p>
<p>Let's see how we write conversation in an Alexa Skill using Alexa.NET.</p>
<p>The first thing to do is parse the payload that came in to your skill once you've determined it's all good. To do this, simply take the JSON that was posted and turn it in to an <code>SkillRequest</code> object from Alexa.NET like so:</p>
<pre><code class="language-csharp">var requestPayload = await req.ReadAsStringAsync();
var alexaRequest = JsonConvert.DeserializeObject&lt;SkillRequest&gt;(requestPayload);
</code></pre>
<p>Much like a Cortana Skill, Alexa kicks off your skill with an &quot;Intent&quot; to which your code reacts. Alexa.NET nicely maps these to strong types so you get to do the following:</p>
<pre><code class="language-csharp">SkillResponse response = null;
try
{
    if (alexaRequest.Request is LaunchRequest launch)
    {
        response = ResponseBuilder.Ask($@&quot;Welcome to the Minecraft bot. Whatchya wanna do.&quot;,
            new Reprompt { OutputSpeech = new PlainTextOutputSpeech { Text = @&quot;Sorry, I don't understand. You can say start the server, stop the server, or is it on&quot; } });
    }
    else if (alexaRequest.Request is IntentRequest intent)
</code></pre>
<p>Here you see me handling if my kids say &quot;Alexa, Start Minecraft Bot&quot;. This will come through from the backend as a <code>LaunchRequest</code> intent which I can handle.</p>
<p>This also introduces us to the one-turn nature of Alexa. Every request to your skill must be met with, in Alexa.NET, a <strong>single</strong> <code>SkillResponse</code> result which must be returned at the end of the handler. For me the code became easiest if I set a single <code>response</code> variable, and at the bottom of my Function's code simply <code>return response;</code> (you'll see this in a bit with the finished product).</p>
<p>Also much like Cortana, Alexa maps what your users say, outside &quot;launch&quot;, &quot;open&quot;, &quot;start&quot; and the like, to intents <strong>you</strong> define in the Developer Portal (more on this later). For me, the flows I anticipated handling were to start the server, stop it, or check to see if it's on. So this code goes on to look like so:</p>
<pre><code class="language-csharp">if (intent.Intent.Name.Equals(@&quot;is_it_on&quot;))
{
...
}
else if (intent.Intent.Name.Equals(@&quot;start_server&quot;))
{
...
}
else if (intent.Intent.Name.Equals(@&quot;stop_server&quot;))
{
...
}
else
{
...
}
</code></pre>
<p>In each handler for the intent, then, we simply implement the work to do and the response to send back. Here's what it looks like for <code>is_it_on</code>:</p>
<pre><code class="language-csharp">var prog = new ProgressiveResponse(alexaRequest);
if (prog.CanSend())
{
    await prog.SendSpeech(@&quot;One second, checking.&quot;);
}

if (IsVmStarted(_config))
{
    response = ResponseBuilder.Tell(@&quot;Yup, it's up and running!&quot;);
}
else
{
    response = ResponseBuilder.Ask(@&quot;Nope it's off. Would you like to start it?&quot;,
        new Reprompt { OutputSpeech = new PlainTextOutputSpeech { Text = @&quot;Sorry, I don't understand. Just say yes or no&quot; } });
}
</code></pre>
<p>Here we are also introduced to the concept of a &quot;Progressive Response&quot;. Now, remember, even though you've sent a response back as your Skill is running, you <strong>still only get 8 seconds</strong> to set &amp; return the <code>response</code> object we're populating. You can see the Progressive Response is sent to the user right away by the fact you have to <code>await</code> the <code>SendSpeech</code> method.</p>
<p>This also introduces the concept of an 'Ask' from Alexa. For my skill, if the server isn't on I let the kids know and give them the option of starting it right away with this prompt. We'll go in to more of how this gets defined in the Skill portal soon.</p>
<p>There are two other intents for which I also implemented handling: <code>start_server</code> where I tell the kids &quot;ok I've sent the request!&quot; and <code>stop_server</code> where I simply issue the REST request and let them know it's shutting down.</p>
<h3>Handling the answer to a question, aka an &quot;Ask&quot;, from Alexa</h3>
<p>I mentioned previously that when the kids ask for the status of the server, I go ahead and let them know that it's on/off and, if it's off, I ask if they want me to turn it on. If they answer 'yes' here, obviously I want to run that routine &amp; let them know it's turning on. But how do I know that they're response (&quot;yes&quot;, &quot;no&quot;) was in reply to Alexa's ask, and not something else?
Enter the 'prompt' value in each request coming in from Alexa.</p>
<p>In the portal, you can configure prompts for any intent (ie: a prompt that comes back from Alexa after it's handled a particular intent). To do this, you have a fill out a couple of areas in the Alexa Skills Kit console:</p>
<ol>
<li>Define a slot type for expected responses from your user to your prompt.
<img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/23/470a989d.png" alt=""></li>
</ol>
<p>Here you can see I've created a new slot type called <code>PROMPTOPTIONS</code>. I'll use this later. Here's what it looks like:
<img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/23/42205e5a.png" alt=""></p>
<p>Take special note of the <code>value</code> and <code>synonyms</code> areas. The <code>value</code> is what you'll be checking for in code, the <code>synonyms</code> are used to train the underlying Natural Language (NL) model for each of the values so, in theory, my kids should be able to say &quot;yah&quot; and it should get mapped to <code>yes</code> even though I haven't explictly defined that as a synonym.</p>
<p>Once you've defined your slot type, it's time to tell the <code>is_it_on</code> intent to use it now</p>
<ol start="2">
<li>Direct an existing intent to use the new slot type</li>
</ol>
<p><img src="https://brandonhmsdnblog.blob.core.windows.net/images/2018/05/23/a331887f.png" alt=""></p>
<p>In my <code>is_it_on</code> intent I now add an Intent Slot, call it <code>prompt</code> and map it to the new <code>PROMPTOPTIONS</code> slot type. Additionally, I add an utterance for my intent that says the user can say one of the slot values (eg: &quot;yes&quot;, &quot;no&quot;) and it should trigger this intent. This seems a little problematic in my mind; I feel like my kids could say &quot;start minecraft bot&quot; to Alexa, and when she answers back &quot;Whatchya wanna do?&quot; they could just say &quot;yes&quot; and end up triggering the <code>is_it_on</code> intent which wouldn't be desirable; I haven't tried this flow yet, though.</p>
<p>After making these two changes, click 'Save Model' and 'Build Model' to make the new language model active for your skill.</p>
<p>Now let's head back to the code:</p>
<pre><code class="language-csharp">response = ResponseBuilder.Ask(@&quot;Nope it's off. Would you like to start it?&quot;,
    new Reprompt { OutputSpeech = new PlainTextOutputSpeech { Text = @&quot;Sorry, I don't understand. Just say yes or no&quot; } });
</code></pre>
<p>Here we tell Alexa to ask the user a question. The user's next response will come back in <strong>under the same Intent as it was asked during</strong> (eg: <code>is_it_on</code>) but with slots filled in accordingly. So the handling code for my <code>is_it_on</code> intent now looks like this:</p>
<pre><code class="language-csharp">if (intent.Intent.Name.Equals(@&quot;is_it_on&quot;))
{
    string promptResponse = intent.Intent.Slots[@&quot;prompt&quot;]?.Value;
    if (!string.IsNullOrEmpty(promptResponse))
    {
        if (promptResponse.Equals(&quot;yes&quot;, StringComparison.OrdinalIgnoreCase))
        {
            response = StartServer(alexaRequest);
        }
        else
        {
            response = ResponseBuilder.Empty();
        }
    }
    else
    {
        _logger.TrackEvent(@&quot;AlexaIsItOn&quot;);
        var prog = new ProgressiveResponse(alexaRequest);
        if (prog.CanSend())
        {
            await prog.SendSpeech(@&quot;One second, checking.&quot;);
...
</code></pre>
<p>Where you can now see I'm checking that slot we created, <code>prompt</code>, to see if it's been populated with anything and, if it has and it's the <code>yes</code> value, go ahead and turn on the server. Otherwise, just stop responding (<code>ResponseBuilder.Empty()</code>).</p>
<p>Sparing the full detail of the bot (calling in to Azure Management API to do the work, etc), hopefully you can now see how quick &amp; easy it is to write an Alexa Skill using Azure Functions and Alexa.Net! Curious how much this may end up costing you? <a href="https://blogs.msdn.microsoft.com/webdev/2018/05/21/a-penny-saved-is-a-ton-of-serverless-compute-earned/">I think you might be quite surprised</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Publishing to an Event Grid topic from .Net</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/publishing-to-an-event-grid-topic-from-net</link>
      <pubDate>Tue, 06 Feb 2018 08:26:07 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=125</guid>
      <description><![CDATA[If you're using Azure's Event Grid and want to publish a custom event to an Event Grid topic, you...]]></description>
      <content:encoded><![CDATA[<p>If you're using Azure's Event Grid and want to publish a custom event to an Event Grid topic, you need to do so via the REST API.</p>
<p>To make this easier, here's a class that'll make this a one-line operation in your code:</p>
<blockquote>
<h3>Update</h3>
<p>Since posting this a reader has <a href="https://twitter.com/tomasrestrepo/status/960563508101435392" target="_blank">brought to my attention</a> <a href="https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/" target="_blank">issues with using HttpClient as a disposable object</a>. <strong>Thank you!!</strong></p>
<p>The implementation, therefore, might be a bit different than what was originally posted here in Nov 2017. But it's all for the better I promise! 😃</p>
</blockquote>
<pre><code>class EventGridObject
{
    private static readonly HttpClient _httpClient = new HttpClient();

    private readonly Uri _endpoint;
    private readonly string _sasKey;

    public EventGridObject(string topicEndpoint, string sasKey, string subject, string eventType, string id = null, DateTime? eventTime = null) : this(new Uri(topicEndpoint), sasKey, subject, eventType, id, eventTime) { }
    public EventGridObject(Uri topicEndpoint, string sasKey, string subject, string eventType, string id = null, DateTime? eventTime = null)
    {
        _endpoint = topicEndpoint ?? throw new ArgumentNullException(nameof(topicEndpoint));
        _sasKey = !string.IsNullOrWhiteSpace(sasKey) ? sasKey : throw new ArgumentNullException(nameof(sasKey));
        Id = string.IsNullOrWhiteSpace(id) ? Guid.NewGuid().ToString() : id;
        Subject = !string.IsNullOrWhiteSpace(subject) ? subject : throw new ArgumentNullException(nameof(subject));
        EventType = !string.IsNullOrWhiteSpace(eventType) ? eventType : throw new ArgumentNullException(nameof(eventType));
        EventTime = eventTime ?? DateTime.UtcNow;

        // https://byterot.blogspot.co.uk/2016/07/singleton-httpclient-dns.html
        System.Net.ServicePointManager.FindServicePoint(_endpoint).ConnectionLeaseTimeout = (int)TimeSpan.FromMinutes(1).TotalMilliseconds;
    }

    [JsonProperty(@&quot;data&quot;)]
    public object Data { get; set; }
    [JsonProperty(@&quot;id&quot;)]
    public string Id { get; }
    [JsonProperty(@&quot;subject&quot;)]
    public string Subject { get; }
    [JsonProperty(@&quot;eventType&quot;)]
    public string EventType { get; }
    [JsonProperty(@&quot;eventTime&quot;)]
    public DateTime EventTime { get; }

    public async Task&lt;HttpResponseMessage&gt; SendAsync()
    {
        if (_httpClient.DefaultRequestHeaders.Contains(@&quot;aeg-sas-key&quot;))
            _httpClient.DefaultRequestHeaders.Remove(@&quot;aeg-sas-key&quot;);
        _httpClient.DefaultRequestHeaders.Add(@&quot;aeg-sas-key&quot;, _sasKey);

        return await _httpClient.PostAsJsonAsync(_endpoint, new[] { this });
    }
}
</code></pre>
<p>and you use it like this:</p>
<pre><code>await new EventGridObject(@&quot;https://&lt;grid topic&gt;.westus2-1.eventgrid.azure.net/api/events&quot;, @&quot;Yo58SQ...=&quot;, @&quot;my/subject/data/goes/here&quot;, @&quot;myEventType&quot;)
{
    Data = new
    {
        myproperty1 = @&quot;value1&quot;,
        myprop2 = variable2,
        queuedTime = DateTime.UtcNow
    }
}.SendAsync();
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Locally debugging an Azure Function triggered by Azure Event Grid</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/locally-debugging-an-azure-function-triggered-by-azure-event-grid</link>
      <pubDate>Thu, 30 Nov 2017 07:14:22 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=135</guid>
      <description><![CDATA[When working with Azure Event Grid, say for something like Azure Blob Storage Events, it's useful to...]]></description>
      <content:encoded><![CDATA[When working with <a target="_blank" href="https://azure.microsoft.com/en-us/services/event-grid/" rel="noopener">Azure Event Grid</a>, say for something like <a target="_blank" href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-event-overview" rel="noopener">Azure Blob Storage Events</a>, it's useful to be able to debug your handling code locally before going through the process of pushing up to its final resting place (in Azure, of course 😉).

However, when <a target="_blank" href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-event-quickstart" rel="noopener">routing Storage Events to a custom web endpoint</a> you're met with a bit of a conundrum - how can I get the event to hit my <strong>local machine</strong> so I can debug my code locally?

This can be accomplished quite easily using a free, publicly-available tool called <a target="_blank" href="https://ngrok.io" rel="noopener">ngrok</a>. Ngrok effectively creates a tunnel to your local machine on HTTP ports (80, 443) that's accessible via the public internet. Upon running it, you're automatically assigned a subdomain of ngrok.io, and any traffic to that endpoint is routed to your local machine.

How can we use this in conjunction with Event Grid? With our friend <a target="_blank" href="https://azure.microsoft.com/en-us/services/functions/" rel="noopener">Azure Functions</a>! By creating an <a target="_blank" href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook#webhook---c-example" rel="noopener">HTTP-triggered Azure Function</a>, running it locally, and setting breakpoints in our code we can inspect the payload coming from Event Grid and also ensure we're reacting properly to it. Doing so requires a couple of important steps, though.
<ol>
 	<li>Make sure you run ngrok correctly. When launching ngrok, you have the option of specifying the port it forwards to locally. For .Net Azure Functions this is, by default, 7071 so you need to give that to ngrok when you run it. Second, you need to specify the host header as Azure Functions runtime doesn't like seeing the request came in to 'ngrok.io' but is now hitting its endpoint hosted on 'localhost'. To do this, you specify the <code>host-header</code> parameter. All-in-all, your ngrok launch command should look something like this (for Azure Functions .Net development):
<code>ngrok http -host-header=localhost 7071</code></li>
</ol>
Upon running this, you'll get a console window:
<img alt="" src="https://brandonhmsdnblog.blob.core.windows.net/images/2017/11/30/31675369.png" />

Take note of the <strong>https</strong> endpoint given to you by ngrok; Event Grid allows <em>only</em> https endpoints as targets for subscriptions to topics.
<ol start="2">
 	<li>Your Function needs to properly handle the <code>SubscriptionValidationEvent</code> sent out by Event Grid when a subscription endpoint is created. You can read more about this <a target="_blank" href="https://docs.microsoft.com/en-us/azure/event-grid/security-authentication#webhook-event-delivery" rel="noopener">here</a>, but suffice to say here's the code you need to do this:</li>
</ol>
[code language="csharp"]var payloadFromEventGrid = JToken.ReadFrom(new JsonTextReader(new StreamReader(await req.Content.ReadAsStreamAsync())));
dynamic eventGridSoleItem = (payloadFromEventGrid as JArray)?.SingleOrDefault();
if (eventGridSoleItem == null)
{
    return req.CreateErrorResponse(HttpStatusCode.BadRequest, $@&quot;Expecting only one item in the Event Grid message&quot;);
}

if (eventGridSoleItem.eventType == @&quot;Microsoft.EventGrid.SubscriptionValidationEvent&quot;)
{
    log.Verbose(@&quot;Event Grid Validation event received.&quot;);
    return new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent($&quot;{{ \&quot;validationResponse\&quot; : \&quot;{((dynamic)payloadFromEventGrid)[0].data.validationCode}\&quot; }}&quot;)
    };
}
[/code]
That's all there is to setup! The final step is, of course, to put the correct URL in to your Event Grid subscription. For the example above, and an Azure HTTP-triggered function called "TestEventGrid" that URL would look like <code>https://5abd9dff.ngrok.io/api/TestEventGrid</code>

Put this URL in to the Event Grid subscription for an Azure Storage Event account as shown:
<img alt="" src="https://brandonhmsdnblog.blob.core.windows.net/images/2017/11/30/d78ff16d.png" />

As soon as you hit 'Create', you'll see your Function get hit with the <code>SubscriptionValidationEvent</code>, then the subscription should be created successfully. You can then drop a blob in to any container in that storage account and you'll see the events fire &amp; hit your locally-running Azure Function!

A couple of caveats:
<ol>
 	<li>ngrok endpoints change with each run of ngrok. The nice thing is if you leave ngrok running and hibernate/suspend your machine then wake it back up, ngrok will attempt to reconnect and grant you the same address. Very handy. However if the address changes, or you stop/restart ngrok, don't forget to update your Event Grid Subscription's endpoint URL!</li>
 	<li>Don't forget to have your function running locally when you create the subscription! If Event Grid doesn't get a 200 OK back with the right payload, it'll error out creating the subscription for you and you'll have to do it again.</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Using Azure API Management to prevent Denial of Wallet attacks</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/using-azure-api-management-to-prevent-denial-of-wallet-attacks</link>
      <pubDate>Mon, 06 Nov 2017 08:17:12 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=115</guid>
      <description><![CDATA[I know, you're probably thinking, "wait what? Denial of Wallet attacks?" Welcome to the world of...]]></description>
      <content:encoded><![CDATA[I know, you're probably thinking, "wait what? Denial of <strong>Wallet</strong> attacks?" Welcome to the world of <a href="https://en.wikipedia.org/wiki/Serverless_computing">serverless computing</a>.

If you're new to the arena let me explain. With serverless computing, not only is the infrastructure abstracted away from you (aka PaaS), but even the <strong>platform</strong> is something you get to stop focusing on. So instead of worrying about instance sizes, manual or auto scaling, worker environments (SDKs, etc) you simply. write. code.

As with most new technologies, though, this does come with a downside. While it would be high near impossible to DDoS a solution running on a serverless platform (scaling would just continue to handle all the requests it needed to), somebody still has to pay for the execution. Most (good) serverless implementations use what is often called "micro-billing" whereby you are billed only for each <em>actual execution</em> of your code. But if we think of this nefariously and I send a few thousand requests/second to your endpoints guess what happens. Yup, one hefty bill. This has become known as a Denial of Wallet attack.

So, if we don't have management over the platform, or the infrastructure, how can we protect ourselves?

Enter <a href="https://azure.microsoft.com/en-us/services/api-management/">Azure API Management</a>. With APIM, we can quicky &amp; easily "gate" requests to <em>any</em> API endpoint. This means no matter which serverless provider you choose (<a href="https://azure.microsoft.com/en-us/overview/serverless-computing/">Azure Functions</a>, <a href="https://aws.amazon.com/serverless/">AWS Lambda</a>, etc), you can still protect your pocketbook. Let's have a look at how we can configure an APIM instance to do just this for our serverless platform of choice.

<hr />

Assuming we've already created an HTTP-triggered Azure Function or HTTP-triggered Azure Logic App, we'll have a url that looks something like this:
<pre><code>https://prod-14.westcentralus.logic.azure.com:443/workflows/.../triggers/manual/paths/invoke?api-version...
</code></pre>
While we <em>could</em> call this URL directly from our app, web site, or other process that ends up doing a couple of things:
<ol>
 	<li>Tightly couples our app and our backend endpoint; this limits our ability to change to a new endpoint, service, provider, etc later without impacting clients</li>
 	<li>Exposes the URL to the outside world (javascript, etc) which...</li>
 	<li>Makes the URL (more) vulnerable to a Denial of Wallet attack</li>
</ol>
So, let's "wrap" access to our function in an API Management endpoint.

First, go to your Azure Portal, click 'New Resource' and search for "api management". Create a new APIM instance:

<img alt="" src="https://brandonhmsdnblog.blob.core.windows.net/images/2017/11/03/2017-11-03_12-28-29.png" />

It's worth noting, at the time of this writing, there is no free tier for APIM.

Once your APIM instance is deployed and activated, it's time to configure our endpoints. In your APIM instance, go to the 'APIs' area on the lefthand side.

You'll see here that we have a lot of options available to us to add a new API or wrap ones we've already. We can directly import our API definitions from Functions or Logic Apps, from an Azure App Service or other OpenAPI spec, or we can roll one from scratch just to name a few. To show how APIM works, for this exercise we'll just create one from scratch so click 'Blank API' and fill it out as follows:
<pre><code>Display Name: My API
Name: endpoint
Description: Here is where a description for My API lives
Web service URL: https://requestb.in/1kzvq4a1
URL Scheme: Both
API URL suffix: safe-endpoint
Version? Yes
Products: Unlimited
Versioning scheme: Query string
Version Identifier: v1
Verison Parameter: api
</code></pre>
If you watch the <code>Base URL</code> setting, you'll see how it changed as you filled out the information. Even in doing this you can see the features provided for you by APIM. The big one? Versioning! Click <code>Create</code> and let's see what we get.

The <code>Products</code> setting we populate with the products that APIM gives us out of the gate. Namely, 'Starter' and 'Unlimited'. You can see what these mean by going to the Developer Portal but for now let's just move along 😃

On the left side of the APIM portal you now see 'My API' with an expandable arrow next to it. If we expand that arrow, we see that My API has already been given v1, leaving you free to iterate on this same api endpoint with new versions to your heart's content.

But let's get to the meat of this blog post - how do we make sure nobody DDoS' our poor requestb.in endpoint via our APIM URL?
<ol>
 	<li>Click My API's v1 instance</li>
 	<li>Click the 'edit' pencil on the Inbound Processing area; this is where we'll add a policy regarding the rate at which we can call our API.</li>
 	<li>Position your cursor below the <code>&lt;base /&gt;</code> tag under the <code>&lt;inbound&gt;</code> tag</li>
 	<li>Click "Limit call rate per key"</li>
</ol>
At this point, a template rule for limiting call rates is injected, and you have to fill out the parameters:
[code language="xml"]&lt;rate-limit-by-key calls=&quot;number&quot; renewal-period=&quot;seconds&quot; 
    counter-key=&quot;expression like @(context.Subscription.Id) or a constant string&quot;
    increment-count=&quot;optional, by default = 1&quot;
    flexible-retry-window=&quot;optional, by default = false&quot;
/&gt;
[/code]
What this is defining is the # of calls per # of seconds, and how they track the calls. Starting with tracking by Subscription id is a good place and we don't need to increment by any amount other than 1 and flexible retry windows also aren't something we need for this demo, so the end result should look like:
[code language="xml"]&lt;inbound&gt;
    &lt;base /&gt;
    &lt;rate-limit-by-key calls=&quot;30&quot; renewal-period=&quot;60&quot; counter-key=&quot;@(context.Subscription.Id)&quot; /&gt;
&lt;/inbound&gt;
[/code]
Which will limit our callers to 30 calls/minute based on the subscription ID they pass in the header <code>Ocp-Apim-Subscription</code> to our API.

Now, we applied this to <strong>every</strong> call to our API by adding this policy to the 'All operations' area. That's fine. To test it, we need to define the HTTP operations available on the API, so let's add a POST operation now, since requestb.in let's us do that out of the box.
<ol>
 	<li>Click 'Add operation'</li>
 	<li>Choose POST and enter <code>/</code> for the resource path</li>
 	<li>Display Name, let's just call it <code>post</code></li>
</ol>
This is just going to pass through any HTTP POST to our API to the requestb.in endpoint we defined. We should then be able to see it at <a href="https://requestb.in/1kzvq4a1?inspect">https://requestb.in/1kzvq4a1?inspect</a>.

Click 'Save' and flip over to the 'Test' area of our endpoint so we can make sure that calls to it are indeed piped through to requestb.in.

Choose the 'post' operation, and enter something trivial in to the Request Body area, like <code>{ "this" : "that" }</code> then click 'Send'.

You'll get an error at this point saying you can't have an empty <code>Ocp-Apim-Subscription-Key</code> header value. That's because by default APIM instances are protected by this header value, and pass it through as <code>context.Subscription</code> which, if you recall, is what we're keying off when we track the rate at which requests are coming in.

Additionally, this means <strong>nobody can hit the API behind your APIM instance without a subscription key of some sort</strong> - so you're already protected. Before any call even <em>gets</em> to your code, it's been gated by APIM.

How do we get an API key? Well, to do that we have to treat ourselves as a developer. And you've probably already noticed the <code>Developer Portal</code> button at the top of the APIM interface. Go ahead and click it.

This is the public website you get <em>for free</em> just by using APIM. You can point developers here to sign up for your API and get their unique value for the <code>Ocp-Apim-Subscription-Key</code> header.

<img alt="" src="https://brandonhmsdnblog.blob.core.windows.net/images/2017/11/03/2288b1f.png" />

Note the other areas of this site. If you click 'APIS' or 'API Documentation', you get taken to <strong>automatically generated documentation</strong> for each endpoint of your API based on how you created them in the portal.

As an administrator, we have an instance of each of our "Products" namely "Starter" and "Unlimited". If you recall when we placed the rate limit on our API, we had the option to choose a Product. This is what those pertain to. You can create additional ones elsewhere in the portal. To get our keys for each Product, click 'Administrator' in the upper right, and choose 'Profile'.

Now you'll see your portal and have access to your subscription keys. click 'Show' next to the primary key for the Unlimited subscription (because it's not unlimited anymore since we placed an API-wide rate limit) and copy this key to use in the test interface.

Heading back to test, paste your key in for the value of <code>Ocp-Apim-Subscription-Key</code>, fill out the raw body of the request, and click 'Send' again.

This time you should get an <code>HTTP 200 OK</code> and if we head over to the <a href="https://requestb.in/1kzvq4a1?inspect"><code>?inspect</code> URL for our requestb.in instance</a> we'll see that our request came thru!

<img alt="" src="https://brandonhmsdnblog.blob.core.windows.net/images/2017/11/03/2017-11-03_14-46-53.png" />

And just like that we've used APIM to rate-limit acccess to our requestb.in endpoint; an arbitrary API on the web!

You can read more about rate-limiting and the other policies available to you as an APIM user <a href="https://docs.microsoft.com/en-us/azure/api-management/api-management-access-restriction-policies">here</a>. If you're interested in Azure's new offering for DDoS protection for your other Azure resources, you can learn more <a href="https://azure.microsoft.com/en-us/services/ddos-protection/">here</a>.]]></content:encoded>
    </item>
    <item>
      <title>Using Middleware to trap Exceptions in Asp.Net Core</title>
      <link>https://docs.microsoft.com/archive/blogs/brandonh/using-middleware-to-trap-exceptions-in-asp-net-core</link>
      <pubDate>Mon, 31 Jul 2017 07:36:39 GMT</pubDate>
      <dc:creator><![CDATA[Brandon H (MSFT)]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/brandonh/?p=95</guid>
      <description><![CDATA[Recently while working on a project I found myself writing a ton of boilerplate code throughout that...]]></description>
      <content:encoded><![CDATA[Recently while working on a project I found myself writing a ton of boilerplate code throughout that looked something like this:
[code language="csharp"]private readonly Lazy&lt;JSchema&gt; _newItemSchema = new Lazy&lt;JSchema&gt;(() =&gt; Helpers.GetSchema(@&quot;POST-request.json&quot;));
[HttpPost]
public async Task&lt;IActionResult&gt; AddNewItem()
{
    var requestJson = Request.ParseBodyToObject(_newItemSchema.Value);
    if (!requestJson.Success)
    {
#if DEBUG
        return BadRequest(requestJson.Object);
#else
        return BadRequest();
#endif
    }
    
    var newItem = requestJson.Object;
...[/code]
The idea here is to have a JSON Schema defined for the body for any of the POST methods on my web api. Using this, I can run quick validation on the body to make sure it's good and, if it's not, throw a <em>meaningful</em> HTTP 400 BAD REQUEST back to the caller.

The problem I found, however, was that I couldn't simply "return BadRequest()" from within my <code>ParseRequestBodyToObjectAsync</code> helper method. Rather I had to resort to returning a <code>ValueTuple</code> containing <code>Success</code> (whether or not schema validation passed) and <code>Object</code> (either the successfully parsed object, or a JSON response that contained any schema validation error messages).

You can see where this would result in this type of code all over my codebase, for every POST endpoint.

I wanted to clean this up. But how could I get <strong>helper</strong> methods to return an Http response out to the API and stop execution of the caller? Sounds like an exception...
<h2>Asp.Net Core Middleware</h2>
Enter middleware. If you've ever looked at the boilerplate for an Asp.Net Core Web Api project, you've seen this code:
[code language="csharp"]public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection(&quot;Logging&quot;));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler();
    }

    app.UseStaticFiles();
    app.UseMvc();
}[/code]
See all those <code>Use...</code> calls? That's adding built-in middleware to your web app. And like a good platform, Asp.Net Core enables developers to write their own middleware as well.
<h3>Custom Middleware</h3>
To create your own middleware, you simply start with the C# Item Template within Visual Studio. Right click your project and choose Add | New Item...
<img alt="" src="https://brandonhmsdnblog.blob.core.windows.net/images/2017/07/31/6c9f588e.png" />

Next, choose the Middleware Class template:
<img alt="" src="https://brandonhmsdnblog.blob.core.windows.net/images/2017/07/31/2017-07-31_14-46-55.png" />

Behold, your boilerplate middleware
<h3>How Middleware works</h3>
Middleware is added to your app during Startup, as you saw above. <strong>The order in which you call the <code>Use...</code> methods <em>does</em> matter!</strong> Middleware is "waterfalled" down through until either all have been executed, or one stops execution (in the case of our exception handling, we'll be writing ours so it stops execution. More on that later).

The first things passed to your middleware is a request delegate. This is a delegate that takes the current HttpContext object and executes it. Your middleware saves this off upon creation, and uses it in the <code>Invoke()</code> step.
<code>Invoke()</code> is where the work is done. Whatever you want to do to the request/response as part of your middleware is done here. Some other usages for middleware might be to authorize a request based on a header or inject a header in to the request or response. For more examples, check out <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware">the Middleware documentation</a>.
<h2>Writing our middleware</h2>
For my middleware, I settled on two new constructs:
<ol>
 	<li>A new exception type - <code>HttpStatusCodeException</code> - which I would throw whenever I wanted to stop execution of the current request and send back a response with a specific Status Code and Body. It turned out looking like this:</li>
</ol>
[code language="csharp"]public class HttpStatusCodeException : Exception
{
    public int StatusCode { get; set; }
    public string ContentType { get; set; } = @&quot;text/plain&quot;;

    public HttpStatusCodeException(int statusCode)
    {
        this.StatusCode = statusCode;
    }

    public HttpStatusCodeException(int statusCode, string message) : base(message)
    {
        this.StatusCode = statusCode;
    }

    public HttpStatusCodeException(int statusCode, Exception inner) : this(statusCode, inner.ToString()) { }

    public HttpStatusCodeException(int statusCode, JObject errorObject) : this(statusCode, errorObject.ToString())
    {
        this.ContentType = @&quot;application/json&quot;;
    }
}[/code]
<ol start="2">
 	<li>The middleware handler of the new exception. This middleware would need to trap the exception, set the necessary properties on the response, send it back and, most importantly, not let any more middleware fire off. It ended up looking like this:</li>
</ol>
[code language="csharp"]public class HttpStatusCodeExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger&lt;HttpStatusCodeExceptionMiddleware&gt; _logger;

    public HttpStatusCodeExceptionMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
    {
        _next = next ?? throw new ArgumentNullException(nameof(next));
        _logger = loggerFactory?.CreateLogger&lt;HttpStatusCodeExceptionMiddleware&gt;() ?? throw new ArgumentNullException(nameof(loggerFactory));
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (HttpStatusCodeException ex)
        {
            if (context.Response.HasStarted)
            {
                _logger.LogWarning(&quot;The response has already started, the http status code middleware will not be executed.&quot;);
                throw;
            }

            context.Response.Clear();
            context.Response.StatusCode = ex.StatusCode;
            context.Response.ContentType = ex.ContentType;

            await context.Response.WriteAsync(ex.Message);

            return;
        }
    }
}

// Extension method used to add the middleware to the HTTP request pipeline.
public static class HttpStatusCodeExceptionMiddlewareExtensions
{
    public static IApplicationBuilder UseHttpStatusCodeExceptionMiddleware(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware&lt;HttpStatusCodeExceptionMiddleware&gt;();
    }
}[/code]
<h2>Using our middleware</h2>
Last but not least, we need to tell our app to <em>use</em> the middleware we just wrote. To do this, we simply change our <code>ConfigureAppliction</code> method in Startup.cs from this:
[code language="csharp"]if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler();
}[/code]
to this:
[code language="csharp" highlight="4,8,9"]if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseHttpStatusCodeExceptionMiddleware();
}
else
{
    app.UseHttpStatusCodeExceptionMiddleware();
    app.UseExceptionHandler();
}[/code]
Notice the difference in order when in development mode vs not. This is important as the Developer Exception page passes through the exception to our handler so in order to get the best of both worlds, you want the Developer Page handler first. In production, however, since the default Exception Page halts execution, we definitely to <em>not</em> want that one first.
<h2>The result</h2>
My previous boilerplate schema validation code, then, now becomes simply this:
[code language="csharp"]private readonly Lazy&lt;JSchema&gt; _newItemSchema = new Lazy&lt;JSchema&gt;(() =&gt; _schemas.GetSchema(@&quot;POST-request.json&quot;));
[HttpPost]
public async Task&lt;IActionResult&gt; AddNewItem()
{
    var requestObject = Request.ParseBodyToObject(_newItemSchema.Value);
[/code]
because now inside my <code>ParseBodyToObject</code> call I'm simply doing
[code language="csharp"]throw new HttpStatusCodeException(StatusCodes.Status400BadRequest, @&quot;You sent bad stuff&quot;);[/code]
which pops all the way up the stack and stops execution of the request within my app.

<hr />

You can clone this code from <a href="https://github.com/brandonh-msft/HttpStatusCodeExceptionMiddleware">Github</a> or just add <a href="https://www.nuget.org/packages/AspNetCore.Middleware.HttpStatusCodeException">the Nuget package</a> to your project. Thanks!]]></content:encoded>
    </item>
  </channel>
</rss>