Jekyll2021-09-18T19:48:14+00:00http://colethecoder.com/feed.xmlcolethecoderC#, Functional Programming, Cloud, SRE etc...Announcing Chronological2018-03-12T12:00:00+00:002018-03-12T12:00:00+00:00http://colethecoder.com/2018/03/12/Announcing-Chronological<p>At present I spend much of my working day on IoT projects and dealing with time series data has become a vital part of this. Relational or Document based databases aren’t really designed to handle lots of telemetry data and trying to do quick queries such as “mean temperature for a particular sensor in the last hour” become painful as data grows. For a while my team experimented with InfluxDB, running in a virtual machine in Azure with some success, but with most of our software moving towards PaaS based services (Azure Functions, Event Grid, Azure SQL etc) maintaining a VM was something we really wanted to avoid.</p>
<p>Last year Microsoft released Azure Time Series Insights, a platform for storing and then subsequently analysing and visualising time series data. We started using it in preview and were really impressed with its performance on the data we were throwing at it. Time Series Insights has a web UI for navigating and querying data and then showing it in various ways, it also supports exporting that data in various ways. To truly be useful as a data store though the data has to be accessible to external applications, fortunately Microsoft provide a REST API for that.</p>
<p>The REST API is documented at:</p>
<p><a href="https://docs.microsoft.com/en-us/rest/api/time-series-insights/time-series-insights-reference-queryapi">https://docs.microsoft.com/en-us/rest/api/time-series-insights/time-series-insights-reference-queryapi</a></p>
<p>There are sample apps for connecting to it at:</p>
<p><a href="https://github.com/Azure-Samples/Azure-Time-Series-Insights">https://github.com/Azure-Samples/Azure-Time-Series-Insights</a></p>
<p>When we started to tackle connecting our applications to the API we quickly found that there was quite a bit of code needed to authenticate, navigate environments and metadata, create the queries in the correct JSON syntax, send the request and then parse the result data. With this in mind, last autumn I started building Chronological, an open source .Net Standard library to simplify access to the API.</p>
<p>The code and documentation is here:</p>
<p><a href="https://github.com/colethecoder/chronological">https://github.com/colethecoder/chronological</a></p>
<p>and if you just want to install a package and get on with it you can get it on nuget here:</p>
<p><a href="https://www.nuget.org/packages/Chronological/">https://www.nuget.org/packages/Chronological/</a></p>
<p>Chronological is a deliberately opinionated wrapper around the API to make accessing time series data feel very familiar to .Net developers. Data in Time Series Insights can take the form of many schemas, imagine a bunch of different sensors firing lots of different readings into the same data store, as a result the API returns a very generic data structure to cope with multiple different schemas in one result set. This approach has its benefits but generally when you are querying data from an application you have some idea of the schema you will be returning. In Chronological you setup an entity class, decorate with a few attributes to reflect the schema you are expecting, connect to your environment and then run a query which returns you an IEnumerable of your entity type. A really simple query for events would look like:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">class</span> <span class="nc">TimeSeriesEntity</span>
<span class="p">{</span>
<span class="p">[</span><span class="nf">ChronologicalEventField</span><span class="p">(</span><span class="s">"DeviceId"</span><span class="p">)]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Id</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="nf">ChronologicalEventField</span><span class="p">(</span><span class="n">BuiltIn</span><span class="p">.</span><span class="n">EventTimeStamp</span><span class="p">)]</span>
<span class="k">public</span> <span class="n">DateTime</span> <span class="n">Date</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="nf">ChronologicalEventField</span><span class="p">(</span><span class="s">"EventType"</span><span class="p">)]</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">Type</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">[</span><span class="nf">ChronologicalEventField</span><span class="p">(</span><span class="s">"Measurement.Value"</span><span class="p">)]</span>
<span class="k">public</span> <span class="kt">double</span><span class="p">?</span> <span class="n">Value</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">connection</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Chronological</span><span class="p">.</span><span class="nf">Connection</span><span class="p">(</span><span class="s">"YourApplicationClientID"</span><span class="p">,</span>
<span class="s">"YourApplicationClientSecret"</span><span class="p">,</span> <span class="s">"YourTenant"</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">environments</span> <span class="p">=</span> <span class="k">await</span> <span class="n">connection</span><span class="p">.</span><span class="nf">GetEnvironmentsAsync</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">environment</span> <span class="p">=</span> <span class="n">environments</span><span class="p">.</span><span class="nf">First</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">events</span> <span class="p">=</span> <span class="k">await</span> <span class="n">environment</span><span class="p">.</span><span class="n">EventQuery</span><span class="p"><</span><span class="n">TimeSeriesEntity</span><span class="p">>(</span><span class="n">DateTime</span><span class="p">.</span><span class="n">UtcNow</span><span class="p">.</span><span class="nf">AddDays</span><span class="p">(-</span><span class="m">1</span><span class="p">),</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">UtcNow</span><span class="p">,</span> <span class="n">Limit</span><span class="p">.</span><span class="n">Take</span><span class="p">,</span> <span class="m">200</span><span class="p">)</span>
<span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">x</span> <span class="p">=></span> <span class="n">x</span><span class="p">.</span><span class="n">Value</span> <span class="p">></span> <span class="m">5</span><span class="p">)</span>
<span class="p">.</span><span class="nf">ExecuteAsync</span><span class="p">();</span>
<span class="k">foreach</span><span class="p">(</span><span class="kt">var</span> <span class="n">e</span> <span class="k">in</span> <span class="n">events</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">$"Type: </span><span class="p">{</span><span class="n">e</span><span class="p">.</span><span class="n">Type</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">ReadLine</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>This is a very simple query just getting 200 events within a date range with a “Measurement.Value” greater than 5. It would generate a JSON query similar to:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="p">{</span>
<span class="dl">"</span><span class="s2">headers</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">x-ms-client-application-name</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">ChronologicalQuery</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Authorization</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Bearer AUTH_TOKEN</span><span class="dl">"</span>
<span class="p">},</span>
<span class="dl">"</span><span class="s2">content</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">searchSpan</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">from</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">2017-12-12T23:02:39.3671297Z</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">to</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">2018-03-12T23:02:39.3671297Z</span><span class="dl">"</span>
<span class="p">},</span>
<span class="dl">"</span><span class="s2">predicate</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">predicateString</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">([Measurement.Value] > 5)</span><span class="dl">"</span>
<span class="p">},</span>
<span class="dl">"</span><span class="s2">take</span><span class="dl">"</span><span class="p">:</span> <span class="mi">200</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Note in particular that the lambda Where clause has been transformed into the correctly structured predicateString. The nested data structure returned by the API is then parsed by Chronological into the entity class.</p>
<p>Chronological v1.0 is currently in alpha, I intend to release a couple of betas as I receive bugs and feedback and then a proper release in a few weeks.</p>
<p>If you are interested in Time Series Insights please give Chronological a try and give me a shout on Github or Twitter if you have any problems or suggestions.</p>Tom ColeAt present I spend much of my working day on IoT projects and dealing with time series data has become a vital part of this. Relational or Document based databases aren’t really designed to handle lots of telemetry data and trying to do quick queries such as “mean temperature for a particular sensor in the last hour” become painful as data grows. For a while my team experimented with InfluxDB, running in a virtual machine in Azure with some success, but with most of our software moving towards PaaS based services (Azure Functions, Event Grid, Azure SQL etc) maintaining a VM was something we really wanted to avoid.Generating Charts For Bots2017-10-12T12:00:00+00:002017-10-12T12:00:00+00:00http://colethecoder.com/2017/10/12/Bot-Framework-Charts-Image-Generation<p>Building an interesting user experience through bots frequently requires the use of images, differing channels have varying capabilities and you can use the <a href="https://docs.botframework.com/en-us/channel-inspector/channels/Skype?f=Carousel&e=example1">Channel Inspector</a> web page to get an idea of what these are for your target platform.</p>
<p>One thing all the image presentations (Hero Card, Thumbnail Card, Attachment etc) have in common is that they ask for a URL to the image. In dynamic scenarios, like generating a chart image, a web facing URL to the image is not necessarily easy. You could create a one-off URL on your web app but that might have security implications and brings caching and other potential headaches. Another option is to generate a base64 string for the image and return a data url as you might in a HTML img tag i.e.</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"> <span class="nt"><img</span> <span class="na">src=</span><span class="s">"data:image/gif;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzA........."</span><span class="nt">/></span></code></pre></figure>
<p>Since a bot built on Bot Framework is just an extended web app a quick way to generate a dynamic chart is to use System.Web.UI.DataVisualization.Charting. This can be found by adding a reference to the System.Web.DataVisualization assembly in your project.</p>
<p>To generate your chart you might use code similar to:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="kt">string</span> <span class="nf">GetLineChart</span><span class="p">(</span><span class="n">Dictionary</span><span class="p"><</span><span class="n">DateTime</span><span class="p">,</span> <span class="kt">double</span><span class="p">></span> <span class="n">points</span><span class="p">,</span> <span class="kt">string</span> <span class="n">title</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Create a series and add data points to it</span>
<span class="kt">var</span> <span class="n">series</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Series</span><span class="p">(</span><span class="s">"Chart"</span><span class="p">);</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">point</span> <span class="k">in</span> <span class="n">points</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">series</span><span class="p">.</span><span class="n">Points</span><span class="p">.</span><span class="nf">AddXY</span><span class="p">(</span><span class="n">point</span><span class="p">.</span><span class="n">Key</span><span class="p">,</span> <span class="n">point</span><span class="p">.</span><span class="n">Value</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">series</span><span class="p">.</span><span class="n">ChartType</span> <span class="p">=</span> <span class="n">SeriesChartType</span><span class="p">.</span><span class="n">Line</span><span class="p">;</span>
<span class="n">series</span><span class="p">.</span><span class="n">MarkerStyle</span> <span class="p">=</span> <span class="n">MarkerStyle</span><span class="p">.</span><span class="n">Circle</span><span class="p">;</span>
<span class="c1">// Generate chart</span>
<span class="kt">var</span> <span class="n">chart</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Chart</span><span class="p">{</span><span class="n">Height</span> <span class="p">=</span> <span class="m">800</span><span class="p">,</span> <span class="n">Width</span> <span class="p">=</span> <span class="m">800</span><span class="p">,</span> <span class="n">Titles</span> <span class="p">=</span> <span class="p">{</span> <span class="k">new</span> <span class="nf">Title</span><span class="p">(</span><span class="n">title</span><span class="p">)}};</span>
<span class="c1">// Setup some styling</span>
<span class="n">chart</span><span class="p">.</span><span class="n">BackColor</span> <span class="p">=</span> <span class="n">Color</span><span class="p">.</span><span class="nf">FromArgb</span><span class="p">(</span><span class="m">211</span><span class="p">,</span> <span class="m">223</span><span class="p">,</span> <span class="m">240</span><span class="p">);</span>
<span class="n">chart</span><span class="p">.</span><span class="n">BorderlineDashStyle</span> <span class="p">=</span> <span class="n">ChartDashStyle</span><span class="p">.</span><span class="n">Solid</span><span class="p">;</span>
<span class="n">chart</span><span class="p">.</span><span class="n">BackGradientStyle</span> <span class="p">=</span> <span class="n">GradientStyle</span><span class="p">.</span><span class="n">TopBottom</span><span class="p">;</span>
<span class="n">chart</span><span class="p">.</span><span class="n">BorderlineWidth</span> <span class="p">=</span> <span class="m">1</span><span class="p">;</span>
<span class="n">chart</span><span class="p">.</span><span class="n">Palette</span> <span class="p">=</span> <span class="n">ChartColorPalette</span><span class="p">.</span><span class="n">BrightPastel</span><span class="p">;</span>
<span class="n">chart</span><span class="p">.</span><span class="n">BorderlineColor</span> <span class="p">=</span> <span class="n">Color</span><span class="p">.</span><span class="nf">FromArgb</span><span class="p">(</span><span class="m">26</span><span class="p">,</span> <span class="m">59</span><span class="p">,</span> <span class="m">105</span><span class="p">);</span>
<span class="n">chart</span><span class="p">.</span><span class="n">RenderType</span> <span class="p">=</span> <span class="n">RenderType</span><span class="p">.</span><span class="n">BinaryStreaming</span><span class="p">;</span>
<span class="n">chart</span><span class="p">.</span><span class="n">BorderSkin</span><span class="p">.</span><span class="n">SkinStyle</span> <span class="p">=</span> <span class="n">BorderSkinStyle</span><span class="p">.</span><span class="n">Emboss</span><span class="p">;</span>
<span class="n">chart</span><span class="p">.</span><span class="n">AntiAliasing</span> <span class="p">=</span> <span class="n">AntiAliasingStyles</span><span class="p">.</span><span class="n">All</span><span class="p">;</span>
<span class="n">chart</span><span class="p">.</span><span class="n">TextAntiAliasingQuality</span> <span class="p">=</span> <span class="n">TextAntiAliasingQuality</span><span class="p">.</span><span class="n">Normal</span><span class="p">;</span>
<span class="c1">// Add series to chart with area</span>
<span class="n">chart</span><span class="p">.</span><span class="n">Series</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">series</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">area</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">ChartArea</span><span class="p">(</span><span class="s">"Area"</span><span class="p">);</span>
<span class="n">chart</span><span class="p">.</span><span class="n">ChartAreas</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">area</span><span class="p">);</span>
<span class="n">chart</span><span class="p">.</span><span class="n">ChartAreas</span><span class="p">[</span><span class="m">0</span><span class="p">].</span><span class="n">AxisX</span><span class="p">.</span><span class="n">LabelStyle</span><span class="p">.</span><span class="n">Format</span> <span class="p">=</span> <span class="s">"t"</span><span class="p">;</span>
<span class="c1">// Save it to a stream</span>
<span class="kt">var</span> <span class="n">imageStream</span> <span class="p">=</span> <span class="k">new</span> <span class="n">System</span><span class="p">.</span><span class="n">IO</span><span class="p">.</span><span class="nf">MemoryStream</span><span class="p">();</span>
<span class="n">chart</span><span class="p">.</span><span class="nf">SaveImage</span><span class="p">(</span><span class="n">imageStream</span><span class="p">,</span> <span class="n">ChartImageFormat</span><span class="p">.</span><span class="n">Png</span><span class="p">);</span>
<span class="c1">// Convert stream to base64 string</span>
<span class="kt">var</span> <span class="n">base64</span> <span class="p">=</span> <span class="n">Convert</span><span class="p">.</span><span class="nf">ToBase64String</span><span class="p">(</span><span class="n">imageStream</span><span class="p">.</span><span class="nf">ToArray</span><span class="p">());</span>
<span class="c1">// Return base64 string prefixed with the relevant data URL parameters</span>
<span class="k">return</span> <span class="s">$"data:image/png;base64,</span><span class="p">{</span><span class="n">base64</span><span class="p">}</span><span class="s">"</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>To then add this to a card in your dialog code you would do something like:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetChart</span><span class="p">(</span><span class="n">IDialogContext</span> <span class="n">context</span><span class="p">,</span> <span class="n">IAwaitable</span><span class="p"><</span><span class="n">IMessageActivity</span><span class="p">></span> <span class="n">activity</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Some mechanism for retrieving data</span>
<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="nf">GetData</span><span class="p">();</span>
<span class="c1">// Call the chart method</span>
<span class="kt">var</span> <span class="n">chartDataUrl</span> <span class="p">=</span> <span class="nf">GetLineChart</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="s">"Chart Title"</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">message</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="nf">MakeMessage</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">card</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HeroCard</span>
<span class="p">{</span>
<span class="n">Title</span> <span class="p">=</span> <span class="s">"Chart"</span><span class="p">,</span>
<span class="n">Subtitle</span> <span class="p">=</span> <span class="s">"Demo"</span>
<span class="p">};</span>
<span class="n">card</span><span class="p">.</span><span class="n">Images</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">CardImage</span><span class="p">></span> <span class="p">{</span><span class="k">new</span> <span class="nf">CardImage</span><span class="p">(</span><span class="n">url</span><span class="p">:</span> <span class="n">chartDataUrl</span><span class="p">};</span>
<span class="kt">var</span> <span class="n">attachment</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Attachment</span><span class="p">(</span><span class="n">contentType</span><span class="p">:</span> <span class="n">HeroCard</span><span class="p">.</span><span class="n">ContentType</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="n">card</span><span class="p">);</span>
<span class="n">message</span><span class="p">.</span><span class="n">Attachments</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">attachment</span><span class="p">);</span>
<span class="k">await</span> <span class="n">context</span><span class="p">.</span><span class="nf">PostAsync</span><span class="p">(</span><span class="n">message</span><span class="p">);</span>
<span class="n">context</span><span class="p">.</span><span class="nf">Wait</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">MessageReceived</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>Or to return as an attachment, which may be preferable on some channels from a zoom perspective (an attachment can be opened full size in Teams / Skype whereas a Hero Card might be scaled down and hard to read).</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">GetChart</span><span class="p">(</span><span class="n">IDialogContext</span> <span class="n">context</span><span class="p">,</span> <span class="n">IAwaitable</span><span class="p"><</span><span class="n">IMessageActivity</span><span class="p">></span> <span class="n">activity</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Some mechanism for retrieving data</span>
<span class="kt">var</span> <span class="n">data</span> <span class="p">=</span> <span class="nf">GetData</span><span class="p">();</span>
<span class="c1">// Call the chart method</span>
<span class="kt">var</span> <span class="n">chartDataUrl</span> <span class="p">=</span> <span class="nf">GetLineChart</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="s">"Chart Title"</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">message</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="nf">MakeMessage</span><span class="p">();</span>
<span class="kt">var</span> <span class="n">attachment</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Attachment</span><span class="p">(</span><span class="n">contentType</span><span class="p">:</span> <span class="s">"image/png"</span><span class="p">,</span> <span class="n">contentUrl</span><span class="p">:</span> <span class="n">url</span><span class="p">);</span>
<span class="n">message</span><span class="p">.</span><span class="n">Attachments</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">attachment</span><span class="p">);</span>
<span class="k">await</span> <span class="n">context</span><span class="p">.</span><span class="nf">PostAsync</span><span class="p">(</span><span class="n">message</span><span class="p">);</span>
<span class="n">context</span><span class="p">.</span><span class="nf">Wait</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">MessageReceived</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>Tom ColeBuilding an interesting user experience through bots frequently requires the use of images, differing channels have varying capabilities and you can use the Channel Inspector web page to get an idea of what these are for your target platform.Showing Current Location on a Map in Cortana Skills2017-10-08T12:00:00+00:002017-10-08T12:00:00+00:00http://colethecoder.com/2017/10/08/Cortana-Current-Location-Bing-Maps<p>One of the interesting things about working with Bot Framework is the channel-specific features that you can make use of. Whilst many channels offer differing format options for displaying responses, Cortana can also expose extra information to Bot Framework about the user. Recently I’ve been working with these features to provide a better user experience on one of my bots to give the user information about IoT-enabled machines that are nearby.</p>
<p>To utilise the user’s location via Cortana you first have to do a little setup through the Bot web interface (<a href="https://dev.botframework.com">dev.botframework.com</a>). You need to configure the Cortana channel for your bot and “Request user profile data”. For the user’s current location in my example I configured:</p>
<p><img src="/img/cortana-request-user-profile-data.jpg" alt="User SemanticLocation Current" /></p>
<p>Once this is done the next time someone invokes the bot via Cortana it will ask them for consent to share their location. If they agree you should then be able to get the location in Bot Framework from the IDialogContext.</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">if</span> <span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">Activity</span><span class="p">.</span><span class="n">ChannelId</span> <span class="p">==</span> <span class="n">ChannelIds</span><span class="p">.</span><span class="n">Cortana</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">userInfo</span> <span class="p">=</span> <span class="n">activity</span><span class="p">.</span><span class="n">Entities</span><span class="p">.</span><span class="nf">FirstOrDefault</span><span class="p">(</span><span class="n">e</span> <span class="p">=></span> <span class="n">e</span><span class="p">.</span><span class="n">Type</span><span class="p">.</span><span class="nf">Equals</span><span class="p">(</span><span class="s">"UserInfo"</span><span class="p">));</span>
<span class="kt">var</span> <span class="n">currentLocation</span> <span class="p">=</span> <span class="n">userInfo</span><span class="p">.</span><span class="n">Properties</span><span class="p">[</span><span class="s">"CurrentLocation"</span><span class="p">];</span>
<span class="p">}</span></code></pre></figure>
<p>The variable currentLocation is of type <a href="https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JToken.htm">Newtonsoft.Json.Linq.JToken</a> and the actual JSON looks like:</p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="p">{</span>
<span class="dl">"</span><span class="s2">StartTime</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">2017-10-04T07:09:59Z</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">EndTime</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">2017-10-08T16:15:22Z</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Hub</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">Id</span><span class="dl">"</span><span class="p">:</span> <span class="dl">""</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Other</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Name</span><span class="dl">"</span><span class="p">:</span> <span class="dl">""</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Latitude</span><span class="dl">"</span><span class="p">:</span> <span class="mf">52.0375053</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Longitude</span><span class="dl">"</span><span class="p">:</span> <span class="o">-</span><span class="mf">0.7645475</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Address</span><span class="dl">"</span><span class="p">:</span> <span class="dl">""</span>
<span class="p">},</span>
<span class="dl">"</span><span class="s2">VenueName</span><span class="dl">"</span><span class="p">:</span> <span class="dl">""</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">Away</span><span class="dl">"</span><span class="p">:</span> <span class="kc">false</span>
<span class="p">}</span></code></pre></figure>
<p>Now I can get the longitude and latitude with code like:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="kt">var</span> <span class="n">hub</span> <span class="p">=</span> <span class="n">currentLocation</span><span class="p">[</span><span class="s">"Hub"</span><span class="p">];</span>
<span class="kt">var</span> <span class="n">latitude</span> <span class="p">=</span> <span class="n">hub</span><span class="p">.</span><span class="n">Value</span><span class="p"><</span><span class="kt">double</span><span class="p">>(</span><span class="s">"Latitude"</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">longitude</span> <span class="p">=</span> <span class="n">hub</span><span class="p">.</span><span class="n">Value</span><span class="p"><</span><span class="kt">double</span><span class="p">>(</span><span class="s">"Longitude"</span><span class="p">);</span></code></pre></figure>
<p>Next we want a good way of showing this location to the user. At present we are quite limited on what we can show via the Cortana UI from Bot Framework so the best option is to generate an image of a map. Fortunately Bing Maps exposes a REST API purely for this purpose: <a href="https://msdn.microsoft.com/en-us/library/ff701724.aspx">Bing Maps REST Service - Imagery</a>. To use this service you need a Bing Maps API key, you can sign up for one of these directly or, if you use Azure, you can add it to your subscription. The <a href="https://www.bingmapsportal.com/">Bing Maps Portal</a> has instructions. Once you have the key it is just a case of building up the querystring for your requirements. Below is the full code for a LUIS Intent that, when called from Cortana, displays a Hero Card for the user’s current location:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="p">[</span><span class="nf">LuisIntent</span><span class="p">(</span><span class="s">"SearchNearbyMachines"</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">SearchNearbyMachines</span><span class="p">(</span><span class="n">IDialogContext</span> <span class="n">context</span><span class="p">,</span> <span class="n">IAwaitable</span><span class="p"><</span><span class="n">IMessageActivity</span><span class="p">></span> <span class="n">activityAsync</span><span class="p">,</span> <span class="n">LuisResult</span> <span class="n">result</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">activity</span> <span class="p">=</span> <span class="k">await</span> <span class="n">activityAsync</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">Activity</span><span class="p">.</span><span class="n">ChannelId</span> <span class="p">==</span> <span class="n">ChannelIds</span><span class="p">.</span><span class="n">Cortana</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">userInfo</span> <span class="p">=</span> <span class="n">activity</span><span class="p">.</span><span class="n">Entities</span><span class="p">.</span><span class="nf">FirstOrDefault</span><span class="p">(</span><span class="n">e</span> <span class="p">=></span> <span class="n">e</span><span class="p">.</span><span class="n">Type</span><span class="p">.</span><span class="nf">Equals</span><span class="p">(</span><span class="s">"UserInfo"</span><span class="p">));</span>
<span class="kt">var</span> <span class="n">currentLocation</span> <span class="p">=</span> <span class="n">userInfo</span><span class="p">.</span><span class="n">Properties</span><span class="p">[</span><span class="s">"CurrentLocation"</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="n">currentLocation</span> <span class="p">!=</span> <span class="k">null</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">hub</span> <span class="p">=</span> <span class="n">currentLocation</span><span class="p">[</span><span class="s">"Hub"</span><span class="p">];</span>
<span class="kt">var</span> <span class="n">latitude</span> <span class="p">=</span> <span class="n">hub</span><span class="p">.</span><span class="n">Value</span><span class="p"><</span><span class="kt">double</span><span class="p">>(</span><span class="s">"Latitude"</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">longitude</span> <span class="p">=</span> <span class="n">hub</span><span class="p">.</span><span class="n">Value</span><span class="p"><</span><span class="kt">double</span><span class="p">>(</span><span class="s">"Longitude"</span><span class="p">);</span>
<span class="c1">// Build the querystring for current location pin</span>
<span class="kt">var</span> <span class="n">currentLocationPinQueryString</span> <span class="p">=</span> <span class="s">$"pp=</span><span class="p">{</span><span class="n">latitude</span><span class="p">}</span><span class="s">,</span><span class="p">{</span><span class="n">longitude</span><span class="p">}</span><span class="s">;21;Current%20Location"</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">message</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="nf">MakeMessage</span><span class="p">();</span>
<span class="c1">// Build the URL for Bing Maps</span>
<span class="kt">var</span> <span class="n">imageUrl</span> <span class="p">=</span>
<span class="s">$"https://dev.virtualearth.net/REST/v1/Imagery/Map/Road/</span><span class="p">{</span><span class="n">latitude</span><span class="p">}</span><span class="s">,</span><span class="p">{</span><span class="n">longitude</span><span class="p">}</span><span class="s">/0?mapSize=350,350&</span><span class="p">{</span><span class="n">currentLocationPinQueryString</span><span class="p">}</span><span class="s">&key=</span><span class="p">{</span><span class="n">_bingMapsKey</span><span class="p">}</span><span class="s">"</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">card</span> <span class="p">=</span> <span class="k">new</span> <span class="n">HeroCard</span>
<span class="p">{</span>
<span class="n">Title</span> <span class="p">=</span> <span class="s">"Nearby Machines"</span><span class="p">,</span>
<span class="n">Images</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">CardImage</span><span class="p">></span> <span class="p">{</span> <span class="k">new</span> <span class="n">CardImage</span><span class="p">{</span><span class="n">Url</span> <span class="p">=</span> <span class="n">imageUrl</span> <span class="p">}</span> <span class="p">}</span>
<span class="p">};</span>
<span class="kt">var</span> <span class="n">attachment</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Attachment</span><span class="p">(</span><span class="n">contentType</span><span class="p">:</span> <span class="n">HeroCard</span><span class="p">.</span><span class="n">ContentType</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="n">card</span><span class="p">);</span>
<span class="n">message</span><span class="p">.</span><span class="n">Attachments</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">attachment</span><span class="p">);</span>
<span class="k">await</span> <span class="n">context</span><span class="p">.</span><span class="nf">PostAsync</span><span class="p">(</span><span class="n">message</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="c1">// Do something for none location-aware channels</span>
<span class="k">await</span> <span class="n">context</span><span class="p">.</span><span class="nf">PostAsync</span><span class="p">(</span><span class="s">$"I don't know where you are"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>In this example I have set the image size to 350x350 which seems to fit nicely in the Cortana canvas for a Hero Card. I have also created a pin for the current location with the name “Current Location” and styling 21. The resulting Card looks like:</p>
<p><img src="/img/purplebot-current-location.JPG" alt="PurpleBot Screen Shot" /></p>
<p>Obviously this only achieves part of my current aim, I will expand on this in future posts.</p>Tom ColeOne of the interesting things about working with Bot Framework is the channel-specific features that you can make use of. Whilst many channels offer differing format options for displaying responses, Cortana can also expose extra information to Bot Framework about the user. Recently I’ve been working with these features to provide a better user experience on one of my bots to give the user information about IoT-enabled machines that are nearby.Cortana Timeouts Using Bot Framework2017-10-06T12:00:00+00:002017-10-06T12:00:00+00:00http://colethecoder.com/2017/10/06/Cortana-Timeouts-Bot-Framework<p>Whilst working with Bot Framework recently I found myself in a situation whereupon my bot worked perfectly across channels including Skype, Teams and Bot Emulator but within Cortana I’d get a strange error.</p>
<p><img src="/img/cortana-timeout-error.jpg" alt="Cortana has run into a problem. Please try again later." /></p>
<p>The error occured after a few interactions and following showing some search results which displayed correctly, any subsequent request resulted in the error. After wiring up Application Insights to my bot I finally generated some more interesting errors.</p>
<p><img src="/img/application-insights-bot-error.jpg" alt="Exception type: Microsoft.Bot.Schema.BotTimeoutExceptionFailed method: Microsoft.Bot.ChannelConnector.BotAPI. Call to SendActivityToUserAsync failed" /></p>
<p>This gave me a bit of a clue about where the problem was, somewhere in the conversation Bot Framework is failing to send information to the Cortana backend. This lead me to revisit my code and look at each message being sent. What followed was some rather clumsy trial and error tweaks to isolate the problem message. Finally I discovered that the problem was sending two messages to Cortana in quick succession.</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="p">[</span><span class="nf">LuisIntent</span><span class="p">(</span><span class="s">"SearchMachines"</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">Search</span><span class="p">(</span><span class="n">IDialogContext</span> <span class="n">context</span><span class="p">,</span> <span class="n">LuisResult</span> <span class="n">result</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">searchingMessage</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="nf">MakeMessage</span><span class="p">();</span>
<span class="n">searchingMessage</span><span class="p">.</span><span class="n">Speak</span> <span class="p">=</span> <span class="s">"Searching"</span><span class="p">;</span>
<span class="n">searchingMessage</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="s">"Searching"</span><span class="p">;</span>
<span class="k">await</span> <span class="n">context</span><span class="p">.</span><span class="nf">PostAsync</span><span class="p">(</span><span class="n">searchingMessage</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">searchResults</span> <span class="p">=</span> <span class="n">searchRepository</span><span class="p">.</span><span class="nf">Search</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">resultMessage</span> <span class="p">=</span> <span class="nf">BuildResultMessage</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
<span class="k">await</span> <span class="n">context</span><span class="p">.</span><span class="nf">PostAsync</span><span class="p">(</span><span class="n">resultMessage</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>By commenting out the rather pointless “Searching” message we now avoid any errors and Cortana behaves. Another alternative is to only drop the “Searching” message for the Cortana channel i.e.</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="p">[</span><span class="nf">LuisIntent</span><span class="p">(</span><span class="s">"SearchMachines"</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">async</span> <span class="n">Task</span> <span class="nf">Search</span><span class="p">(</span><span class="n">IDialogContext</span> <span class="n">context</span><span class="p">,</span> <span class="n">LuisResult</span> <span class="n">result</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">Activity</span><span class="p">.</span><span class="n">ChannelId</span> <span class="p">!=</span> <span class="n">ChannelIds</span><span class="p">.</span><span class="n">Cortana</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">searchingMessage</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="nf">MakeMessage</span><span class="p">();</span>
<span class="n">searchingMessage</span><span class="p">.</span><span class="n">Speak</span> <span class="p">=</span> <span class="s">"Searching"</span><span class="p">;</span>
<span class="n">searchingMessage</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="s">"Searching"</span><span class="p">;</span>
<span class="k">await</span> <span class="n">context</span><span class="p">.</span><span class="nf">PostAsync</span><span class="p">(</span><span class="n">searchingMessage</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">var</span> <span class="n">searchResults</span> <span class="p">=</span> <span class="n">searchRepository</span><span class="p">.</span><span class="nf">Search</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">resultMessage</span> <span class="p">=</span> <span class="nf">BuildResultMessage</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
<span class="k">await</span> <span class="n">context</span><span class="p">.</span><span class="nf">PostAsync</span><span class="p">(</span><span class="n">resultMessage</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>Tom ColeWhilst working with Bot Framework recently I found myself in a situation whereupon my bot worked perfectly across channels including Skype, Teams and Bot Emulator but within Cortana I’d get a strange error.Quick Integration Tests Using JSON2014-08-14T12:00:00+00:002014-08-14T12:00:00+00:00http://colethecoder.com/2014/08/14/Quick-Integration-Tests-Using-JSON<p>A few times recently I’ve picked up legacy code, with no unit tests and long complex methods and had to tweak it. In an ideal world you’d deconstruct the logic and break it down into a series of small testable steps but when time is short that’s not always an option. To avoid any “seat of the pants” hacking and the associated manual testing I sometimes find it useful to write some quick high-level tests that assess all the logic together, save me some time manually testing and provide a little bit of a safety net for future adventurers.</p>
<p>Checking an expected output given a specific input is easy for simple types or small data structures but it quickly turns into lots of tests or stacks of asserts if you have a large object as the result.</p>
<p>A simple method I have used recently to quickly compare two C# objects to ensure their properties match is to serialize the objects and compare the serialized strings to each other. Using <a href="https://www.nuget.org/packages/newtonsoft.json/">Json.Net</a> and <a href="https://www.nuget.org/packages/NUnit/">NUnit</a> you can rapidly put together a dirty test that gives you some assurance that what you are doing is working as you expect e.g.</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">void</span> <span class="nf">AssertAreEqualByJson</span><span class="p">(</span><span class="kt">object</span> <span class="n">expected</span><span class="p">,</span> <span class="kt">object</span> <span class="n">actual</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">expectedJson</span> <span class="p">=</span> <span class="n">JsonConvert</span><span class="p">.</span><span class="nf">SerializeObject</span><span class="p">(</span><span class="n">expected</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">actualJson</span> <span class="p">=</span> <span class="n">JsonConvert</span><span class="p">.</span><span class="nf">SerializeObject</span><span class="p">(</span><span class="n">actual</span><span class="p">);</span>
<span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="n">expectedJson</span><span class="p">,</span> <span class="n">actualJson</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>I’m not advocating this as a replacement for proper testing and if the test fails it can be a bit awkward to work out what the problem is (especially on large objects) but as an alternative to no tests at all it has saved me plenty of time.</p>Tom ColeA few times recently I’ve picked up legacy code, with no unit tests and long complex methods and had to tweak it. In an ideal world you’d deconstruct the logic and break it down into a series of small testable steps but when time is short that’s not always an option. To avoid any “seat of the pants” hacking and the associated manual testing I sometimes find it useful to write some quick high-level tests that assess all the logic together, save me some time manually testing and provide a little bit of a safety net for future adventurers.Cruise Control .Net Self Updating Config2013-01-19T12:00:00+00:002013-01-19T12:00:00+00:00http://colethecoder.com/2013/01/19/Cruise-Control-Net-Self-Updating-Config<p>I’m a massive advocate of continuous integration (CI). I set up a build server for my team a few years ago and it really changed the way we worked for the better. Cruise Control .Net was the first CI software I used and despite flirting with the likes of TeamCity, FAKE and even TFS I always end up returning to Cruise Control because at the moment it does just enough for what I need and is easy to extend with plugins or Powershell when my requirements are a bit more complex.</p>
<p>When you first set up a build server the config is normally pretty basic but as you and your colleagues get used to it you start to realise quite what it can do for you. My current team have our CI server: pulling source code, grabbing Nuget packages, building, testing, minifying, zipping, deploying, running SQL updates, flashing our office traffic lights and updating our HipChat room every time we commit code. As you can imagine the config for this is now fairly big. A few times in the last year I’ve needed to roll back config changes and struggled so I eventually ended up shoving the config in source control. This is great but pushing the latest version into source control and then copying it onto the server seemed weird so I started to investigate whether Cruise Control could update itself.</p>
<p>Fortunately on Thoughtwork’s CCNet pages there is an <a href="http://confluence.public.thoughtworks.org/display/CCNET/Configure+CruiseControl.Net+to+Automatically+Update+its+Config+File">article</a> on just that. I quickly modified our config and ran it to try it. It works great but unfortunately if you push bad config to your source control it will trash your CCNet setup and worse, if CCNet is running you might not even find out about this till next time it restarts.</p>
<p>I wanted a more robust mechanism for updating the config, one that validated my config instead of blindly overwriting the master one. Fortunately CCNet ships with <a href="http://build.sharpdevelop.net/ccnet/doc/CCNET/CCValidator.html">CCValidator.exe</a> which is built for just this purpose.</p>
<p>I found that by using an <a href="http://build.sharpdevelop.net/ccnet/doc/CCNET/Executable%20Task.html">exec task</a> with a specific successExitCodes section I could create a build that failed if the config was invalid. The important task is:</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt"><exec></span>
<span class="nt"><executable></span>$(CCNetValidatorPath)<span class="nt"></executable></span>
<span class="nt"><description></span>Validate Config File<span class="nt"></description></span>
<span class="nt"><baseDirectory></span>C:\<span class="nt"></baseDirectory></span>
<span class="nt"><buildArgs></span>c:\CI\CruiseControl\ccnet.config --nogui --logfile=c:\CI\Logs\ConfigValidation.log<span class="nt"></buildArgs></span>
<span class="nt"><buildTimeoutSeconds></span>30<span class="nt"></buildTimeoutSeconds></span>
<span class="nt"><successExitCodes></span>0<span class="nt"></successExitCodes></span>
<span class="nt"></exec></span></code></pre></figure>
<p>Note that I specify a log file. This is useful for tracking what the problem in the config actually is. You can merge it into your build output using the File publisher:</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt"><publishers></span>
<span class="nt"><merge></span>
<span class="nt"><files></span>
<span class="nt"><file></span>c:\CI\Logs\ConfigValidation.log<span class="nt"></file></span>
<span class="nt"></files></span>
<span class="nt"></merge></span>
<span class="nt"><xmllogger/></span>
<span class="nt"></publishers></span></code></pre></figure>
<p>Now I know my config is under source control and I don’t even have to log onto our build server to update it.</p>
<p>Full config file can be downloaded from: <a href="https://bitbucket.org/colethecoder/cruise-control-auto-update-demo">https://bitbucket.org/colethecoder/cruise-control-auto-update-demo</a></p>Tom ColeI’m a massive advocate of continuous integration (CI). I set up a build server for my team a few years ago and it really changed the way we worked for the better. Cruise Control .Net was the first CI software I used and despite flirting with the likes of TeamCity, FAKE and even TFS I always end up returning to Cruise Control because at the moment it does just enough for what I need and is easy to extend with plugins or Powershell when my requirements are a bit more complex.Simplifying Documentation In MVC With Markdown2012-09-17T12:00:00+00:002012-09-17T12:00:00+00:00http://colethecoder.com/2012/09/17/Simplifying-Documentation-In-MVC-With-Markdown<p>Recently I’ve been building an API for work with the new ASP.Net Web API features and needed to document the functionality for 3rd Party users. I defaulted to cranking open Word and started typing, but it felt clunky. As soon as I started to create a table to track version history I started to foresee the confusion often caused in keeping the documentation in sync with the version of the API. Add to that the API is likely to be used on multiple customer sites which may not all be on the same version of the software and there is a recipe for issues in the future.</p>
<p>I decided instead to opt for web based documentation built into the API to ease the potential for syncing issues. I <a href="http://colethecoder.com/2012/09/16/Markdown-MVC-Mashup/">previously posted</a> about my new-found love of Markdown for simplifying publishing for this blog and whilst there are loads of wiki packages out there I opted for a simple Markdown based solution. Fortunately there’s already a Nuget package available to aid with this: <a href="http://nuget.org/packages/Kiwi.Markdown">Kiwi.Markdown</a>.</p>
<p>To include in a Web API project (I’ve assumed the Razor view engine) you can start by using the Package Manager console:</p>
<blockquote>
<p>PM> Install-Package Kiwi.Markdown</p>
</blockquote>
<p>to keep it nicely formatted I also threw in Twitter Bootstrap:</p>
<blockquote>
<p>PM> Install-Package Twitter.Bootstrap</p>
</blockquote>
<p>The Kiwi.Markdown package creates a new view for you for formatting the Markdown.</p>
<blockquote>
<p>Views\Wiki\Doc.cshtml</p>
</blockquote>
<p>By default this file will be picking up its layout from:</p>
<blockquote>
<p>Views\Shared\_Layout.cshtml</p>
</blockquote>
<p>To incorporate Bootstrap into your Markdown pages, change _Layout.cshtml to:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span> <span class="nt">/></span>
<span class="nt"><meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width"</span> <span class="nt">/></span>
<span class="nt"><title></span>@ViewBag.Title<span class="nt"></title></span>
<span class="nt"><link</span> <span class="na">href=</span><span class="s">"@Url.Content("</span><span class="err">~/</span><span class="na">Content</span><span class="err">/</span><span class="na">bootstrap.min.css</span><span class="err">")"</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="nt">/></span>
<span class="nt"><style </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">padding-top</span><span class="p">:</span> <span class="m">60px</span><span class="p">;</span>
<span class="nl">padding-bottom</span><span class="p">:</span> <span class="m">40px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"><link</span> <span class="na">href=</span><span class="s">"@Url.Content("</span><span class="err">~/</span><span class="na">Content</span><span class="err">/</span><span class="na">bootstrap.responsive-min.css</span><span class="err">")"</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="nt">/></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"navbar navbar-fixed-top"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"navbar-inner"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"container"</span><span class="nt">></span>
<span class="nt"><a</span> <span class="na">class=</span><span class="s">"btn btn-navbar"</span> <span class="na">data-toggle=</span><span class="s">"collapse"</span> <span class="na">data-target=</span><span class="s">".nav-collapse"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"icon-bar"</span><span class="nt">></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"icon-bar"</span><span class="nt">></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"icon-bar"</span><span class="nt">></span></span>
<span class="nt"></a></span>
<span class="nt"><a</span> <span class="na">class=</span><span class="s">"brand"</span> <span class="na">href=</span><span class="s">"#"</span><span class="nt">></span>DOCUMENTATION NAME HERE<span class="nt"></a></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"nav-collapse"</span><span class="nt">></span>
<span class="nt"><ul</span> <span class="na">class=</span><span class="s">"nav"</span><span class="nt">></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"active"</span><span class="nt">><a</span> <span class="na">href=</span><span class="s">"#"</span><span class="nt">></span>Home<span class="nt"></a></li></span>
<span class="nt"></ul></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"container"</span><span class="nt">></span>
@RenderBody()
<span class="nt"></div></span>
@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false)
<span class="nt"></body></span>
<span class="nt"></html></span></code></pre></figure>
<p>and your Doc.cshtml to:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html">@using Kiwi.Markdown
@model Document
@{
ViewBag.Title = @Model.Title;
}
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"span12"</span><span class="nt">></span>
<span class="nt"><h1></span>@Model.Title<span class="nt"></h1></span>
@Html.Raw(Model.Content)
<span class="nt"></div></span></code></pre></figure>
<p>Now adding md files to:</p>
<blockquote>
<p>App_Data\MarkdownFiles\</p>
</blockquote>
<p>will result in nice neatly formatted good looking documentation.</p>Tom ColeRecently I’ve been building an API for work with the new ASP.Net Web API features and needed to document the functionality for 3rd Party users. I defaulted to cranking open Word and started typing, but it felt clunky. As soon as I started to create a table to track version history I started to foresee the confusion often caused in keeping the documentation in sync with the version of the API. Add to that the API is likely to be used on multiple customer sites which may not all be on the same version of the software and there is a recipe for issues in the future.A Journey To A Better Blog2012-09-16T12:00:00+00:002012-09-16T12:00:00+00:00http://colethecoder.com/2012/09/16/Markdown-MVC-Mashup<p>When I originally started this blog it was hosted on <a href="http://www.blogger.com/home" title="http://www.blogger.com/home">Blogger</a> and I spent vast amounts of time tweaking it to get it just how I wanted. In fact I spent so much time tweaking it that I barely posted anything. I found myself fighting against the platform and spending my time hacking instead of publishing. I left Blogger behind and dived into writing my own blog software to host myself, I tried out <a href="http://orchardproject.net/" title="http://orchardproject.net/">Orchard</a>, half wrote my own in MVC but was still spending my time mucking around with code rather than blogging.</p>
<p>Having spoken to other devs this seems like a common story so I started looking for a simpler, cleaner approach. I settled on <a href="http://pages.github.com/" title="Github Pages">Github Pages</a> through the <a href="https://github.com/mojombo/jekyll" title="Jekyll">Jekyll</a> engine. This allowed me to generate a static site (e.g. just HTML, CSS, Javascript) but still gave me the ability to template files and avoid lots of duplicate code. The great thing about Jekyll is that all the content is separated out into <a href="http://daringfireball.net/projects/markdown/" title="Daring Fireball Markdown Page">Markdown</a> format. I can scribble down some quick Markdown in <a href="http://markdownpad.com/" title="Markdown Pad Project">Markdown Pad</a> and have it published through Github for Windows really easily with little friction.</p>
<p>Whilst Jekyll gave me a really clean publishing and templating model it did not give me layout, I’d spent a lot of time on this previously and was now keen to avoid hand crafting this myself. Since the vast majority of my own blog reading is now on either my iPhone I also wanted the blog to look good on mobile, ideally without having separate mobile views. Enter: <a href="http://twitter.github.com/bootstrap/index.html" title="Bootstrap pages on Github">Twitter Bootstrap</a>, a great set of CSS and Javascript that allows you to forget about much of the tweaking to get a cross-browser / cross-device site working. I’ve heard other people slight Bootstrap by saying sites built with it all look the same but the sites look fantastic and development with it is really simple, within a couple of hours of playing around I had a good looking blog up and running and could start to focus on content.</p>
<p>Now I’ve got no excuses for not posting more often.</p>Tom ColeWhen I originally started this blog it was hosted on Blogger and I spent vast amounts of time tweaking it to get it just how I wanted. In fact I spent so much time tweaking it that I barely posted anything. I found myself fighting against the platform and spending my time hacking instead of publishing. I left Blogger behind and dived into writing my own blog software to host myself, I tried out Orchard, half wrote my own in MVC but was still spending my time mucking around with code rather than blogging.Web API - Getting Started2012-09-16T12:00:00+00:002012-09-16T12:00:00+00:00http://colethecoder.com/2012/09/16/Web-API-Paging-Page-Size-And-Result-Size<p>I’ve built a few RESTful APIs in recent years as an alternative to SOAP web services. Over that time it’s got much easier to build them in .Net, firstly MVC v3 added the JsonResult allowing you to just return JSON simply from Controllers and more recently Web API has emerged alongside MVC v4 as a way of building this type of API really simply.</p>
<p>One of the first things I often need to do is get some type of result paging working to support returning only parts of large result sets. The beta versions of Web API had a couple of ways of doing this, using either an OData style syntax or handcrafting it through the querystring but in the final RTM version the [Queryable] attribute was dropped and <a href="http://aspnetwebstack.codeplex.com/SourceControl/changeset/af11adf6b3c5" title="http://aspnetwebstack.codeplex.com/SourceControl/changeset/af11adf6b3c5">this OData support omitted</a> so for now we are left with handcrafting</p>
<p>To build a paged Web API we first need to:</p>
<ul>
<li>Start a new Project in VS2012</li>
<li>Choose “ASP.Net MVC 4 Web Application”</li>
<li>In the MVC4 dialog choose “Web API”</li>
</ul>
<p>VS will generate a new project for you and immediately give you a ValuesController.</p>
<p>Hit F5 to debug and in the browser navigate to:</p>
<blockquote>
<p>http://[your debug server]/api/values</p>
</blockquote>
<p>This will do a GET request which goes through the ValuesController and hits the method:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="nf">Get</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="kt">string</span><span class="p">[]</span> <span class="p">{</span> <span class="s">"value1"</span><span class="p">,</span> <span class="s">"value2"</span> <span class="p">};</span>
<span class="p">}</span></code></pre></figure>
<p>Note that if you’ve used Chrome to do the query you get the result as XML, this is because the default GET header contains the line:</p>
<figure class="highlight"><pre><code class="language-http" data-lang="http"><span class="err">Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</span></code></pre></figure>
<p>You would get the same result if you simply passed in:</p>
<figure class="highlight"><pre><code class="language-http" data-lang="http"><span class="err">Accept: application/xml</span></code></pre></figure>
<p>e.g.</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt"><ArrayOfstring</span> <span class="na">xmlns:i=</span><span class="s">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="na">xmlns=</span><span class="s">"http://schemas.microsoft.com/2003/10/Serialization/Arrays"</span><span class="nt">></span>
<span class="nt"><string></span>value1<span class="nt"></string></span>
<span class="nt"><string></span>value2<span class="nt"></string></span>
<span class="nt"></ArrayOfstring></span></code></pre></figure>
<p>Or you could switch it to JSON with:</p>
<figure class="highlight"><pre><code class="language-http" data-lang="http"><span class="err">Accept: application/json</span></code></pre></figure>
<p>which would give you:</p>
<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">[</span><span class="s2">"value1"</span><span class="p">,</span><span class="s2">"value2"</span><span class="p">]</span></code></pre></figure>
<p>You can try this out with the excellent <a href="http://www.fiddler2.com/fiddler2/" title="http://www.fiddler2.com/fiddler2/">Fiddler</a>. Re-perform the action in the browser with Fiddler running and then drag the request into the Composer where you can manipulate and “Execute” it. This is much easier than trying to do it through the browser over and over and looking in the Inspector -> Raw views you can see exactly what’s going on. I’ll stick with the JSON requests for now.</p>
<p>So once you start to dip your toes into the world of REST you’ll find a lot of arguments over what is and isn’t RESTful. I’m going to handle my paging in the querystring, I think this looks clean and feels REST-y enough for me, I’m sure other people will have differing opinions. What I want to do is be able to limit the query using a url like:</p>
<blockquote>
<p>http://[your debug server]/api/values?page=1&pageSize=2</p>
</blockquote>
<p>To do this I add a couple of optional parameters to the Get method along with default values incase they are not specified. By doing this I stop anyone ever returning the whole result set unless they intentionally do so by overriding the pageSize with a big enough number.</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="n">List</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="n">values</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="kt">string</span><span class="p">></span>
<span class="p">{</span>
<span class="s">"value1"</span><span class="p">,</span> <span class="s">"value2"</span><span class="p">,</span> <span class="s">"value3"</span><span class="p">,</span> <span class="s">"value4"</span><span class="p">,</span> <span class="s">"value5"</span>
<span class="p">};</span>
<span class="k">public</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="kt">string</span><span class="p">></span> <span class="nf">Get</span><span class="p">(</span><span class="kt">int</span> <span class="n">page</span> <span class="p">=</span> <span class="m">0</span><span class="p">,</span> <span class="kt">int</span> <span class="n">pageSize</span> <span class="p">=</span> <span class="m">3</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">values</span><span class="p">.</span><span class="nf">Skip</span><span class="p">(</span><span class="n">page</span><span class="p">*</span><span class="n">pageSize</span><span class="p">).</span><span class="nf">Take</span><span class="p">(</span><span class="n">pageSize</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>Debugging now I can see that:</p>
<blockquote>
<p>http://[your debug server]/api/values?page=1&pageSize=4</p>
</blockquote>
<p>returns:</p>
<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">[</span><span class="s2">"value3"</span><span class="p">,</span><span class="s2">"value4"</span><span class="p">]</span></code></pre></figure>
<p>This is great but it does give you a bit of a problem if you want to do something based on the size of the entire result set e.g. have links for all the pages for navigation, since you would not know how many pages worth of data there was. I’ve seen numerous approaches for this that involve either a second call to another resource for a count or that modify the result set to add the count in. Neither feel particularly clean to me and my preference is to add it into it’s own custom HTTP header, so that irrespective of the limitations you have implemented through the querystring the entire count is always available e.g.</p>
<figure class="highlight"><pre><code class="language-http" data-lang="http"><span class="err">X-Result-Count: 5</span></code></pre></figure>
<p>would highlight that there are 5 results in total.</p>
<p>To implement this we have to make a few alterations to our previous method to expose the HttpResponseMessage so that we can access the headers.</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="n">HttpResponseMessage</span> <span class="nf">Get</span><span class="p">(</span><span class="kt">int</span> <span class="n">page</span> <span class="p">=</span> <span class="m">0</span><span class="p">,</span> <span class="kt">int</span> <span class="n">pageSize</span> <span class="p">=</span> <span class="m">3</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">returnValue</span> <span class="p">=</span> <span class="n">values</span><span class="p">.</span><span class="nf">Skip</span><span class="p">(</span><span class="n">page</span> <span class="p">*</span> <span class="n">pageSize</span><span class="p">).</span><span class="nf">Take</span><span class="p">(</span><span class="n">pageSize</span><span class="p">);</span>
<span class="n">HttpResponseMessage</span> <span class="n">response</span> <span class="p">=</span> <span class="n">Request</span><span class="p">.</span><span class="nf">CreateResponse</span><span class="p">(</span><span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">OK</span><span class="p">,</span> <span class="n">returnValue</span><span class="p">);</span>
<span class="n">response</span><span class="p">.</span><span class="n">Headers</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="s">"X-Result-Count"</span><span class="p">,</span><span class="n">values</span><span class="p">.</span><span class="n">Count</span><span class="p">.</span><span class="nf">ToString</span><span class="p">());</span>
<span class="k">return</span> <span class="n">response</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>Note the return type is now a HttpResponseMessage and we wrap the data up inside it through the Request.CreateResponse. We then simply add the header and return the response.</p>
<p>This does everything we need to simply return paged results and know the overall size the entire response message for:</p>
<blockquote>
<p>http://[your debug server]/api/values?page=1&pageSize=4</p>
</blockquote>
<p>looks something like:</p>
<figure class="highlight"><pre><code class="language-http" data-lang="http"><span class="k">HTTP</span><span class="o">/</span><span class="m">1.1</span> <span class="m">200</span> <span class="ne">OK</span>
<span class="na">Cache-Control</span><span class="p">:</span> <span class="s">no-cache</span>
<span class="na">Pragma</span><span class="p">:</span> <span class="s">no-cache</span>
<span class="na">Content-Type</span><span class="p">:</span> <span class="s">application/json; charset=utf-8</span>
<span class="na">Expires</span><span class="p">:</span> <span class="s">-1</span>
<span class="na">Server</span><span class="p">:</span> <span class="s">Microsoft-IIS/8.0</span>
<span class="na">X-Result-Count</span><span class="p">:</span> <span class="s">5</span>
<span class="na">X-AspNet-Version</span><span class="p">:</span> <span class="s">4.0.30319</span>
<span class="na">X-SourceFiles</span><span class="p">:</span> <span class="s">=?UTF-8?B?RTpcSW5mb3JtXEFQSVRlc3RcQVBJZGVzdFxhcGlcdmFsdWVz?=</span>
<span class="na">X-Powered-By</span><span class="p">:</span> <span class="s">ASP.NET</span>
<span class="na">Date</span><span class="p">:</span> <span class="s">Sun, 16 Sep 2012 22:16:18 GMT</span>
<span class="na">Content-Length</span><span class="p">:</span> <span class="s">19</span>
<span class="p">[</span><span class="s2">"value3"</span><span class="p">,</span><span class="s2">"value4"</span><span class="p">]</span></code></pre></figure>
<p>We are still left with one final awkward scenario, what if we want to retreive the result set size without any data, well we could compromise and return a single result but this seems clumsy. Fortunately there is the HTTP verb HEAD for just this sort of thing. We can implement it so that a HEAD request includes the result size parameter. Web API makes this really simply since we can just add the following method:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="n">HttpResponseMessage</span> <span class="nf">Head</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">HttpResponseMessage</span> <span class="n">response</span> <span class="p">=</span> <span class="n">Request</span><span class="p">.</span><span class="nf">CreateResponse</span><span class="p">();</span>
<span class="n">response</span><span class="p">.</span><span class="n">Headers</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="s">"X-Result-Count"</span><span class="p">,</span> <span class="n">values</span><span class="p">.</span><span class="n">Count</span><span class="p">.</span><span class="nf">ToString</span><span class="p">());</span>
<span class="k">return</span> <span class="n">response</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>now a HEAD request will include the X-Result-Count.</p>Tom ColeI’ve built a few RESTful APIs in recent years as an alternative to SOAP web services. Over that time it’s got much easier to build them in .Net, firstly MVC v3 added the JsonResult allowing you to just return JSON simply from Controllers and more recently Web API has emerged alongside MVC v4 as a way of building this type of API really simply.Netduino Plus DHCP2012-09-06T12:00:00+00:002012-09-06T12:00:00+00:00http://colethecoder.com/2012/09/06/Netduino-Plus-DHCP-Fun-And-Games<p>Over the last week I’ve been playing around with a <a href="http://www.netduino.com/netduinoplus/specs.htm">Netduino Plus</a> for a little project I’ve been planning for a while. It’s a great little device and really easy to get started with.</p>
<p>The first project I tried was to create a little webserver and I found a great “hello world” example here: <a href="http://netduinohacking.blogspot.co.uk/2011/03/netduino-plus-web-server-hello-world.html">http://netduinohacking.blogspot.co.uk/2011/03/netduino-plus-web-server-hello-world.html</a></p>
<p>The tutorial is pretty thorough but I ran into an interesting problem when outputting the assigned IP address out to the debug console while the device was attached to my router via ethernet via the code below:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="n">socket</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Socket</span><span class="p">(</span><span class="n">AddressFamily</span><span class="p">.</span><span class="n">InterNetwork</span><span class="p">,</span><span class="n">SocketType</span><span class="p">.</span><span class="n">Stream</span><span class="p">,</span> <span class="n">ProtocolType</span><span class="p">.</span><span class="n">Tcp</span><span class="p">);</span>
<span class="n">socket</span><span class="p">.</span><span class="nf">Bind</span><span class="p">(</span><span class="k">new</span> <span class="nf">IPEndPoint</span><span class="p">(</span><span class="n">IPAddress</span><span class="p">.</span><span class="n">Any</span><span class="p">,</span> <span class="m">80</span><span class="p">));</span>
<span class="n">Debug</span><span class="p">.</span><span class="nf">Print</span><span class="p">(</span><span class="n">Microsoft</span><span class="p">.</span><span class="n">SPOT</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">NetworkInformation</span><span class="p">.</span><span class="n">NetworkInterface</span><span class="p">.</span><span class="nf">GetAllNetworkInterfaces</span><span class="p">()[</span><span class="m">0</span><span class="p">].</span><span class="n">IPAddress</span><span class="p">);</span>
<span class="n">socket</span><span class="p">.</span><span class="nf">Listen</span><span class="p">(</span><span class="m">10</span><span class="p">);</span>
<span class="nf">ListenForRequest</span><span class="p">();</span></code></pre></figure>
<p>I found that every time I started debugging it always output the IP: 192.168.5.100. This is not on my router’s subnet (192.168.1.xxx).</p>
<p>After a bit of digging I found that 192.168.5.100 is in fact the Netduino’s default IP address and that by being output at this point the most likely issue was that the router hadn’t assigned an IP to the device. This can indicate a network configuration issue but in my case it was because it was taking a while to assign an IP (through DHCP) to the device.</p>
<p>A quick rough tweak to the code fixed the issue by adding a while loop to wait for the IP to be assigned before starting listening.</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="n">socket</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Socket</span><span class="p">(</span><span class="n">AddressFamily</span><span class="p">.</span><span class="n">InterNetwork</span><span class="p">,</span> <span class="n">SocketType</span><span class="p">.</span><span class="n">Stream</span><span class="p">,</span> <span class="n">ProtocolType</span><span class="p">.</span><span class="n">Tcp</span><span class="p">);</span>
<span class="n">socket</span><span class="p">.</span><span class="nf">Bind</span><span class="p">(</span><span class="k">new</span> <span class="nf">IPEndPoint</span><span class="p">(</span><span class="n">IPAddress</span><span class="p">.</span><span class="n">Any</span><span class="p">,</span> <span class="m">80</span><span class="p">));</span>
<span class="kt">string</span> <span class="n">address</span> <span class="p">=</span> <span class="n">Microsoft</span><span class="p">.</span><span class="n">SPOT</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">NetworkInformation</span><span class="p">.</span><span class="n">NetworkInterface</span><span class="p">.</span><span class="nf">GetAllNetworkInterfaces</span><span class="p">()[</span><span class="m">0</span><span class="p">].</span><span class="n">IPAddress</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="n">address</span> <span class="p">==</span> <span class="s">"192.168.5.100"</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">address</span> <span class="p">=</span> <span class="n">Microsoft</span><span class="p">.</span><span class="n">SPOT</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">NetworkInformation</span><span class="p">.</span><span class="n">NetworkInterface</span><span class="p">.</span><span class="nf">GetAllNetworkInterfaces</span><span class="p">()[</span><span class="m">0</span><span class="p">].</span><span class="n">IPAddress</span><span class="p">;</span>
<span class="n">Thread</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="m">2000</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">Debug</span><span class="p">.</span><span class="nf">Print</span><span class="p">(</span><span class="n">address</span><span class="p">);</span>
<span class="n">socket</span><span class="p">.</span><span class="nf">Listen</span><span class="p">(</span><span class="m">10</span><span class="p">);</span>
<span class="nf">ListenForRequest</span><span class="p">();</span></code></pre></figure>
<p>Hope this saves other people time if they run into the same issue.</p>Tom ColeOver the last week I’ve been playing around with a Netduino Plus for a little project I’ve been planning for a while. It’s a great little device and really easy to get started with.