<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Mike Stall's .NET Debugging Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/jmstall/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/jmstall/feed.xml</link>
    <description>Notes on Managed Debugging, ICorDebug, and random .NET stuff</description>
    <lastBuildDate>Wed, 24 Feb 2016 14:45:16 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Webjobs SDK Beta is released</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/webjobs-sdk-beta-is-released</link>
      <pubDate>Thu, 19 Jun 2014 09:36:12 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/06/19/webjobs-sdk-beta-is-released/</guid>
      <description><![CDATA[&#160;  We just released the WebJobs SDK Beta! Some highlights:     ServiceBus support!    Better...]]></description>
      <content:encoded><![CDATA[<p>&#160;</p>  <p>We just <a href="http://azure.microsoft.com/blog/2014/06/18/announcing-the-0-3-0-beta-preview-of-microsoft-azure-webjobs-sdk/">released the WebJobs SDK Beta</a>! Some highlights:</p>  <ul>   <li>ServiceBus support!</li>    <li>Better configuration options. You can pass in an ITypeLocator to specify which types are indexed, and an INameResolver to resolve %key% tokens in the attributes to values. </li>    <li>Cleaner model for Triggering (this is a breaking change … I need to go and update my previous blob entries) </li> </ul>  <p>There were <em>some breaking changes</em> , including an attribute rename and&#160; a <a href="http://azure.microsoft.com/blog/2014/03/25/upcoming-name-change-for-windows-azure/">branding rename</a>. </p>  <ul>   <li>nuget package rename: Microsoft.WindowsAzure.Jobs.Host –&gt; Microsoft.Azure.Jobs</li>    <li>nuget package rename: Microsoft.WindowsAzure.Jobs –&gt; Microsoft.Azure.Jobs.Core</li>    <li>attribute change: Instead of [BlobInput]/[BlobOutput] attributes, we now have [BlobTrigger] and [Blob].&#160; </li>    <li>attribute change: Instead of&#160; [QueueInput] / [QueueOutput]&#160; have become just [QueueTrigger] and [Queue].</li> </ul>  <p>The attribute changes makes it very clear exactly what’s triggering a function. Functions can only have 1 trigger. </p>]]></content:encoded>
    </item>
    <item>
      <title>Azure Storage Naming Rules</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/azure-storage-naming-rules</link>
      <pubDate>Thu, 12 Jun 2014 13:59:28 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/06/12/azure-storage-naming-rules/</guid>
      <description><![CDATA[I constantly get burned by naming rules for azure storage. Here’s a collection of the naming rules...]]></description>
      <content:encoded><![CDATA[<p>I constantly get burned by naming rules for azure storage. Here’s a collection of the naming rules from MSDN. The Storage client libraries don’t help you with these rules and just give you a 400 if you get them wrong. Fortunately, <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/24/webjobs-sdk.aspx">WebJobs SDK</a> will provide client-side validation and give you more friendly messages. </p>  <p>Here’s a summary of rules in table form:</p>  <table style="list-style-type: disc; border-collapse: collapse;" cellspacing="0" cellpadding="0" width="446" border="0"><font style="font-size: 12pt;"></font><colgroup><col style="mso-width-source: userset; mso-width-alt: 4278;" width="117" /><font style="font-size: 12pt;"></font><col style="mso-width-source: userset; mso-width-alt: 2486;" width="68" /><font style="font-size: 12pt;"></font><col style="mso-width-source: userset; mso-width-alt: 3949;" width="108" /><font style="font-size: 12pt;"></font><col style="mso-width-source: userset; mso-width-alt: 5595;" width="153" /><font style="font-size: 12pt;"></font></colgroup><tbody>     <tr style="height: 15pt;" height="20"><font style="font-size: 12pt;"></font>        <td style="background: rgb(91, 155, 213); border-width: 0.5pt medium 0.5pt 0.5pt; border-style: solid none solid solid; border-color: rgb(155, 194, 230) currentcolor rgb(155, 194, 230) rgb(155, 194, 230); vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #5b9bd5 none;" height="20" width="117"><font face="Calibri"><font style="font-size: 11pt;" color="#ffffff"><strong>Kind</strong></font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(91, 155, 213); border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #5b9bd5 none;" width="68"><font face="Calibri"><font color="#ffffff"><strong><font style="font-size: 11pt;">Length</font><span style="mso-spacerun: yes;"><font style="font-size: 11pt;">&#160;</font></span></strong></font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(91, 155, 213); border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #5b9bd5 none;" width="108"><font face="Calibri"><font style="font-size: 11pt;" color="#ffffff"><strong>Casing?</strong></font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(91, 155, 213); border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: rgb(155, 194, 230) rgb(155, 194, 230) rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #5b9bd5 none;" width="153"><font face="Calibri"><font style="font-size: 11pt;" color="#ffffff"><strong>Valid chars?</strong></font></font></td>       <font style="font-size: 12pt;"></font></tr>     <font style="font-size: 12pt;"></font>      <tr style="height: 15pt;" height="20"><font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt medium 0.5pt 0.5pt; border-style: solid none solid solid; border-color: rgb(155, 194, 230) currentcolor rgb(155, 194, 230) rgb(155, 194, 230); vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;" height="20"><font face="Calibri"><font style="font-size: 11pt;">Storage Account</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;"><font face="Calibri"><font style="font-size: 11pt;">3-24</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;"><font face="Calibri"><font style="font-size: 11pt;">lowercase</font><span style="mso-spacerun: yes;"><font style="font-size: 11pt;">&#160;</font></span></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: rgb(155, 194, 230) rgb(155, 194, 230) rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;"><font face="Calibri"><font style="font-size: 11pt;">alphanumeric</font></font></td>       <font style="font-size: 12pt;"></font></tr>     <font style="font-size: 12pt;"></font>      <tr style="height: 15pt;" height="20"><font style="font-size: 12pt;"></font>        <td style="border-width: 0.5pt medium 0.5pt 0.5pt; border-style: solid none solid solid; border-color: rgb(155, 194, 230) currentcolor rgb(155, 194, 230) rgb(155, 194, 230); vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none;" height="20"><font face="Calibri"><font style="font-size: 11pt;">Blob Name</font></font></td>       <font style="font-size: 12pt;"></font>        <td class="xl65" style="border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none;"><font face="Calibri"><font style="font-size: 11pt;">1-1024</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none;"><font face="Calibri"><font style="font-size: 11pt;">case-sensitive</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: rgb(155, 194, 230) rgb(155, 194, 230) rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none;"><font face="Calibri"><font style="font-size: 11pt;">any url char</font></font></td>       <font style="font-size: 12pt;"></font></tr>     <font style="font-size: 12pt;"></font>      <tr style="height: 15pt;" height="20"><font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt medium 0.5pt 0.5pt; border-style: solid none solid solid; border-color: rgb(155, 194, 230) currentcolor rgb(155, 194, 230) rgb(155, 194, 230); vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;" height="20"><font face="Calibri"><font style="font-size: 11pt;">Container Name</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;"><font face="Calibri"><font style="font-size: 11pt;">3-63</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;"><font face="Calibri"><font style="font-size: 11pt;">lowercase</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: rgb(155, 194, 230) rgb(155, 194, 230) rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;"><font face="Calibri"><font style="font-size: 11pt;">alphanumeric and dash</font></font></td>       <font style="font-size: 12pt;"></font></tr>     <font style="font-size: 12pt;"></font>      <tr style="height: 15pt;" height="20"><font style="font-size: 12pt;"></font>        <td style="border-width: 0.5pt medium 0.5pt 0.5pt; border-style: solid none solid solid; border-color: rgb(155, 194, 230) currentcolor rgb(155, 194, 230) rgb(155, 194, 230); vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none;" height="20"><font face="Calibri"><font style="font-size: 11pt;">QueueName</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none;"><font face="Calibri"><font style="font-size: 11pt;">3-63</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none;"><font face="Calibri"><font style="font-size: 11pt;">lowercase</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: rgb(155, 194, 230) rgb(155, 194, 230) rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none;"><font face="Calibri"><font style="font-size: 11pt;">alphanumeric and dash</font></font></td>       <font style="font-size: 12pt;"></font></tr>     <font style="font-size: 12pt;"></font>      <tr style="height: 15pt;" height="20"><font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt medium 0.5pt 0.5pt; border-style: solid none solid solid; border-color: rgb(155, 194, 230) currentcolor rgb(155, 194, 230) rgb(155, 194, 230); vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;" height="20"><font face="Calibri"><font style="font-size: 11pt;">TableName</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;"><font face="Calibri"><font style="font-size: 11pt;">3-63</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt medium; border-style: solid none; border-color: rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;"><font face="Calibri"><font style="font-size: 11pt;">case-insensitive</font></font></td>       <font style="font-size: 12pt;"></font>        <td style="background: rgb(221, 235, 247); border-width: 0.5pt 0.5pt 0.5pt medium; border-style: solid solid solid none; border-color: rgb(155, 194, 230) rgb(155, 194, 230) rgb(155, 194, 230) currentcolor; vertical-align: bottom; white-space: nowrap; text-underline-style: none; text-line-through: none; mso-pattern: #ddebf7 none;"><font face="Calibri"><font style="font-size: 11pt;">alphanumeric</font></font></td>       <font style="font-size: 12pt;"></font></tr>     <font style="font-size: 12pt;"></font></tbody></table>  <p>You’ll notice blobs, tables, and queues all have different naming rules. </p>  <p>Here are the relevant excerpts from MSDN with more details. </p>  <h1>Storage account names</h1>  <p>Storage account names are scoped globally (across subscriptions). </p>  <p>Between 3 and 24 characters.&#160; Lowercase letters and numbers .&#160; </p>  <h1>Blobs </h1>  <p>From MSDN <a href="http://msdn.microsoft.com/en-us/library/dd135715.aspx">here</a>.</p>  <h3>Blob Names </h3>  <p>A blob name can contain any combination of characters, but reserved URL characters must be properly escaped. A blob name must be at least one character long and cannot be more than 1,024 characters long. Blob names are case-sensitive.</p>  <p>Avoid blob names that end with a dot (.), a forward slash (/), or a sequence or combination of the two.</p>  <p>By convention / is the virtual directory separator. Don’t use \ in a blob name. The client APIs may allow it, but then fail to hash properly and the signatures mismatch </p>  <h3>Blob Metadata Names</h3>  <p>Metadata for a container or blob resource is stored as name-value pairs associated with the resource. Metadata names must adhere to the naming rules for <a href="http://msdn.microsoft.com/en-us/library/aa664670(VS.71).aspx">C# identifiers</a>.</p>  <p>Note that metadata names preserve the case with which they were created, but are case-insensitive when set or read. If two or more metadata headers with the same name are submitted for a resource, the Blob service returns status code 400 (Bad Request).</p>  <h3><font color="#333333"><font style="style"></font></font><font color="#333333">Container Names </font><font color="#333333"></font></h3>  <p>A container name must be a valid DNS name, conforming to the following naming rules:</p>  <ol>   <li>Container names must start with a letter or number, and can contain only letters, numbers, and the dash (-) character.</li>    <li>Every dash (-) character must be immediately preceded and followed by a letter or number; consecutive dashes are not permitted in container names.</li>    <li>All letters in a container name must be lowercase.</li>    <li>Container names must be from 3 through 63 characters long.</li> </ol>  <h1>Queues</h1>  <p><a href="http://msdn.microsoft.com/en-us/library/dd179349.aspx">From MSDN</a>: </p>  <p>Every queue within an account must have a unique name. The queue name must be a valid DNS name.</p>  <p>Queue names must confirm to the following rules:</p>  <ol>   <li>A queue name must start with a letter or number, and can only contain letters, numbers, and the dash (-) character. </li>    <li>The first and last letters in the queue name must be alphanumeric. The dash (-) character cannot be the first or last character. Consecutive dash characters are not permitted in the queue name.</li>    <li>All letters in a queue name must be lowercase.</li>    <li>A queue name must be from 3 through 63 characters long.</li> </ol>    <h1>Tables</h1>  <h3>Name of the table</h3>  <p><a href="http://msdn.microsoft.com/en-us/library/azure/dd179338.aspx">Table names must conform to these rules</a>:</p>  <ul>   <li>Table names must be unique within an account.</li>    <li>Table names may contain only alphanumeric characters.</li>    <li>Table names cannot begin with a numeric character. </li>    <li>Table names are case-insensitive.</li>    <li>Table names must be from 3 to 63 characters long.</li>    <li>Some table names are reserved, including &quot;tables&quot;. Attempting to create a table with a reserved table name returns error code 404 (Bad Request).</li> </ul>  <p>These rules are also described by the regular expression &quot;^[A-Za-z][A-Za-z0-9]{2,62}$&quot;.</p>  <p>Table names preserve the case with which they were created, but are case-insensitive when used.</p>  <h3>Valid property names</h3>  <p>Property names are case-sensitive strings up to 255 characters in size. Property names should follow naming rules for <a href="http://go.microsoft.com/fwlink/?LinkId=155321">C# identifiers</a>. (The dash is no longer allowed)</p>    <h3>Valid values for PartitionKey and RowKey</h3>  <p>The following characters are not allowed in values for the <strong>PartitionKey</strong> and <strong>RowKey</strong> properties:</p>  <ul>   <li>The forward slash (/) character</li>    <li>The backslash (\) character</li>    <li>The number sign (#) character </li>    <li>The question mark (?) character</li>    <li>Control characters from U+0000 to U+001F, including:     <ul>       <li>The horizontal tab (\t) character</li>        <li>The linefeed (\n) character</li>        <li>The carriage return (\r) character</li>     </ul>   </li>    <li>Control characters from U+007F to U+009F</li> </ul>]]></content:encoded>
    </item>
    <item>
      <title>Redis Cache Service on Azure</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/redis-cache-service-on-azure</link>
      <pubDate>Tue, 13 May 2014 12:51:54 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/05/13/redis-cache-service-on-azure/</guid>
      <description><![CDATA[We just previewed a Redis cache service on Azure.&#160; A good writeup is also on ScottGu’s blog....]]></description>
      <content:encoded><![CDATA[<p>We just previewed a <a href="http://azure.microsoft.com/en-us/services/cache/">Redis cache service on Azure</a>.&#160; A good writeup is also on <a href="http://weblogs.asp.net/scottgu/archive/2014/05/12/azure-vm-security-extensions-expressroute-ga-reserved-ips-internal-load-balancing-multi-site-to-site-vpns-storage-import-export-ga-new-smb-file-service-api-management-hybrid-connection-service-redis-cache-remote-apps-and-more.aspx">ScottGu’s blog</a>. </p>  <p><img alt="" src="http://acom.azurecomcdn.net/80C57D/cdn/images/20140513-1001-115/page/services/cache/redis.png?t=popn" width="136" height="116" /></p>    <p>This is Redis hosted within azure as service. You can create a cache via the portal, and then access it via </p>  <p>Some highlights:</p>  <ol>   <li>Hosting Redis 2.8 on Azure VMs </li>    <li>accessible via <a href="http://redis.io/clients">redis clients from any language</a>. My recommendation for C# is <a href="https://github.com/StackExchange/StackExchange.Redis">Marc Gravell’s Stackexchange.Redis</a>.</li>    <li>Caches expose a SSL endpoint, and support the Auth command.</li>    <li>The standard SKU provides a single-endpoint that’s backed by a 2-node Master/Slave cluster to increase availability. The service includes automatic failover detection and forwarding requests to the master so you get the persistence without needing to worry about it. </li>    <li>There’s a <a href="http://azure.microsoft.com/en-us/documentation/articles/cache-dotnet-how-to-use-azure-redis-cache/#store-session">redis session state provider</a> for using redis from your ASP apps. </li> </ol>  <p>See the <a href="http://azure.microsoft.com/en-us/documentation/articles/cache-dotnet-how-to-use-azure-redis-cache/">Getting Started Guide</a> for how to jump right in. </p>]]></content:encoded>
    </item>
    <item>
      <title>Hosting interactive code in the Cloud</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/hosting-interactive-code-in-the-cloud</link>
      <pubDate>Fri, 25 Apr 2014 21:47:25 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/04/25/hosting-interactive-code-in-the-cloud/</guid>
      <description><![CDATA[Azure WebJobs SDK alpha 2 makes it very easy to host code in the cloud and run it...]]></description>
      <content:encoded><![CDATA[<p>Azure <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/24/webjobs-sdk.aspx">WebJobs SDK</a> alpha 2 makes it very easy to host code in the cloud and run it interactively.&#160; <em>You can now invoke your SDK functions directly from the dashboard</em>. Some great uses here:</p>  <ol>   <li>Provide admin diagnostic commands for your live site. </li>    <li>Easily host code in azure for testing benchmarking code within a datacenter. </li>    <li>Sharing your functions so that others trusted folks can call them, without the hassle of writing an MVC front end.&#160; </li>    <li>This provides a great live-site debugging tool since you can replay erroneous executions without perturbing the rest of the system.&#160; (Couple that with other SDK debugging features like <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/19/who-wrote-that-blob.aspx">Who wrote this blob?</a>)</li> </ol>  <p>For example, suppose you have a function Writer(). In this case, we’ll just do something silly (take a string and write it out multiple times), but you can imagine doing something more interesting like providing diagnostic functions on your live site (eg ,”GetLogs”, “ClearStaleData”, etc). </p>  <pre class="code"><span style="background: white; color: blue;">using </span><span style="background: white; color: black;">Microsoft.WindowsAzure.Jobs; </span><span style="background: white; color: green;">// From nuget: Microsoft.WindowsAzure.Jobs.Host
</span><span style="background: white; color: blue;">using </span><span style="background: white; color: black;">System.IO;

</span><span style="background: white; color: blue;">namespace </span><span style="background: white; color: black;">Live
{
    </span><span style="background: white; color: blue;">class </span><span style="background: white; color: rgb(43, 145, 175);">Program
    </span><span style="background: white; color: black;">{
        </span><span style="background: white; color: blue;">static void </span><span style="background: white; color: black;">Main(</span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">[] args)
        {
            </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">host = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: rgb(43, 145, 175);">JobHost</span><span style="background: white; color: black;">();
</span><span style="background: white; color: green;">
            </span><span style="background: white; color: black;">host.RunAndBlock();
        }

        </span><span style="background: white; color: green;">// Given a string, write it our 'multiple' times. (&quot;A&quot;,3) ==&gt; &quot;AAA&quot;.
        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">Writer(</span><span style="background: white; color: blue;">string </span><span style="background: white; color: black;">content, </span><span style="background: white; color: blue;">int </span><span style="background: white; color: black;">multiply, [</span><span style="background: white; color: rgb(43, 145, 175);">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;test/output.txt&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">TextWriter </span><span style="background: white; color: black;">output)
        {
            </span><span style="background: white; color: blue;">for </span><span style="background: white; color: black;">(</span><span style="background: white; color: blue;">int </span><span style="background: white; color: black;">i = 0; i &lt; multiply; i++)
            {
                output.Write(content);
            }
        }
    }
}
</span></pre>


<p>Once you run the program to azure, if you go to the <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/27/getting-a-dashboard-for-local-development-with-the-webjobs-sdk.aspx">dashboard</a>, you’ll see the function show up in the function list (it’s “published” when the JobHost ctor runs):</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/8547.image_529B7443.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/8547.image_5F00_529B7443.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/8475.image_thumb_1918644C.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/8475.image_5F00_thumb_5F00_1918644C.png" width="730" height="319" /></a></p>



<p>You can click on that function and see a history of executions and their status. :</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/3201.image_7B39E04A.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/3201.image_5F00_7B39E04A.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/2642.image_thumb_76C35F83.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/2642.image_5F00_thumb_5F00_76C35F83.png" width="697" height="368" /></a></p>

<p>You can click on the blue “run function”&#160; to invoke the function directly from the dashboard! This lets you fill in the parameters. Notice that the parameters are parsed from strings. So ‘multiply’ is strongly-typed as an integer, and we parse it by invoking the Int.TryParse function. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/7345.image_58E4DB82.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/7345.image_5F00_58E4DB82.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/1680.image_thumb_7F46BECD.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/1680.image_5F00_thumb_5F00_7F46BECD.png" width="764" height="479" /></a></p>

<p>And of course, the above page has a shareable password-protected permalink, (looks like: <a title="https://simplebatch.scm.azurewebsites.net/azurejobs/function/run?functionId=simplebatch3.Live.Live.Program.Writer" href="https://simplebatch.scm.azurewebsites.net/azurejobs/function/run?functionId=simplebatch3.Live.Live.Program.Writer">https://simplebatch.scm.azurewebsites.net/azurejobs/function/run?functionId=simplebatch3.Live.Live.Program.Writer</a> ) so that you can share out the invocation ability with others. </p>

<p>You can hit run and the function will get invoked! The assumes that your webjob is running, and the invoke works by queuing a message that the JobHost.RunAndBlock() call will listen to.&#160; (This means that your webjob needs to actually be running somewhere, although if it’s not, that dashboard will warn you about that too). Run will also take you to the “permalink” for the function instance execution, which is a shareable URL that provides information about the function execution. You can see that the output parameter was written to a blob “test/output.txt” and it wrote 9 bytes and the hyperlink will take you to the blobs contents. It also notes that the execution reason was “Ran form dashboard”. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/7384.image_4F1F740A.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/7384.image_5F00_4F1F740A.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/4101.image_thumb_63A4C388.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/4101.image_5F00_thumb_5F00_63A4C388.png" width="655" height="498" /></a></p>

<p>You can also hit “replay function”&#160; on an existing instance to replay the function. This will take you back to the invoke page and&#160; a) pre-seed the parameters with values from the execution and b) record a “parent” link to the permalink back to the original instance of the execution so you can see what was replayed. </p>]]></content:encoded>
    </item>
    <item>
      <title>How does [BlobInput] work?</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/how-does-blobinput-work</link>
      <pubDate>Thu, 17 Apr 2014 13:14:58 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/04/17/how-does-blobinput-work/</guid>
      <description><![CDATA[The Azure WebJobs SDK supports running functions when a new blob is added.&#160; IE, you can write...]]></description>
      <content:encoded><![CDATA[<p>The <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-1-blobs.aspx">Azure WebJobs SDK</a> supports running functions when a new blob is added.&#160; IE, you can write code like this:</p>  <pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">CopyWithStream(
            [</span><span style="background: white; color: rgb(43, 145, 175);"><font style="background-color: rgb(255, 255, 0);">BlobInput</font></span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/in/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: black;"></span><span style="background: white; color: rgb(43, 145, 175);">Stream </span><span style="background: white; color: rgb(43, 145, 175);"></span><span style="background: white; color: black;">input,
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/out1/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: black;"></span><span style="background: white; color: rgb(43, 145, 175);">Stream </span><span style="background: white; color: rgb(43, 145, 175);"></span><span style="background: white; color: black;">output
            )
        {
            </span><span style="background: white; color: rgb(43, 145, 175);">Debug</span><span style="background: white; color: black;">.Assert(input.CanRead &amp;&amp; !input.CanWrite);
            </span><span style="background: white; color: rgb(43, 145, 175);">Debug</span><span style="background: white; color: black;">.Assert(!output.CanRead &amp;&amp; output.CanWrite);

            input.CopyTo(output);
        }
</span></pre>

<p>See <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-1-blobs.aspx">modelbinding to blobs</a> for how we bind the blob to types like Stream.&#160; In this entry, I wanted to explain how we handle the blob listening.&#160; The executive summary is:</p>

<ol>
  <li>The existing blobs in your container are processed immediately on startup. </li>

  <li>But once you’re in steady state, [BlobInput] detection (from external sources) <strong>can take up to 10 minutes</strong>. If you need fast responses, use [QueueInput]. </li>

  <li>[BlobInput] can be triggered multiple times on the same blob. But the function will only run if the input is newer than the outputs. </li>
</ol>

<p><strong>More details…</strong></p>

<p>Blob listening is tricky since the Azure Storage APIs don’t provide this directly. WebJobs SDK builds this on top of the existing storage APIs by:</p>

<p>1. Determining the set of containers to listen on by scanning&#160; the [BlobInput] attributes in your program via reflection in the JobHost ctor. This is a&#160; fixed list because while the blob names can have { } expressions, the container names must be constants.&#160; IE, in the above case, the container is named “container”, and then we scan for any blobs in that container that match the name “in/{name}”. </p>

<p align="left">2. When JobHost.RunAndBlock is first called, it will kick off a background scan of the containers. This is naively using <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudblobcontainer.listblobs.aspx">CloudBlobContainer.ListBlobs</a>. </p>

<p>&#160;&#160;&#160; a. For small containers, this is quick and gives a nice instant feel.&#160;&#160; <br />&#160;&#160;&#160; b. For large containers, the scan can take a long time. </p>

<p>3. For steady state, it will scan the azure storage logs. This provides a highly efficient way of getting notifications for blobs across all containers without pulling. Unfortunately, the storage logs are buffered and only updated every 10 minutes, and so that means that the <strong>steady state detection for new blobs can have&#160; a 5-10 minute lag</strong>. For fast response times at scale, our recommendation is to <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-2-queues.aspx">use Queues</a>. </p>

<p>The scanning from #2 and #3 are done in parallel. </p>

<p>4. There is an optimization where any blob written via a [BlobOutput] (as opposed to being written by some external source) will optimistically check for any matching [BlobInputs], without relying on #2 or #3. This lets them chain very quickly. This means that a [QueueInput] can start a chain of blob outputs / inputs, and it can still be very efficient. </p>

<p><strong></strong></p>

<p><strong>See Also </strong></p>

<ul>
  <li><a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/24/webjobs-sdk.aspx">Overview of WebJobs SDK</a></li>

  <li><a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/19/who-wrote-that-blob.aspx">Who wrote that blob?</a></li>

  <li><a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/28/trigger-bindings-and-route-parameters-in-azurejobs.aspx">Triggering rules</a> </li>

  <li>Binding to <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-1-blobs.aspx">Blobs</a>, <a href="http://blogs.msdn.com/b/jmstall/archive/2014/03/06/azure-storage-bindings-part-3-tables.aspx">Tables</a>, and <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-2-queues.aspx">Queues</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Azure Storage Bindings Part 3 – Tables</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/azure-storage-bindings-part-3-tables</link>
      <pubDate>Thu, 06 Mar 2014 17:37:55 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/03/06/azure-storage-bindings-part-3-tables/</guid>
      <description><![CDATA[This blog post was made during the early previews of the SDK. Some of the features/ APIs have...]]></description>
      <content:encoded><![CDATA[<p>This blog post was made during the early previews of the SDK. Some of the features/ APIs have changed. For the<br />latest documentation on WebJobs SDK, please see this link <a href="http://azure.microsoft.com/en-us/documentation/articles/websites-webjobs-resources">http://azure.microsoft.com/en-us/documentation/articles/websites-webjobs-resources</a></p>
<p>The dictionary bindings were removed from the core product and are being moved into an extension. </p>
<p>====</p>
<p>I previously described how the <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/24/webjobs-sdk.aspx">Azure WebJobs SDK</a> can bind to <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-1-blobs.aspx">Blobs</a> and <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-2-queues.aspx">Queues</a>.&nbsp; This entry describes binding to Tables.</p>
<p>You can use a [Table] attribute from the Microsoft.WindowsAzure.Jobs namespace in the <a href="http://www.nuget.org/packages/Microsoft.WindowsAzure.Jobs.Host">Jobs.Host nuget package</a>.&nbsp;&nbsp; Functions are not triggered on table changes. However, once a function is called for some other reason, it can bind to a table as a read/write resource for doing its task.</p>
<p>As background, here&rsquo;s a good tutorial using about azure tables and using the v2.x+ azure <a href="http://www.windowsazure.com/en-us/documentation/articles/storage-dotnet-how-to-use-table-storage-20/">storage sdk for tables</a>.</p>
<p>The WebJobs SDK currently supports binding a table to an <strong>IDictionary</strong>.&nbsp; where:</p>
<ol>
<li>The dictionary key is Tuple&lt;string,string&gt; represents the partition and row key.&nbsp;</li>
<li>the dictionary value is a user poco type whose properties map to the table properties to be read. Note that the type does not need to derive from TableServiceEntity or any other base class.</li>
<li>Your poco type&rsquo;s properties can by strongly typed (not just string) including <em>binding to enum properties </em>or any type with a TryParse() method.</li>
<li>the binding is read/write</li>
</ol>
<p>For example, here&rsquo;s a declaration that binds the &lsquo;dict&rsquo; parameter to an Azure Table. The table is treated as a homogenous table where each row has properties Fruit, Duration, and Value.</p>
<pre class="code"><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">TableDict([</span><span style="background: white; color: #2b91af;">Table</span><span style="background: white; color: black;">(</span><span style="background: white; color: #a31515;">"mytable"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: #2b91af;">IDictionary</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: #2b91af;">Tuple</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">, </span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">&gt;, </span><span style="background: white; color: #2b91af;">OtherStuff</span><span style="background: white; color: black;">&gt; dict) {}</span></pre>
<pre class="code"><span style="background: white; color: blue;">public class </span><span style="background: white; color: #2b91af;">OtherStuff </span><span style="background: white; color: black;">{ </span><span style="background: white; color: blue;">public </span><span style="background: white; color: #2b91af;">Fruit </span><span style="background: white; color: black;">Fruit { </span><span style="background: white; color: blue;">get</span><span style="background: white; color: black;">; </span><span style="background: white; color: blue;">set</span><span style="background: white; color: black;">; } </span><span style="background: white; color: blue;">public </span><span style="background: white; color: #2b91af;">TimeSpan </span><span style="background: white; color: black;">Duration { </span><span style="background: white; color: blue;">get</span><span style="background: white; color: black;">; </span><span style="background: white; color: blue;">set</span><span style="background: white; color: black;">; } </span><span style="background: white; color: blue;">public string </span><span style="background: white; color: black;">Value { </span><span style="background: white; color: blue;">get</span><span style="background: white; color: black;">; </span><span style="background: white; color: blue;">set</span><span style="background: white; color: black;">; } } </span><span style="background: white; color: blue;">public enum </span><span style="background: white; color: #2b91af;">Fruit </span><span style="background: white; color: black;">{ Apple, Banana, Pear, }</span></pre>
<p>You can also retrieve PartitionKey, RowKey, or TimeStamp properties by including them as properties on your poco.</p>
<h3>Writing to a table</h3>
<p>You can use a the dictionary binding to write to a table via the <span style="background-color: #ffff00;">index operator </span>.&nbsp; Here&rsquo;s an example of ingressing a file (read via some Parse&lt;&gt; function) to an azure table.</p>
<pre class="code"><span style="background: white; color: black;"> [</span><span style="background: white; color: #2b91af;">NoAutomaticTrigger</span><span style="background: white; color: black;">] </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">Ingress( [</span><span style="background: white; color: #2b91af;">BlobInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: #a31515;">@"table-uploads\key.csv"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: #2b91af;">Stream </span><span style="background: white; color: black;">inputStream, </span><span style="background: white; color: black;"> [</span><span style="background: white; color: #2b91af;">Table</span><span style="background: white; color: black;">(</span><span style="background: white; color: #a31515;">"convert"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: #2b91af;">IDictionary</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: #2b91af;">Tuple</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">, </span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">&gt;, </span><span style="background: white; color: blue;">object</span><span style="background: white; color: black;">&gt; table </span><span style="background: white; color: black;"> ) { </span><span style="background: white; color: #2b91af;">IEnumerable</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: #2b91af;">Payload</span><span style="background: white; color: black;">&gt; rows = Parse&lt;</span><span style="background: white; color: #2b91af;">Payload</span><span style="background: white; color: black;">&gt;(inputStream); </span><span style="background: white; color: blue;">foreach </span><span style="background: white; color: black;">(</span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">row </span><span style="background: white; color: blue;">in </span><span style="background: white; color: black;">rows) { </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">partRowKey = </span><span style="background: white; color: #2b91af;">Tuple</span><span style="background: white; color: black;">.Create(</span><span style="background: white; color: #a31515;">"const"</span><span style="background: white; color: black;">, row.guidkey.ToString()); <span style="background-color: #ffff00;">table[partRowKey]</span> = row; </span><span style="background: white; color: green;">// azure table write </span><span style="background: white; color: black;">} }</span></pre>
<p>In this case, the IDictionary implementation follows azure table best practices for writing by buffering up the writes by partition key and flushing the batches for you.</p>
<p>Writes default to Upserts.</p>
<h3>Reading a table entry</h3>
<p>You can use the dictionary indexer or TryGetValue to lookup a single entity based on partition row key.</p>
<pre class="code"><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">TableDict([</span><span style="background: white; color: #2b91af;">Table</span><span style="background: white; color: black;">(</span><span style="background: white; color: #a31515;">"mytable"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: #2b91af;">IDictionary</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: #2b91af;">Tuple</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">, </span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">&gt;, </span><span style="background: white; color: #2b91af;">OtherStuff</span><span style="background: white; color: black;">&gt; dict) { </span><span style="background: white; color: green;">// Use IDictionary interface to access an azure table. <span style="background: white; color: blue;">var </span><span style="background: white; color: black;">partRowKey = </span><span style="background: white; color: #2b91af;">Tuple</span><span style="background: white; color: black;">.Create(</span><span style="background: white; color: #a31515;">"PartitionKeyValue"</span><span style="background: white; color: black;">, </span><span style="background: white; color: #a31515;">"RowKeyValue"</span><span style="background: white; color: black;">);</span></span><span style="background: white; color: #2b91af;">OtherStuff </span><span style="background: white; color: black;">val; </span><span style="background: white; color: blue;">bool </span><span style="background: white; color: black;">found = dict.TryGetValue(partRowKey, </span><span style="background: white; color: blue;">out </span><span style="background: white; color: black;">val); </span><span style="background: white; color: #2b91af;">OtherStuff </span><span style="background: white; color: black;">val2 = dict[partRowKey]; </span><span style="background: white; color: green;">// lookup via indexer // another write exmaple </span><span style="background: white; color: black;">dict[partRowKey] = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: #2b91af;">OtherStuff </span><span style="background: white; color: black;">{ Value = </span><span style="background: white; color: #a31515;">"fall"</span><span style="background: white; color: black;">, Fruit = </span><span style="background: white; color: #2b91af;">Fruit</span><span style="background: white; color: black;">.Apple, Duration = </span><span style="background: white; color: #2b91af;">TimeSpan</span><span style="background: white; color: black;">.FromMinutes(5) }; } </span></pre>
<h3>Enumerating table entries</h3>
<p>You can use foreach() on the table to enumerate the entries. The dictionary&lt;&gt; binding will enumerate the entire table and doesn&rsquo;t support enumerating a single partition.</p>
<pre class="code"><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">TableDict([</span><span style="background: white; color: #2b91af;">Table</span><span style="background: white; color: black;">(</span><span style="background: white; color: #a31515;">"mytable"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: #2b91af;">IDictionary</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: #2b91af;">Tuple</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">, </span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">&gt;, </span><span style="background: white; color: #2b91af;">OtherStuff</span><span style="background: white; color: black;">&gt; dict) { </span><span style="background: white; color: blue;"><span style="background-color: #ffff00;">foreach</span> </span><span style="background: white; color: black;">(</span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">kv </span><span style="background: white; color: blue;">in </span><span style="background: white; color: black;">dict) { </span><span style="background: white; color: #2b91af;">OtherStuff </span><span style="background: white; color: black;">val = kv.Value; } } </span></pre>
<p>You can also use linq expressions over azure tables, since that just builds on foreach().</p>
<p>Here&rsquo;s an example of an basic RssAggregator that gets the blog roll from an Azure Table and then writes out a combined RSS feed via [BlobOutput].&nbsp; The whole sample is <a href="https://github.com/MikeStall/RssReaderAzureJobs">available on GitHub</a>, but the interesting code is:</p>
<pre class="code"><span style="background: white; color: green;">// RSS reader. // Aggregates to: http://&lt;mystorage&gt;.blob.core.windows.net/blog/output.rss.xml // Get blog roll from a table. </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">AggregateRss( [</span><span style="background: white; color: #2b91af;">Table</span><span style="background: white; color: black;">(</span><span style="background: white; color: #a31515;">"blogroll"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: #2b91af;">IDictionary</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: #2b91af;">Tuple</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">, </span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">&gt;, </span><span style="background: white; color: #2b91af;">BlogRollEntry</span><span style="background: white; color: black;">&gt; blogroll</span><span style="background: white; color: black;">, [</span><span style="background: white; color: #2b91af;">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: #a31515;">@"blog/output.rss.xml"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: blue;">out </span><span style="background: white; color: #2b91af;">SyndicationFeed </span><span style="background: white; color: black;">output ) { </span><span style="background: white; color: green;">// get blog roll form an azure table </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">urls = <span style="background-color: #ffff00;">(</span></span></pre>
<p><span style="background-color: #ffff00;"><span style="background: white; color: blue;">from </span><span style="background: white; color: black;">kv </span><span style="background: white; color: blue;">in </span></span></p>
<pre class="code"><span style="background: white; color: black;"><span style="background-color: #ffff00;">blogroll</span> </span><span style="background: white; color: blue;">select </span><span style="background: white; color: black;">kv.Value.url).ToArray(); </span><span style="background: white; color: #2b91af;">List</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: #2b91af;">SyndicationItem</span><span style="background: white; color: black;">&gt; items = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: #2b91af;">List</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: #2b91af;">SyndicationItem</span><span style="background: white; color: black;">&gt;(); </span><span style="background: white; color: blue;">foreach </span><span style="background: white; color: black;">(</span><span style="background: white; color: blue;">string </span><span style="background: white; color: black;">url </span><span style="background: white; color: blue;">in </span><span style="background: white; color: black;">urls) { </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">reader = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: #2b91af;">XmlTextReader</span><span style="background: white; color: black;">(url); </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">feed = </span><span style="background: white; color: #2b91af;">SyndicationFeed</span><span style="background: white; color: black;">.Load(reader); items.AddRange(feed.Items.Take(5)); } </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">sorted = items.OrderBy(item =&gt; item.PublishDate); output = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: #2b91af;">SyndicationFeed</span><span style="background: white; color: black;">(</span><span style="background: white; color: #a31515;">"Status"</span><span style="background: white; color: black;">, </span><span style="background: white; color: #a31515;">"Status from SimpleBatch"</span><span style="background: white; color: black;">, </span><span style="background: white; color: blue;">null</span><span style="background: white; color: black;">, sorted); }</span></pre>
<p>BlobRollEntry is just a <a href="http://en.wikipedia.org/wiki/Plain_Old_CLR_Object">poco</a>, with no mandatory base class.</p>
<pre class="code"><span style="background: white; color: green;">// Format for blog roll in the azure table </span><span style="background: white; color: blue;">public class </span><span style="background: white; color: #2b91af;">BlogRollEntry </span><span style="background: white; color: black;">{ </span><span style="background: white; color: blue;">public string </span><span style="background: white; color: black;">url { </span><span style="background: white; color: blue;">get</span><span style="background: white; color: black;">; </span><span style="background: white; color: blue;">set</span><span style="background: white; color: black;">; } }</span></pre>
<p>Here&rsquo;s the contents of the azure table. So you can see how the POCO maps to the table properties of interest.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/8664.image_4044B989.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/8664.image_5F00_4044B989.png"><img style="display: inline; background-image: none;" title="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/6521.image_thumb_5BE9457F.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/6521.image_5F00_thumb_5F00_5BE9457F.png" alt="image" width="405" height="86" border="0" /></a></p>
<h3>&nbsp;</h3>
<h3>Removing from a table</h3>
<p>You can use IDictionary.Remove() to remove from the table.</p>
<pre class="code"><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">TableDict([</span><span style="background: white; color: #2b91af;">Table</span><span style="background: white; color: black;">(TableNameDict)] </span><span style="background: white; color: #2b91af;">IDictionary</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: #2b91af;">Tuple</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">, </span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">&gt;, </span><span style="background: white; color: #2b91af;">OtherStuff</span><span style="background: white; color: black;">&gt; dict) { </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">partRowKey = </span><span style="background: white; color: #2b91af;">Tuple</span><span style="background: white; color: black;">.Create(</span><span style="background: white; color: #a31515;">"PartitionKeyValue"</span><span style="background: white; color: black;">, </span><span style="background: white; color: #a31515;">"RowKeyValue"</span><span style="background: white; color: black;">); </span><span style="background: white; color: green;">// Clear </span><span style="background: white; color: black;">dict.<span style="background-color: #ffff00;">Remove</span>(partRowKey); }</span></pre>
<p>You can use IDictionary.Clear()&nbsp; to clear an entire table.</p>
<h3>Summary</h3>
<p>Here&rsquo;s a summary of which IDictionary operations map to table operations.</p>
<p>Assume <em>dict</em> is a dictionary table mapping, and partRowKey is a tuple as used above.</p>
<p>&nbsp;</p>
<table style="width: 517px;" border="1" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td valign="top" width="199"><strong>Operation</strong></td>
<td valign="top" width="316"><strong>Code snippet</strong></td>
</tr>
<tr>
<td valign="top" width="199">Read single entity</td>
<td valign="top" width="316">value = dict[partRowKey]</td>
</tr>
<tr>
<td valign="top" width="199">&nbsp;</td>
<td valign="top" width="316">dict.TryGetValue(partRowKey, out val)</td>
</tr>
<tr>
<td valign="top" width="199">Contains a key</td>
<td valign="top" width="316">bool found = dict.ContainsKey(partRowKey)</td>
</tr>
<tr>
<td valign="top" width="199">Write single entity</td>
<td valign="top" width="316">dict[partRowKey] = value</td>
</tr>
<tr>
<td valign="top" width="199">&nbsp;</td>
<td valign="top" width="316">Add(partRowKey, value)</td>
</tr>
<tr>
<td valign="top" width="199">enumerate entire table</td>
<td valign="top" width="316">foreach(var kv in dict) { }</td>
</tr>
<tr>
<td valign="top" width="199">Remove a single entity</td>
<td valign="top" width="316">dict.Remove(partRowKey);</td>
</tr>
<tr>
<td valign="top" width="199">Clear all entities</td>
<td valign="top" width="316">dict.Clear()</td>
</tr>
</tbody>
</table>
<h3>&nbsp;</h3>
<h3>Other notes</h3>
<ol>
<li>This binding is obviously limited. You can always bind directly to CloudStorageAccount and use the SDK directly if you need more control.</li>
<li>The dictionary adapter does not implement all properties on IDictionary&lt;&gt;. For example, in the Alpha 1 release, CopyTo, Contains, Keys, Value, and other aren&rsquo;t implemented.</li>
<li>We&rsquo;re looking at more Table bindings in the next update (such as binding directly to <a href="http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.storage.table.cloudtable.aspx">CloudTable</a>).</li>
<li>You see some more examples for <a href="https://aspnet.codeplex.com/SourceControl/latest#Samples/AzureWebJobs/BasicSamples/TableOperations/Program.cs">table usage on samples site</a>.</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Who wrote that blob?</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/who-wrote-that-blob</link>
      <pubDate>Wed, 19 Feb 2014 09:06:02 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/02/19/who-wrote-that-blob/</guid>
      <description><![CDATA[One of my favorite features of the Azure WebJobs SDK is the “Who wrote this blob?” feature. This is...]]></description>
      <content:encoded><![CDATA[<p>One of my favorite features of the <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/24/webjobs-sdk.aspx">Azure WebJobs SDK</a> is the “Who wrote this blob?” feature. This is a common debugging scenario: you see your output is incorrect (in this case, a blob) and you’re trying to find the culprit that wrote the bad output. </p>  <p>On the main <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/27/getting-a-dashboard-for-local-development-with-the-webjobs-sdk.aspx">dashboard</a>, there’s a “Search Blobs” button, which lets you enter the blob name. </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/5582.image_4B076552.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/5582.image_5F00_4B076552.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/3438.image_thumb_5F8CB4D0.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/3438.image_5F00_thumb_5F00_5F8CB4D0.png" width="597" height="182" /></a></p>  <p>Hit “Search” and then it takes you to a permalink for the function instance page that wrote that blob.</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/5428.image_7AC50DD1.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/5428.image_5F00_7AC50DD1.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/6180.image_thumb_6F9B8387.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/6180.image_5F00_thumb_5F00_6F9B8387.png" width="676" height="497" /></a></p>  <p>Of course, once you’re at the function instance page, you can then see things like that function’s input parameters, console output, and trigger reason for why that function was executed. In this case, the input blob was “in/a.txt”, and you can hit the “lookup” button on that to see who wrote the input. So you’re effectively tracing back up the chain. </p>  <p>And once you find the culprit, you can re-publish the function (if it was a coding error) or re-upload the blob (if it was a bad initial input) and re-execute it just the affected blobs. </p>  <p><em>It’s basically omniscient debugging for Azure with edit-and-continue. </em></p>  <p><strong>How does it work? </strong></p>  <p>When the WebJobs SDK invokes a function instance, it gives it a unique guid. That guid is used in the permalink to the function instance page. When a blob is <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-1-blobs.aspx">written via&#160; [BlobOutput]</a>, the blob’s metadata is stamped with that guid.&#160; So the lookup only works for functions written by the WebJobs SDK. </p>  <p><strong>What about queues?</strong></p>  <p>The <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-2-queues.aspx">WebJobs SDK has a similar lookup queues</a>. Queue messages written by [QueueOutput] also get stamped with the function instance guid and so you can lookup which function instance queued a message. </p>]]></content:encoded>
    </item>
    <item>
      <title>Azure Storage Bindings Part 2 – Queues</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/azure-storage-bindings-part-2-queues</link>
      <pubDate>Tue, 18 Feb 2014 11:04:23 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/02/18/azure-storage-bindings-part-2-queues/</guid>
      <description><![CDATA[&#160; I previously described how the Azure Webjobs SDK can bind to Blobs. This entry describes...]]></description>
      <content:encoded><![CDATA[&#160; <p>I previously described how the <a href="http://blogs.msdn.com/b/jmstall/archive/2014/02/18/azure-storage-bindings-part-1-blobs.aspx">Azure Webjobs SDK can bind to Blobs</a>. This entry describes binding to Azure Queues.&#160;&#160; (<a href="http://msdn.microsoft.com/en-us/library/windowsazure/hh767287.aspx">Binding to Service Bus Queues is not yet implemented</a>)</p>  <p>You can see some more examples for <a href="https://aspnet.codeplex.com/SourceControl/latest#Samples/AzureWebJobs/BasicSamples/QueueOperations/Program.cs">queue usage on the sample site</a>. Here are some supported queue bindings in the Alpha:</p>  <h3>Queue Input for BCL types (String, Object, Byte[])</h3>  <p>A function can have a [QueueInput]&#160; attribute, which means that the function will get invoked when a queue message is available. </p>  <p>The queue name is either specified via the QueueInput constructor parameter or by the name of the local variable (similar to MVC).&#160; So the following are equivalent:</p>  <pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">Queue1([</span><span style="background: white; color: rgb(43, 145, 175);">QueueInput</span><span style="background: white; color: black;">] </span><span style="background: white; color: blue;">string </span><span style="background: white; color: black;">queuename)
        {
        }

        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">Queue2([</span><span style="background: white; color: rgb(43, 145, 175);">QueueInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;queuename&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: blue;">string </span><span style="background: white; color: black;">x)
        {
        }</span></pre>


<p>In this case, the functions are triggered when a new message shows up in “queuename”, and the parameter is bound to the message contents (CloudQueueMessage.AsString). </p>

<p>The parameter type can be string or object (both which bind as CloudQueueMessage.AsString) or byte[] (which binds as <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudqueuemessage.asbytes.aspx">cloudQueueMessage.AsBytes</a>)</p>

<p>As an added benefit, the SDK will ensure the queue input message is held until the function returns . It does this by calling <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudqueue.updatemessage.aspx">UpdateMessage</a> on a background thread while the function is still executing and calls <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudqueue.deletemessage.aspx">DeleteMessage</a> when the function returns. </p>

<h3>Queue Input for user types</h3>

<p>The parameter type can also be a your user defined poco type, in which case it is deserialized with JSON.Net.&#160; For example:</p>

<pre class="code"><span style="background: white; color: black;">    </span><span style="background: white; color: blue;">public class </span><span style="background: white; color: rgb(43, 145, 175);">Payload
    </span><span style="background: white; color: black;">{
        </span><span style="background: white; color: blue;">public int </span><span style="background: white; color: black;">Value { </span><span style="background: white; color: blue;">get</span><span style="background: white; color: black;">; </span><span style="background: white; color: blue;">set</span><span style="background: white; color: black;">; }
        </span><span style="background: white; color: blue;">public string </span><span style="background: white; color: black;">Output { </span><span style="background: white; color: blue;">get</span><span style="background: white; color: black;">; </span><span style="background: white; color: blue;">set</span><span style="background: white; color: black;">; }
    }</span></pre>


<pre class="code"><span style="background: white; color: blue;">    public static void </span><span style="background: white; color: black;">Queue2([</span><span style="background: white; color: rgb(43, 145, 175);">QueueInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;queuename&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">Payload </span><span style="background: white; color: black;">x)
    {
    }
</span></pre>


<p>That has the same execution semantics as this:</p>

<pre class="code"><span style="background: white; color: blue;">    public static void </span><span style="background: white; color: black;">Queue2([</span><span style="background: white; color: rgb(43, 145, 175);">QueueInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;queuename&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: blue;">string </span><span style="background: white; color: black;">json)
    {
        </span><span style="background: white; color: rgb(43, 145, 175);">Payload </span><span style="background: white; color: black;">x = </span><span style="background: white; color: rgb(43, 145, 175);">JsonConvert</span><span style="background: white; color: black;">.DeserializeObject&lt;</span><span style="background: white; color: rgb(43, 145, 175);">Payload</span><span style="background: white; color: black;">&gt;(json);
        // …
    }</span></pre>


<p>Serialization errors are treated as runtime exceptions which show up in the dashboard. </p>

<p>Of course, a big difference is that using poco type means the QueueInput <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/28/trigger-bindings-and-route-parameters-in-azurejobs.aspx">provides route parameters</a>, which means you can directly use the queue message properties in other parameter bindigs, like so:</p>

<pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">Queue2(
            [</span><span style="background: white; color: rgb(43, 145, 175);">QueueInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;queuename&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">Payload </span><span style="background: white; color: black;">x,
            </span><span style="background: white; color: blue;">int </span><span style="background: white; color: black;">Value, 
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/{Output}.txt&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">Stream </span><span style="background: white; color: black;">output)
        {
        }</span></pre>


<p>With bindings like these, it’s possible you don’t even need to use x in the function body. </p>



<h3>Queue Output </h3>

<p>A function can enqueue messages via [QueueOutput]. It can enqueue a single message via an out parameter. If the value is not null on return, the message is serialized and queued, similar to the rules used for [QueueInput].</p>

<p>Here’s an example of queuing a mesasage saying “payload” to a queue named testqueue.</p>



<pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">OutputQueue([</span><span style="background: white; color: rgb(43, 145, 175);">QueueOutput</span><span style="background: white; color: black;">] </span><span style="background: white; color: blue;">out string </span><span style="background: white; color: black;">testqueue)
        {
            testqueue = </span><span style="background: white; color: rgb(163, 21, 21);">&quot;payload&quot;</span><span style="background: white; color: black;">;
        }</span></pre>


<p>In this case, the function doesn’t have any triggers (no [QueueInput] or [BlobInput]), but could still be invoked directly from the host:</p>

<pre class="code"><span style="background: white; color: black;">        host.Call(</span><span style="background: white; color: blue;">typeof</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(43, 145, 175);">Program</span><span style="background: white; color: black;">).GetMethod(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;OutputQueue&quot;</span><span style="background: white; color: black;">));</span></pre>


<p>It can enqueue multiple messages via an IEnumerable&lt;T&gt;.&#160; This function queues 3 messages:</p>

<pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">OutputMultiple([</span><span style="background: white; color: rgb(43, 145, 175);">QueueOutput</span><span style="background: white; color: black;">] </span><span style="background: white; color: blue;">out </span><span style="background: white; color: rgb(43, 145, 175);">IEnumerable</span><span style="background: white; color: black;">&lt;</span><span style="background: white; color: blue;">string</span><span style="background: white; color: black;">&gt; testqueue)
        {
            testqueue = </span><span style="background: white; color: blue;">new string</span><span style="background: white; color: black;">[] {
                </span><span style="background: white; color: rgb(163, 21, 21);">&quot;one&quot;</span><span style="background: white; color: black;">,
                </span><span style="background: white; color: rgb(163, 21, 21);">&quot;two&quot;</span><span style="background: white; color: black;">,
                </span><span style="background: white; color: rgb(163, 21, 21);">&quot;three&quot;
            </span><span style="background: white; color: black;">};
        }  </span></pre>

<pre class="code"><span style="background: white; color: black;"></span><span style="background: white; color: black;"></span></pre>

<p>You could of course bind to multiple output queues. For example, this takes an OrderRequest object as input, logs a history to the “history” queue, and may turn around and enqueue suborders for this order. </p>

<pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">ProcessOrders(
            [</span><span style="background: white; color: rgb(43, 145, 175);">QueueInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;orders&quot;</span><span style="background: white; color: black;">)] OrderRequest input,
            [</span><span style="background: white; color: rgb(43, 145, 175);">QueueOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;history&quot;</span><span style="background: white; color: black;">)] <span style="background: white; color: black;"></span><span style="background: white; color: blue;">out </span>WorkItem output, </span><span style="background: white; color: green;">// log a history
            </span><span style="background: white; color: black;">[</span><span style="background: white; color: rgb(43, 145, 175);">QueueOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;orders&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: blue;">out </span><span style="background: white; color: rgb(43, 145, 175);">IEnumerable</span><span style="background: white; color: black;">&lt;OrderRequest&gt; children
            )
        {
            
        }</span></pre>


<h3>Diagnostics: Navigating between Producers and Consumers</h3>

<p>The Azure WebJobs SDK will track who queued a message so you can use the <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/27/getting-a-dashboard-for-local-development-with-the-webjobs-sdk.aspx">dashboard</a> to see relationships between queue producers and consumers. </p>

<p>For example, consider these functions:</p>

<pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">Producer(
            [</span><span style="background: white; color: rgb(43, 145, 175);">QueueOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;testqueue&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: blue;">out </span><span style="background: white; color: rgb(43, 145, 175);">Payload </span><span style="background: white; color: black;">payload,
            </span><span style="background: white; color: blue;">string </span><span style="background: white; color: black;">output, 
            </span><span style="background: white; color: blue;">int </span><span style="background: white; color: black;">value            
            )
        {
            payload = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: rgb(43, 145, 175);">Payload </span><span style="background: white; color: black;">{ Output = output, Value = value };
        }

        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">Consumer([</span><span style="background: white; color: rgb(43, 145, 175);">QueueInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;testqueue&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">Payload </span><span style="background: white; color: black;">payload)
        {
        }</span></pre>


<p>And say we invoked Producer explicitly via:</p>

<pre class="code"><span style="background: white; color: black;">        host.Call(</span><span style="background: white; color: blue;">typeof</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(43, 145, 175);">Program</span><span style="background: white; color: black;">).GetMethod(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;Producer&quot;</span><span style="background: white; color: black;">), </span><span style="background: white; color: blue;">new </span><span style="background: white; color: black;">{ output = </span><span style="background: white; color: rgb(163, 21, 21);">&quot;Hello&quot;</span><span style="background: white; color: black;">, value = 15 });</span></pre>


<p>So the Producer() queues a message which is then consumed by Consumer(). </p>

<p>We can see Consumer’s execution in the dashboard:</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/6708.image_2AD2818E.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/6708.image_5F00_2AD2818E.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/4263.image_thumb_5853A151.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/4263.image_5F00_thumb_5F00_5853A151.png" width="518" height="321" /></a></p>

<p>And we can see that it was executed because “New queue input message on ‘testqueue’ from Producer()”. So we can click on the link to producer to jump to that function instance:</p>



<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/2110.image_7F21B791.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/2110.image_5F00_7F21B791.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/0066.image_thumb_5F06AAD4.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/0066.image_5F00_thumb_5F00_5F06AAD4.png" width="523" height="499" /></a></p>

<p>And here, we can see that it was executed because of our explicit call to JobHost.Call. And that a child function of Producer() is Consumer(), so you can navigating both directions. </p>

<p>Note this only works when using non-BCL types. You’ll notice the queue payload has an extra “$AzureJobsParentId” field, which we can easily add in JSON objects.</p>



<h3>Binding to CloudMessage SDK Types</h3>

<p>You can also bind to the CloudQueue Storage SDK type directly. This provides a backdoor if you need full access to queue APIs that don’t naturally map to model binding. </p>

<pre class="code"><span style="background: white; color: black;">        [</span><span style="background: white; color: rgb(43, 145, 175);">NoAutomaticTrigger</span><span style="background: white; color: black;">]
        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">Queue1(</span><span style="background: white; color: rgb(43, 145, 175);">CloudQueue </span><span style="background: white; color: black;">testqueue)
        {
            </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">ts = </span><span style="background: white; color: rgb(43, 145, 175);">TimeSpan</span><span style="background: white; color: black;">.FromSeconds(400);
            testqueue.AddMessage(</span><span style="background: white; color: blue;">new </span><span style="background: white; color: rgb(43, 145, 175);">CloudQueueMessage</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;test&quot;</span><span style="background: white; color: black;">), ts);            
        }</span></pre>


<p>It’s still in Alpha, so there are some known issues we’re working through, such as:</p>

<ul>
  <li>Alpha 1 does not support binding to CloudQueueMessage directly. </li>

  <li>better bindings for outputs </li>

  <li>more customization round serialization for non-BCL types. </li>

  <li>Better user control over the QueueInput listening </li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Azure Storage Bindings Part 1 – Blobs</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/azure-storage-bindings-part-1-blobs</link>
      <pubDate>Tue, 18 Feb 2014 09:09:24 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/02/18/azure-storage-bindings-part-1-blobs/</guid>
      <description><![CDATA[The Azure WebJobs SDK provides model binding between C# BCL types and Azure storage like Blobs,...]]></description>
      <content:encoded><![CDATA[<p>The <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/24/webjobs-sdk.aspx">Azure WebJobs SDK</a> provides model binding between C# BCL types and Azure storage like Blobs, Tables, and Queues. </p>  <p>The SDK has a <a href="http://www.nuget.org/packages/Microsoft.WindowsAzure.Jobs.Host">JobHost</a> object which reflects over the functions in your assembly.&#160; So your main looks like this:</p>  <pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">static void </span><span style="background: white; color: black;">Main()
        {
            </span><span style="background: white; color: blue;">string </span><span style="background: white; color: black;">acs = </span><span style="background: white; color: rgb(163, 21, 21);">&quot;DefaultEndpointsProtocol=https;AccountName=???;AccountKey=???&quot;</span><span style="background: white; color: black;">;
            </span><span style="background: white; color: rgb(43, 145, 175);">JobHost </span><span style="background: white; color: black;">host = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: rgb(43, 145, 175);">JobHost</span><span style="background: white; color: black;">(acs); </span><span style="background: white; color: green;">// From nuget: Microsoft.WindowsAzure.Jobs.Host
            </span><span style="background: white; color: black;">host.RunAndBlock();            
        }</span></pre>

<p>The JobHost will reflect over your methods looking for attributes in the Microsoft.WindowsAzure.Jobs namespace and use those attributes to setup some triggers (BlobInput, QueueInput) and do bindings. RunAndBlock() will scan for various triggers and then invoke your function when a trigger is fired. <strong>Model Binding </strong>refers to how the JobHost binds your functions parameters. (it’s very similar to MVC/WebAPI).</p>

<p>The benefits of model binding:</p>

<ol>
  <li><strong>Convenience</strong>. You can pick the type that’s most useful for you to consume and the WebJobs SDK will take care of the glue code. If you’re doing string operations on a blob, you can bind directly to TextReader/TextWriter, rather than 10 lines of ceremony to convert a TextWriter from a CloudBlob. </li>

  <li><strong>Flushing and Closing</strong>: The WebJobs SDK will automatically flush and close outstanding outputs. </li>

  <li><strong>Unit testability</strong>. It’s far easier to unit test and mock BCL types like TextWriter than ICloudBlob. </li>

  <li><strong>Diagnostics</strong>.&#160; model binding cooperates with the dashboard to give you real time diagnostics on your parameter usage. See screenshots below.</li>
</ol>

<p>And if model binding is not sufficient for you, you can always bind to the Storage SDK types directly. </p>

<p>That said, here are the bindings that are currently supported in the Alpha release.&#160; </p>

<h3></h3>

<h3>Binding to BCL types: Stream, TextReader/Writer, String</h3>

<p>You can use [BlobInput] and [BlobOutput] attributes to bind blobs to the BCL types Stream, TextReader and String. </p>

<p>See <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/28/trigger-bindings-and-route-parameters-in-azurejobs.aspx">triggering rules</a> for more details, but basically a function runs when a blob matching [BlobInput] is found that is newer than the blobs specified by [BlobOutput]. This means that it’s important for a [BlobInput] function to write some output (even if it’s just a dummy file) so that the JobHost knows that it’s run and doesn’t keep re-triggering it. </p>

<p>Here’s an example of a blob copy function using each of those types: </p>

<pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">CopyWithStream(
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/in/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);"><font style="background-color: rgb(255, 255, 0);">Stream</font> </span><span style="background: white; color: black;">input,
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/out1/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);"><font style="background-color: rgb(255, 255, 0);">Stream</font> </span><span style="background: white; color: black;">output
            )
        {
            </span><span style="background: white; color: rgb(43, 145, 175);">Debug</span><span style="background: white; color: black;">.Assert(input.CanRead &amp;&amp; !input.CanWrite);
            </span><span style="background: white; color: rgb(43, 145, 175);">Debug</span><span style="background: white; color: black;">.Assert(!output.CanRead &amp;&amp; output.CanWrite);

            input.CopyTo(output);
        }

        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">CopyWithText(
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/in/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);"><font style="background-color: rgb(255, 255, 0);">TextReader</font> </span><span style="background: white; color: black;">input,
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/out2/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);"><font style="background-color: rgb(255, 255, 0);">TextWriter</font> </span><span style="background: white; color: black;">output
            )
        {
            </span><span style="background: white; color: blue;">string </span><span style="background: white; color: black;">content = input.ReadToEnd();
            output.Write(content);
        }

        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">CopyWithString(
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/in/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: blue;"><font style="background-color: rgb(255, 255, 0);">string</font> </span><span style="background: white; color: black;">input,
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/out3/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: blue;"><font style="background-color: rgb(255, 255, 0);">out string</font> </span><span style="background: white; color: black;">output
            )
        {
            output = input;
        }</span></pre>

<p>Some notes:</p>

<ol><!--StartFragment-->
  <li>It’s fine to have multiple functions read from the same input blob. In this case, all functions are reading from any blob that matches “in/{name}” in the container named “container”.</li>

  <li>The Streams / TextWriters are automatically flushed when the function returns.&#160; </li>
<!--EndFragment--></ol>

<p>You can see some more examples for <a href="https://aspnet.codeplex.com/SourceControl/latest#Samples/AzureWebJobs/BasicSamples/BlobOperations/Program.cs">blob usage on the sample site</a>. </p>



<h3>Diagnostics!</h3>

<p>When you look at the function invocation in the <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/27/getting-a-dashboard-for-local-development-with-the-webjobs-sdk.aspx">dashboard</a>, you can see usage stats for each parameter. In this case, we see that CopyWithStream() was invoked on blob “in/a.txt”, and read 4 bytes from it, spending 0.076 seconds on IO, and wrote out 4 bytes to blob “out1/a.txt”. </p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/8508.image_73C5296A.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/8508.image_5F00_73C5296A.png"><img title="image" style="display: inline; background-image: none;" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/40/72/metablogapi/6445.image_thumb_338F0FF0.png" original-url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-40-72-metablogapi/6445.image_5F00_thumb_5F00_338F0FF0.png" width="697" height="217" /></a></p>

<p>Again, the monitoring here “just works” when using the SDK, you don’t need to include any extra logging packages or do any extra configuration work to enable it. </p>



<h3>Binding to Blob Storage SDK types</h3>

<p>You can also bind directly to <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudblob.aspx">CloudBlob</a> (v1 storage sdk) or <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.blob.icloudblob.aspx">ICloudBlob</a>, <a href="http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.storageclient.cloudpageblob.aspx">CloudPageBlob</a>, <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudblockblob.aspx">CloudBlobBlob</a> (v2+ storage sdk). These options are good when you need to blob properties not exposed as a stream (such as etags, metadata, etc). </p>

<pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">UseStorageSdk(
           [</span><span style="background: white; color: rgb(43, 145, 175);">BlobInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/in/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);"><font style="background-color: rgb(255, 255, 0);">CloudBlob</font> </span><span style="background: white; color: black;">input,
           [</span><span style="background: white; color: rgb(43, 145, 175);">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;container/out4/{name}&quot;</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);"><font style="background-color: rgb(255, 255, 0);">CloudBlob</font> </span><span style="background: white; color: black;">output
           )
        {
            </span><span style="background: white; color: green;">// get non-stream properties 
            </span><span style="background: white; color: black;">input.FetchAttributes();
            </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">keys = input.Metadata.AllKeys;            
            
            </span><span style="background: white; color: green;">// do stuff...
        </span><span style="background: white; color: black;">}</span></pre>


<p>The storage types obviously give you full control, but they don’t cooperate with the dashboard and so won’t give you the same monitoring experience as using the BCL types.</p>

<p>You can also bind a parameter to both <strong>CloudStorageAccount</strong> 1.7x and 2.x+ Storage SDK types. </p>

<pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">Func(</span><span style="background: white; color: rgb(43, 145, 175);">CloudStorageAccount </span><span style="background: white; color: black;">account, ...)
        {
            </span><span style="background: white; color: green;">// Now use the azure SDK directly 
        </span><span style="background: white; color: black;">}</span></pre>

<p>The SDK is reflecting over the method parameters, so it knows if ‘account’ is 1.7x (<a href="http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.cloudstorageaccount.cloudstorageaccount.aspx">Microsoft.WindowsAzure.CloudStorageAccount</a>) or 2x+ (<a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.cloudstorageaccount(v=azure.10).aspx">Microsoft.WindowsAzure.Storage.CloudStorageAccount</a>) and can bind to either one. This means that existing applications using 1.7 can start to incorporate the WebJobs SDK. </p>]]></content:encoded>
    </item>
    <item>
      <title>Trigger, Bindings, and Route parameters in AzureJobs</title>
      <link>https://docs.microsoft.com/archive/blogs/jmstall/trigger-bindings-and-route-parameters-in-azurejobs</link>
      <pubDate>Tue, 28 Jan 2014 10:28:39 GMT</pubDate>
      <dc:creator><![CDATA[Mike Stall - MSFT]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/jmstall/2014/01/28/trigger-bindings-and-route-parameters-in-azurejobs/</guid>
      <description><![CDATA[We recently an alpha for WebJobs SDK (aka AzureJobs , and internally codenamed “SimpleBatch”). In...]]></description>
      <content:encoded><![CDATA[<p>We recently an alpha for WebJobs SDK (aka <a href="http://blogs.msdn.com/b/jmstall/archive/2014/01/25/10492631.aspx">AzureJobs</a> , and internally codenamed “SimpleBatch”). In this blog entry, I wanted to explain how Triggers, Bindings, and Route Parameters worked in AzureJobs. </p><p>A function can be <strong>“triggered”</strong> by some event such as a new blob, new queue message, or explicit invocation. JobHost (in the <a href="http://www.nuget.org/packages/Microsoft.WindowsAzure.Jobs.Host/0.1.0-alpha1">Microsoft.WindowsAzure.Jobs.Host</a> nuget package) listens for the triggers and invokes the functions. </p><p>The trigger source also provides the <strong>“route parameters”</strong>, which is an extra name-value pair dictionary that helps with binding. This is very similar to WebAPI / MVC. The trigger event provides the route parameters, and then the parameter can be consumed in other bindings:</p><p>1. Via a [BlobOutput] parameter&nbsp; <br>2. Via an explicit parameter capture. </p><p>&nbsp;</p><h4>Trigger on new blobs</h4><p><strong>Example usage:</strong></p><p>This happens when the first attribute is [BlobInput] and the function gets triggered when a new blob is detected that matches the pattern.&nbsp;&nbsp; </p><pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">ApplyWaterMark(
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">@"images-output/{<font style="background-color: rgb(255, 255, 0);">name</font>}"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">Stream </span><span style="background: white; color: black;">inputStream,
            </span><span style="background: white; color: blue;">string </span><span style="background: white; color: black;"><font style="background-color: rgb(255, 255, 0);">name</font>,
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">@"images-watermarks/{<font style="background-color: rgb(255, 255, 0);">name</font>}"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">Stream </span><span style="background: white; color: black;">outputStream)
        {
            </span><span style="background: white; color: rgb(43, 145, 175);">WebImage </span><span style="background: white; color: black;">image = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: rgb(43, 145, 175);">WebImage</span><span style="background: white; color: black;">(inputStream);
            image.AddTextWatermark(name, fontSize: 20, fontColor: </span><span style="background: white; color: rgb(163, 21, 21);">"red"</span><span style="background: white; color: black;">);
            image.Save(outputStream);
        }</span></pre><p><strong>When does it execute?</strong></p><p>The triggering system will compare timestamps for the input blobs to timestamps from the output blobs and only invoke the function if the inputs are newer than the outputs. This simple rules makes the system very easy to explain and prevents the system from endlessly re-executing the same function.</p><p><strong>Route parameters</strong>: </p><p>In this case, the route parameter is {name} from BlobInput, and it flows to the BlobOutput binding. This pattern lends itself nicely for doing blob-2-blob transforms.</p><p>The route parameter is also captured via the “name” parameter. If the parameter type is not string, the binder will try to convert via invoking the TryParse method on the parameter type. This provides nice serialization semantics for simple types like int, guid, etc. The binder also looks for a TypeConverter, so you can extend binding to your own custom types. </p><p>In WebAPI, route parameters are provided by pattern matching against a URL. In AzureJobs, they’re provided by pattern matching against a BlobInput path (which is morally similar to a URL). This case was implemented first and so the name kind of stuck. </p><p>&nbsp;</p><h4>Trigger on new queue message </h4><p><strong>Example usage:</strong></p><p>This happens when the first attribute is [QueueInput]. </p><pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">public static void </span><span style="background: white; color: black;">HandleQueue(
            [</span><span style="background: white; color: black;"></span><span style="background: white; color: rgb(43, 145, 175);">QueueInput</span><span style="background: white; color: rgb(43, 145, 175);"><font style=""></font></span><span style="background: white; color: black;">(queueName : </span><span style="background: white; color: rgb(163, 21, 21);">"myqueue"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">CustomObject </span><span style="background: white; color: black;">obj,
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobInput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">"input/{<font style="background-color: rgb(0, 255, 0);">Text</font>}.txt"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">Stream </span><span style="background: white; color: black;">input,
            </span><span style="background: white; color: blue;">int </span><span style="background: white; color: black;"><font style="background-color: rgb(255, 255, 0);">Number</font>,
            [</span><span style="background: white; color: rgb(43, 145, 175);">BlobOutput</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">"results/{<font style="background-color: rgb(0, 255, 0);">Text</font>}.txt"</span><span style="background: white; color: black;">)] </span><span style="background: white; color: rgb(43, 145, 175);">Stream </span><span style="background: white; color: black;">output)
        {
        }</span></pre><pre class="code"><span style="background: white; color: black;"></span>&nbsp;</pre><pre class="code"><span style="background: white; color: black;">    </span><span style="background: white; color: blue;">public class </span><span style="background: white; color: rgb(43, 145, 175);">CustomObject
    </span><span style="background: white; color: black;">{
        </span><span style="background: white; color: blue;">public string </span><span style="background: white; color: black;"><font style="background-color: rgb(0, 255, 0);">Text</font> { </span><span style="background: white; color: blue;">get</span><span style="background: white; color: black;">; </span><span style="background: white; color: blue;">set</span><span style="background: white; color: black;">; }

        </span><span style="background: white; color: blue;">public int </span><span style="background: white; color: black;"><font style="background-color: rgb(255, 255, 0);">Number</font> { </span><span style="background: white; color: blue;">get</span><span style="background: white; color: black;">; </span><span style="background: white; color: blue;">set</span><span style="background: white; color: black;">; }
    }</span></pre><pre class="code">&nbsp;</pre><p>The function has both a QueueInput and BlobInput, but it triggers when the Queue message is detected and just uses the Blob input as a resource while executing. </p><p><strong>When does it execute?</strong></p><p>This function executes when a new queue message is found on the specified queue. The JobHost will keep the <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudqueue.updatemessage.aspx">message invisible</a> until the function returns (which is very handy for long running functions) and it will <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudqueue.deletemessage.aspx">DeleteMessage</a> for you when the function is done. </p><p><strong>Route parameters:</strong></p><p>In this case, the route parameters are the simple properties on the Queue parameter type&nbsp; (so Text and Number). Note that since the queue parameter type (CustomObject) is a complex object, it will get deserialized using JSON.net.&nbsp; Queue parameter types could also be string or byte[] (in which case they bind to the <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudqueuemessage.asstring.aspx">CloudQueueMessage.AsString</a> and <a href="http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudqueuemessage.asbytes.aspx">AsBytes</a>). </p><p>The usage of parameter binding here may mean your function body doesn’t even need to look at the contents of the queue message. </p><p>&nbsp;</p><h4>Trigger when explicitly called via JobHost.Call(). </h4><p><strong>Example usage:</strong></p><p>You can explicitly invoke a method via JobHost.Call().</p><pre class="code"><span style="background: white; color: black;">            </span><span style="background: white; color: rgb(43, 145, 175);">JobHost </span><span style="background: white; color: black;">h = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: rgb(43, 145, 175);">JobHost</span><span style="background: white; color: black;">();
            </span><span style="background: white; color: blue;">var </span><span style="background: white; color: black;">method = </span><span style="background: white; color: blue;">typeof</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(43, 145, 175);">ImageFuncs</span><span style="background: white; color: black;">).GetMethod(</span><span style="background: white; color: rgb(163, 21, 21);">"ApplyWaterMark"</span><span style="background: white; color: black;">);
            h.Call(method, </span><span style="background: white; color: blue;">new </span><span style="background: white; color: black;">{ name = </span><span style="background: white; color: rgb(163, 21, 21);">"fruit.jpg" </span><span style="background: white; color: black;">});</span></pre><p><strong>When does it execute?</strong></p><p>I expect the list of possible triggers to grow over time, although JobHost.Call() does provide tremendous flexibility since you can have your own external listening mechanism that invokes the functions yourself. EG, you could simulate a Timer trigger by having your own timer callback which does JobHost.Call().</p><p>You can use JobHost.Call() to invoke a method that would normally be triggered by BlobInput. </p><p>You can also suppress automatic triggering via a "[NoAutomaticTrigger]” attribute on the method. In that case, the function can only be invoked via JobHost.Call(). </p><p><strong>Route Parameters:</strong></p><p>The Call() method takes an anonymous object that provides the route parameters. In this case, it assigned “name”&nbsp; as “fruit,jpg”. The single route parameter will allow 3 normal parameters of ApplyWaterMark to get bound.</p><p>&nbsp;</p><h4>Disclaimers</h4><p>AzureJobs is still in alpha. So some of the rules may get tweaked to improve the experience. </p><p><span style="background: white; color: black;"></span></p>]]></content:encoded>
    </item>
  </channel>
</rss>