<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Shayne Boyer]]></title><description><![CDATA[Hi, I'm Shayne Boyer, work as a developer advocate for Azure, .NET Core and Open Source, speak at national & community events while helping teams architect web and cloud applications.]]></description><link>https://tattoocoder.com/</link><image><url>https://tattoocoder.com/favicon.png</url><title>Shayne Boyer</title><link>https://tattoocoder.com/</link></image><generator>Ghost 3.2</generator><lastBuildDate>Thu, 09 Apr 2026 22:07:42 GMT</lastBuildDate><atom:link href="https://tattoocoder.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Building applications with C# and a Challenge!]]></title><description><![CDATA[<p>It's seems not too long ago I was laying down the words for "<a href="https://tattoocoder.com/so-many-ways-to-learn-net-in-2020/">So Many Ways to Learn .NET in 2020</a>", but of course it was March yesterday too.</p><p>This list is still very valid; 101 videos (<a href="https://www.youtube.com/channel/UCvtT19MZW8dq5Wwfu6B0oxw">youtube</a> | <a href="https://channel9.msdn.com/Search?term=101&amp;WT.mc_id=dotnet-0000-shboyer">channel9</a>), <a href="https://docs.microsoft.com">Microsoft docs</a>, the various shows now available on the new <a href="https://live.dot.net">https:</a></p>]]></description><link>https://tattoocoder.com/building-applications-with-c-and-a-challenge/</link><guid isPermaLink="false">5fa41669d62e170001a85827</guid><category><![CDATA[learning]]></category><category><![CDATA[dotnet]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Thu, 05 Nov 2020 15:43:08 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2020/11/challenge-header.png" medium="image"/><content:encoded><![CDATA[<img src="https://tattoocoder.com/content/images/2020/11/challenge-header.png" alt="Building applications with C# and a Challenge!"><p>It's seems not too long ago I was laying down the words for "<a href="https://tattoocoder.com/so-many-ways-to-learn-net-in-2020/">So Many Ways to Learn .NET in 2020</a>", but of course it was March yesterday too.</p><p>This list is still very valid; 101 videos (<a href="https://www.youtube.com/channel/UCvtT19MZW8dq5Wwfu6B0oxw">youtube</a> | <a href="https://channel9.msdn.com/Search?term=101&amp;WT.mc_id=dotnet-0000-shboyer">channel9</a>), <a href="https://docs.microsoft.com">Microsoft docs</a>, the various shows now available on the new <a href="https://live.dot.net">https://live.dot.net</a> and <a href="https://docs.microsoft.com/learn/tv/">LearnTV</a> too!</p><p>But wait there's more...</p><!--kg-card-begin: markdown--><h2 id="anewmicrosoftlearningpathforc">A New Microsoft Learning Path for C#</h2>
<p><a href="https://docs.microsoft.com/en-us/learn/paths/build-dotnet-applications-csharp/">Build .NET applications with C# </a>is a new learning path with 6 modules to get anyone started with creating apps from scratch with C#. Start with a basic introduction, move into working with projects and dependencies, debugging and more. In little more than 3 hours, get a refresher or a whole new start with .NET and C#.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://tattoocoder.com/content/images/2020/11/image.png" class="kg-image" alt="Building applications with C# and a Challenge!"></figure><!--kg-card-begin: markdown--><h2 id="wantachallenge">Want a challenge?</h2>
<p>Join the <a href="https://aka.ms/dotnetskills">.NET Skills Challenge</a> for the month of November.</p>
<p>Compete against friends and coworkers by completing interactive modules on how to build apps across multiple platforms with .NET and earn your rank on the leaderboard.</p>
<p><img src="https://tattoocoder.com/content/images/2020/11/how_it_works_3.png" alt="Building applications with C# and a Challenge!"></p>
<p>Over 40 hours of <strong>FREE</strong> Learning inside of this awesome collection of 8 Paths and 5 additional bonus modules.</p>
<p>Topics include Basic C# skills, Web API development, Blazor Apps, Static Web Apps, Xamarin and Visual Studio or VS Code.</p>
<p>Get started by going to <a href="https://aka.ms/dotnetskills">https://aka.ms/dotnetskills</a></p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h2 id="letmeknowhowyouredoing">Let me know how you're doing</h2>
<p>Tweet me <a href="https://twitter.com/spboyer">@spboyer</a>, how are you doing on the leaderboard? Are there more modules you'd like to see for C# or other .NET related topics?</p>
<p>Have fun, it's FREE and for you!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Are you reading the "What's New" in .NET docs?]]></title><description><![CDATA[<p>Did you know that every month, the docs team at Microsoft has a post for <a href="https://docs.microsoft.com/dotnet/whats-new/?WT.mc_id=blog-docs-shboyer">what's new in the .NET documentation</a>?</p><p>For each month there are new articles, updates to existing docs, and kudos for the <a href="https://docs.microsoft.com/en-us/dotnet/whats-new/dotnet-2020-01#community-contributors">community contributors</a>.</p><blockquote>It's super easy to get involved in contributing to the docs for</blockquote>]]></description><link>https://tattoocoder.com/are-you-reading-the-whats-new/</link><guid isPermaLink="false">5e4fe5c8e593dd000196cfa2</guid><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Fri, 21 Feb 2020 14:47:32 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2020/02/document_desk.png" medium="image"/><content:encoded><![CDATA[<img src="https://tattoocoder.com/content/images/2020/02/document_desk.png" alt="Are you reading the "What's New" in .NET docs?"><p>Did you know that every month, the docs team at Microsoft has a post for <a href="https://docs.microsoft.com/dotnet/whats-new/?WT.mc_id=blog-docs-shboyer">what's new in the .NET documentation</a>?</p><p>For each month there are new articles, updates to existing docs, and kudos for the <a href="https://docs.microsoft.com/en-us/dotnet/whats-new/dotnet-2020-01#community-contributors">community contributors</a>.</p><blockquote>It's super easy to get involved in contributing to the docs for the related technologies you are invested or interested in.  See the <a href="https://docs.microsoft.com/contribute">Microsoft docs contributors guide</a> or simply click the "Edit" link at the top of any doc to get started, they are all open source!</blockquote><p>Here are some of the highlights for<a href="https://docs.microsoft.com/dotnet/whats-new/dotnet-2020-01?WT.mc_id=blog-docs-shboyer"> last month</a> .NET Docs</p><p>The <a href="https://docs.microsoft.com/dotnet/architecture/cloud-native/?WT.mc_id=blog-docs-shboyer"><strong>Architecting Cloud-Native Apps for Azure architecture guide e-book</strong></a> added some new sections -</p><ul><li><a href="https://docs.microsoft.com/dotnet/architecture/cloud-native/azure-caching?WT.mc_id=blog-docs-shboyer">Caching in a cloud native app</a></li><li><a href="https://docs.microsoft.com/dotnet/architecture/cloud-native/database-per-microservice?WT.mc_id=blog-docs-shboyer">Database per microservice</a></li><li><a href="https://docs.microsoft.com/dotnet/architecture/cloud-native/elastic-search-in-azure?WT.mc_id=blog-docs-shboyer">Elasticsearch in in a cloud native app</a></li></ul><p><strong><a href="https://docs.microsoft.com/dotnet/csharp/?WT.mc_id=blog-docs-shboyer">C# language</a></strong> revised the <a href="https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/value-types?WT.mc_id=blog-docs-shboyer">Value types</a> and <a href="https://docs.microsoft.com/dotnet/csharp/programming-guide/xmldoc/inheritdoc?WT.mc_id=blog-docs-shboyer">added new &lt;inheritdoc&gt; xml documentation</a></p><p><strong>.NET</strong> added a great new article in the <strong><a href="https://docs.microsoft.com/dotnet/standard/?WT.mc_id=blog-docs-shboyer">.NET Guide</a></strong> on <a href="https://docs.microsoft.com/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to?WT.mc_id=blog-docs-shboyer">How to migrate from Newtonsoft.Json to System.Text.Json</a></p><p>Other areas of the docs are also adding similar related what's new pages too. Check out <strong><a href="https://docs.microsoft.com/aspnet/core/whats-new/?view=aspnetcore-3.1&amp;WT.mc_id=blog-docs-shboyer">ASP.NET Core docs updates</a></strong> and<strong><a href="https://docs.microsoft.com/xamarin/whats-new/?WT.mc_id=blog-docs-shboyer"> Xamarin updates</a> </strong>too!</p><p>The docs continue to grow and evolve. Check in often on these pages to keep up to date with the latest content. </p>]]></content:encoded></item><item><title><![CDATA[Updating the my blog from AppService to Containers...finally]]></title><description><![CDATA[<p>I have been running the well known <a href="https://ghost.org">ghost blogging platform </a>on <a href="https://docs.microsoft.com/azure/app-service/?WT.mc_id=-blog-shboyer">Azure AppService</a> since ghost was version 0.10, about 8 years. In fact, it was before Azure had resource groups.</p><p>This means that it's Node on Windows Servers and I'm doing a bit of maintenance for upgrading the version</p>]]></description><link>https://tattoocoder.com/updating-the-my-blog-from-appservice-to-containers-finally/</link><guid isPermaLink="false">5e21f038938cee0001801e9f</guid><category><![CDATA[azure]]></category><category><![CDATA[docker]]></category><category><![CDATA[ghost]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Fri, 17 Jan 2020 18:53:34 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1455487890814-f11ab4eaec4b?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=2000&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1455487890814-f11ab4eaec4b?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=2000&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ" alt="Updating the my blog from AppService to Containers...finally"><p>I have been running the well known <a href="https://ghost.org">ghost blogging platform </a>on <a href="https://docs.microsoft.com/azure/app-service/?WT.mc_id=-blog-shboyer">Azure AppService</a> since ghost was version 0.10, about 8 years. In fact, it was before Azure had resource groups.</p><p>This means that it's Node on Windows Servers and I'm doing a bit of maintenance for upgrading the version of the platform. Running things like gulp.js scripts for builds and so and hoping for <a href="https://github.com/projectkudu/kudu/wiki">Kudu </a>to do my git deployment after a couple of tries because I am running on a small box and there are limitations for networking and npm and start scripts to complete in enough time.</p><p>After a few successful upgrades, it became overwhelmingly painful to try and make the updates and life, work, etc. got in the way and now ghost is on version 3.2 and I am far too behind to try and do a manual update. So the jump to containers makes sense.</p><hr><blockquote>The data conversion was a little more work as I had to install ghost 1.0, import my data &gt; export it and then import to 3.0.</blockquote><h1 id="choosing-the-setup">Choosing the setup</h1><p>I am using the latest <strong>ghost:3.2-alpine</strong> image available on Docker Hub.  </p><!--kg-card-begin: markdown--><p><code>$ docker run -d -p 3001:2368 ghost:3.2-alpine</code></p>
<!--kg-card-end: markdown--><p>It uses SQLite by default as the backend, but also offers MySQL which I'll use as an option through MySQL on Azure.</p><h2 id="analytics">Analytics</h2><p>I have been using Google Analytics for the past 12 years on my blog and want to continue with this solution. However, if you're starting a new solution, <a href="https://docs.microsoft.com/azure/azure-monitor/app/app-insights-overview?WT.mc_id=-blog-shboyer">Application Insights</a> is a quick click option when creating your AppService instance. </p><p>Create a new Dockerfile and add <a href="https://docs.microsoft.com/azure/azure-monitor/app/app-insights-overview?WT.mc_id=-blog-shboyer">Application Insights</a> in this manner:</p><!--kg-card-begin: markdown--><pre><code>FROM ghost:3.2-alpine

# Add app-insights globally
RUN npm install -g applicationinsights

# Link app insights to avoid rebuild/validate projects npm package tree
RUN cd current &amp;&amp; npm link applicationinsights 

# ENV APPINSIGHTS_INSTRUMENTATIONKEY xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
RUN sed  -i.bak -e &quot;/var startTime = Date.now(),/a appInsights = require('applicationinsights'), &quot; \
                -e &quot;/ghost, express, common, urlService, parentApp;/a appInsights.setup().start();&quot; current/index.js
</code></pre>
<!--kg-card-end: markdown--><blockquote>You'll need to build your own Dockerfile and host it in a repository. i.e. Azure Container Registry, Docker Hub, GitHub etc.</blockquote><p>This adds the npm package for <a href="https://docs.microsoft.com/azure/azure-monitor/app/app-insights-overview?WT.mc_id=-blog-shboyer">Application Insights</a> and adds the script to the <strong>index,js </strong>files of the application. Be sure to add your <strong>APPINSIGHTS_INSTRUMENTATIONKEY </strong>environment variable to your App Service Configuration.</p><h2 id="azure-web-app-for-containers">Azure Web App for Containers</h2><p>As I mentioned, the previous version was hosted in Azure App Service on Windows (Node 10 + Windows). Now we are moving to Linux (Alpine) on <a href="https://docs.microsoft.com/en-us/azure/app-service/containers/">Web App for Containers</a>.</p><p><a href="https://docs.microsoft.com/azure/app-service/containers/app-service-linux-cli?WT.mc_id=-blog-shboyer">Creating the app service</a> was really simple. A single command line got the job started for me.  (ok maybe 2, need a service plan too)</p><!--kg-card-begin: markdown--><pre><code># Created my S1 service plan
az appservice plan create -n spboyerblog20 -g spboyer --is-linux - &quot;East US&quot; --sku S1 --number-of-workers 1

# Create the app service with the alpine 3.2 ghost image
az webapp create -n spboyer -g spboyer -p spboyerblog20 -i ghost:3.2-alpine
</code></pre>
<!--kg-card-end: markdown--><h3 id="mysql">MySQL</h3><p><br>I have setup the database backend using <a href="https://azure.microsoft.com/services/mysql/?WT.mc_id=-blog-shboyer">Azure Database for MySQL</a> selecting bare minimums and an auto growth option - Basic, 1 vCore(s), 10 GB. </p><p>The data connections are set as ENV variables in my application settings.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tattoocoder.com/content/images/2020/01/image.png" class="kg-image" alt="Updating the my blog from AppService to Containers...finally"><figcaption>Database settings for MySQL</figcaption></figure><p>Using a service for my data takes care of the potential data loss should the container fail. However, there are files like my <strong>themes and images</strong> that I want to make sure I don't lose if the container decides to restart or when I put in a customer container and CI/CD.  Enter -&gt; <a href="https://docs.microsoft.com/azure/storage/?WT.mc_id=-blog-shboyer">Azure Storage</a> and <a href="https://docs.microsoft.com/azure/app-service/containers/how-to-serve-content-from-azure-storage?WT.mc_id=-blog-shboyer">Path mappings in Web App for Containers</a>!</p><p>I created a File Share in my storage account called <strong>contentfiles, </strong>where I can upload/update this content as well as interact with it using any SDK or even an Azure Function.</p><figure class="kg-card kg-image-card"><img src="https://tattoocoder.com/content/images/2020/01/image-1.png" class="kg-image" alt="Updating the my blog from AppService to Containers...finally"></figure><p>Next, to map the path to the container set it in the <strong>Path mappings</strong> section of my configuration.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tattoocoder.com/content/images/2020/01/image-2.png" class="kg-image" alt="Updating the my blog from AppService to Containers...finally"><figcaption>Path Mappings</figcaption></figure><blockquote>Be sure to set the ENV in configuration  <br><strong>paths__contentPath </strong>to <strong> /var/lib/ghost/content_files</strong></blockquote><p>This can also be done using the Azure CLI, however I found it easier using the GUI for this task.</p><!--kg-card-begin: markdown--><p><code>az webapp config storage-account add -g &lt;resource-group&gt; --custom-id Content-name [Storage Account Name] --share-name contentfiles --access-key [Storage Account Key] mount-path /var/lib/ghost/content_files</code></p>
<!--kg-card-end: markdown--><h2 id="other-configuration-settings">Other configuration settings </h2><ul><li>NODE_ENV : production</li><li>url : &lt;appname&gt;.azurewebsites.net OR your custom domain (cause links to break)</li><li>WEBSITES_PORT : 2368 (internal port for ghost) - this my be a regression for auto detecting port used by containers.</li><li>PORT : 2368  (internal port for ghost) - this my be a regression for auto detecting port used by containers. <em>not a duplicate</em></li></ul><h2 id="additional-notable-changes">Additional Notable changes</h2><p>I run Cloudflare for DNS and caching, so there were some changes I needed to make for my custom domains. The DNS changes took about 30 seconds to make the A, CNAME and TXT updates. Either it's much easier or I know what I'm doing. </p><p>Caching was purged, pushed a button and SSL - done, comes free with Cloudflare.</p><hr><p>After all that, very happy. Was great and Azure was super easy to get setup on containers and now I am positioned for CI/CD on GitHub Actions or Azure DevOps or whatever I want. Bring on the updates!</p>]]></content:encoded></item><item><title><![CDATA[So Many Ways to Learn .NET in 2020]]></title><description><![CDATA[<p>It's a new year and sure to be on your list, as well as mine, is learning. Here is a quick list of some .NET learning resources for you to check off that resolution for 2020.</p><h2 id="-net-101-videos-dot-net-videos">.NET 101 Videos - <a href="https://dotnet.microsoft.com/learn/videos?WT.mc_id=learn-blog-shboyer">dot.net/videos</a></h2><figure class="kg-card kg-image-card"><img src="https://tattoocoder.com/content/images/2020/01/dotnet-videos.png" class="kg-image" alt=".NET 101 Videos"></figure><p>In September of 2019, many members if</p>]]></description><link>https://tattoocoder.com/so-many-ways-to-learn-net-in-2020/</link><guid isPermaLink="false">5e21d58e8f21290001e160f5</guid><category><![CDATA[dotnet]]></category><category><![CDATA[learning]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Wed, 08 Jan 2020 16:59:00 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2020/01/2020learning.png" medium="image"/><content:encoded><![CDATA[<img src="https://tattoocoder.com/content/images/2020/01/2020learning.png" alt="So Many Ways to Learn .NET in 2020"><p>It's a new year and sure to be on your list, as well as mine, is learning. Here is a quick list of some .NET learning resources for you to check off that resolution for 2020.</p><h2 id="-net-101-videos-dot-net-videos">.NET 101 Videos - <a href="https://dotnet.microsoft.com/learn/videos?WT.mc_id=learn-blog-shboyer">dot.net/videos</a></h2><figure class="kg-card kg-image-card"><img src="https://tattoocoder.com/content/images/2020/01/dotnet-videos.png" class="kg-image" alt="So Many Ways to Learn .NET in 2020"></figure><p>In September of 2019, many members if the .NET team created over 100 videos for topics including C# 101, .NET, desktop apps, ASP.NET web apps, learning containers and Docker. More have been added recently including a whole series around creating and managing NuGet packages.</p><p>All of the videos are available on <a href="https://www.youtube.com/channel/UCvtT19MZW8dq5Wwfu6B0oxw">YouTube</a> or <a href="https://channel9.msdn.com/Search?term=101&amp;WT.mc_id=learn-blog-shboyer">Channel 9</a>.</p><h2 id="microsoft-learn">Microsoft Learn</h2><p><a href="https://docs.microsoft.com/learn/?WT.mc_id=learn-blog-shboyer">Microsoft Learn</a> allows you to master core concepts at your speed. Take 15 minutes to complete a module or start a whole learning path  over a course of an hour or multiple hours on your schedule.</p><h4 id="c-modules">C# Modules</h4><figure class="kg-card kg-image-card"><img src="https://tattoocoder.com/content/images/2020/01/csharp-learn.png" class="kg-image" alt="So Many Ways to Learn .NET in 2020"></figure><p><a href="https://docs.microsoft.com/learn/browse/?term=c%23&amp;WT.mc_id=learn-blog-shboyer">Over 20 Modules</a> on C# available.</p><h4 id="asp-net-net-core-modules">ASP.NET / .NET Core Modules</h4><figure class="kg-card kg-image-card"><img src="https://tattoocoder.com/content/images/2020/01/aspnet-learn.png" class="kg-image" alt="So Many Ways to Learn .NET in 2020"></figure><p><a href="https://docs.microsoft.com/learn/modules/build-web-api-net-core/?WT.mc_id=learn-blog-shboyer">Create a web API with ASP.NET Core</a> - Create a RESTful service with ASP.NET Core that supports Create, Read, Update, Delete (CRUD) operations.</p><p><a href="https://docs.microsoft.com/learn/modules/create-razor-pages-aspnet-core/?WT.mc_id=learn-blog-shboyer">Create a web UI with ASP.NET Core</a> - ASP.NET Core supports creating webpages using a built-in templating engine called Razor. In this module, you'll learn how to create webpages using Razor with ASP.NET Core.</p><p><a href="https://docs.microsoft.com/learn/modules/secure-aspnet-core-identity/?WT.mc_id=learn-blog-shboyer">Secure an ASP.NET Core web app with the Identity framework</a> - Add authentication and authorization to an ASP.NET Core web app using the Identity framework.</p><p><a href="https://docs.microsoft.com/learn/modules/persist-data-ef-core/?WT.mc_id=learn-blog-shboyer">Persist and retrieve relational data with Entity Framework Core</a> - Query and manage relational data in a .NET Core app with an Object-Relational Mapper.</p><h2 id="docs-docs-docs-">Docs, Docs, Docs!</h2><p>There are so many pages of tutorials, reference pages, SDK, and examples in the docs. <a href="https://docs.microsoft.com/">https://docs.microsoft.com/</a> is the entry point, however here are the .NET related pages for you.</p><ul><li><a href="https://docs.microsoft.com/dotnet/?WT.mc_id=learn-blog-shboyer">.NET Docs</a></li><li><a href="https://docs.microsoft.com/aspnet/?WT.mc_id=learn-blog-shboyer">ASP.NET Core Docs</a></li><li><a href="https://docs.microsoft.com/xamarin/?WT.mc_id=learn-blog-shboyer">Xamarin Docs</a></li><li><a href="https://docs.microsoft.com/dotnet/azure/?view=azure-dotnet&amp;WT.mc_id=learn-blog-shboyer">.NET on Azure</a></li></ul><h2 id="others">Others</h2><ul><li><a href="https://channel9.msdn.com/Shows/On-NET?WT.mc_id=learn-blog-shboyer">On.NET Show</a> - Channel 9 show hosted by Cecil Phillip <a href="https://twitter.com/cecilphillip">cecilphillip</a>, Rich Lander <a href="https://twitter.com/runfaster2000">@runfaster2000</a> and other guest hosts. Great content where they look at the APIs, the tooling, and some of the interesting projects being created in the .NET ecosystem.</li><li><a href="https://channel9.msdn.com/Shows/Azure-Friday?WT.mc_id=learn-blog-shboyer">Azure Friday</a> - Join Scott Hanselman, Donovan Brown, or Lara Rubbelke as they host the engineers who build Azure, demo it, answer questions, and share insights.</li><li><a href="https://aka.ms/cloudnativeshow">Cloud Native Show</a> - Follow Shayne as he explores Microsoft campus to get the definition (and more) straight from engineers and product teams.</li></ul><p>This is in no way an exhaustive list, there are many blogs, and other video resources out on the web. Feel free to comment with your favorites!</p>]]></content:encoded></item><item><title><![CDATA[Recommending VSCode extensions within your Open Source projects]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Do you run an open-source project? Use <a href="https://code.visualstudio.com">Visual Studio Code</a> and its extensive set of <a href="https://marketplace.visualstudio.com/vscode">extensions</a> when maintaining your project or even coding day to day?</p>
<p>If you have an extension or set of them you prefer/recommend for your projects; you can enable other contributors by informing them with</p>]]></description><link>https://tattoocoder.com/recommending-vscode-extensions-within-your-open-source-projects/</link><guid isPermaLink="false">5e20d712283d3500013a42f4</guid><category><![CDATA[vscode]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Wed, 14 Aug 2019 19:23:57 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2019/08/Screen-Shot-2019-08-14-at-2.53.11-PM-1.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://tattoocoder.com/content/images/2019/08/Screen-Shot-2019-08-14-at-2.53.11-PM-1.png" alt="Recommending VSCode extensions within your Open Source projects"><p>Do you run an open-source project? Use <a href="https://code.visualstudio.com">Visual Studio Code</a> and its extensive set of <a href="https://marketplace.visualstudio.com/vscode">extensions</a> when maintaining your project or even coding day to day?</p>
<p>If you have an extension or set of them you prefer/recommend for your projects; you can enable other contributors by informing them with an alert showing any like.</p>
<p><img src="https://tattoocoder.com/content/images/2019/08/Screen-Shot-2019-08-14-at-2.53.11-PM.png" alt="Recommending VSCode extensions within your Open Source projects"></p>
<p>Clicking on <strong>Show Recommendations</strong> opens the <strong>Workspace Recommendations</strong></p>
<p><img src="https://tattoocoder.com/content/images/2019/08/Screen-Shot-2019-08-14-at-2.53.35-PM.png" alt="Recommending VSCode extensions within your Open Source projects"></p>
<p>Details allows you to also ignore Ignore the recommendation as well.</p>
<p><img src="https://tattoocoder.com/content/images/2019/08/Screen-Shot-2019-08-14-at-2.54.15-PM.png" alt="Recommending VSCode extensions within your Open Source projects"></p>
<h3 id="enablinginyourrepository">Enabling in your repository</h3>
<p>Add a <code>.vscode</code> folder, if not already there for your debugging setup, and create a new file named: <code>extensions.json</code> with the following structure.</p>
<pre><code class="language-javascript">{
	&quot;recommendations&quot;: [
		&quot;msjsdiag.debugger-for-chrome&quot;
	]
}
</code></pre>
<p>The <code>recommendations[]</code> contains the extensions identifier from the Visual Studio Marketplace.</p>
<p>If I were to add recommended extensions for the <a href="https://github.com/dotnet-presentations/aspnetcore-app-workshop">ASP.NET Core Workshop</a> for instance. The <code>extensions.json</code> file would likely look something like this.</p>
<pre><code class="language-javascript">{
	&quot;recommendations&quot;: [
                &quot;ms-vscode.csharp&quot;,
                &quot;VisualStudioExptTeam.vscodeintellicode&quot;,
                &quot;ms-mssql.mssql&quot;,
                &quot;ms-vscode.azure-account&quot;,
                &quot;ms-azuretools.vscode-azureappservice&quot;,
		&quot;ms-azuretools.vscode-docker&quot;,
                &quot;MS-vsliveshare.vsliveshare-pack&quot;
	]
}
</code></pre>
<ul>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp">C#</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode">Visual Studio Intellicode</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-mssql.mssql">SQL Server</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account">Azure Account</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azureappservice">Azure App Service</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker">Docker</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-pack">VS Live Share Pack</a></li>
</ul>
<h3 id="simpleandclean">Simple and clean</h3>
<p>A small addition to help contributors discover extensions you utilize as well as use to add to the projects you're maintaining, and completely optional.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Deploying WCF and .NET Core applications to a single Kubernetes cluster]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In my <a href="https://tattoocoder.com/modernizing-wcf-services-with-containers-and-visual-studio/">previous post</a>, I showed how to take a WCF service and containerize it using Visual Studio. By doing so, this gives us the opportunity to push our heritage (aka legacy) application to the cloud either in Azure App Service using <a href="https://docs.microsoft.com/en-us/azure/app-service/app-service-web-get-started-windows-container">Web App for Containers</a>, A<a href="https://docs.microsoft.com/en-us/azure/container-instances/?WT.mc_id=none-blog-shboyer">zure Container Instances</a></p>]]></description><link>https://tattoocoder.com/deploy-wcf-and-netcore-apps-kubernetes/</link><guid isPermaLink="false">5e20d712283d3500013a42f3</guid><category><![CDATA[wcf]]></category><category><![CDATA[docker]]></category><category><![CDATA[kubernetes]]></category><category><![CDATA[azure]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Thu, 20 Jun 2019 17:03:02 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2019/06/pablo--10-.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://tattoocoder.com/content/images/2019/06/pablo--10-.png" alt="Deploying WCF and .NET Core applications to a single Kubernetes cluster"><p>In my <a href="https://tattoocoder.com/modernizing-wcf-services-with-containers-and-visual-studio/">previous post</a>, I showed how to take a WCF service and containerize it using Visual Studio. By doing so, this gives us the opportunity to push our heritage (aka legacy) application to the cloud either in Azure App Service using <a href="https://docs.microsoft.com/en-us/azure/app-service/app-service-web-get-started-windows-container">Web App for Containers</a>, A<a href="https://docs.microsoft.com/en-us/azure/container-instances/?WT.mc_id=none-blog-shboyer">zure Container Instances (ACI)</a>, or in the event we need something like an orchestrator Kubernetes is available in <a href="https://docs.microsoft.com/en-us/azure/aks/windows-container-cli?WT.mc_id=none-blog-shboyer">AKS</a>.</p>
<p>Many times we would like to use the new technology with the old. For instance, creating a .NET Core Razor Pages application or .NET Core Web API to consume the WCF application.</p>
<p>However, the new applications will be using Linux containers and everything must be scalable and run in a Kubernetes cluster.</p>
<p>Let's see how we can use AKS with the new Windows Container support to accomplish this!</p>
<h2 id="settingupthewindowsenabledakscluster">Setting up the Windows enabled AKS Cluster</h2>
<p><img src="https://cloudblogs.microsoft.com/uploads/prod/sites/37/2019/03/Kubernetes-Control-Pane-1024x409.png" alt="Deploying WCF and .NET Core applications to a single Kubernetes cluster"></p>
<p>NOTE: <a href="https://docs.microsoft.com/en-us/azure/aks/windows-container-cli">please read related docs</a>, there are some <strong><a href="https://docs.microsoft.com/en-us/azure/aks/windows-container-cli#before-you-begin">Before you begin</a></strong> items that are important to have set up.</p>
<ul>
<li><a href="https://docs.microsoft.com/en-us/azure/aks/windows-container-cli#install-aks-preview-cli-extension">Install the aks-preview CLI Extension</a></li>
<li><a href="https://docs.microsoft.com/en-us/azure/aks/windows-container-cli#register-windows-preview-feature">Register Windows preview feature</a></li>
</ul>
<h3 id="createthecluster">Create the cluster</h3>
<p>A couple of notes here is you must create the cluster using the Azure Network plugin (<a href="https://docs.microsoft.com/en-us/azure/aks/concepts-network#azure-cni-advanced-networking">Azure CNI</a>) as well as a Windows Admin Password for any Windows Server Containers created on the cluster.</p>
<pre><code class="language-console">GROUP=&quot;demo-aks&quot;
CLUSTER_NAME=&quot;demo-cluster&quot;

# user and password needed for the Windows nodes if we create a Windows node pool
PASSWORD_WIN=&quot;P@ssw0rd1234&quot;
USER_WIN=&quot;azureuser&quot;

az group create -l eastus -n $GROUP

#create the aks cluster
az aks create \
    --resource-group $GROUP \
    --name $CLUSTER_NAME \
    --node-count 1 \
    --enable-addons monitoring \
    --kubernetes-version 1.14.0 \
    --generate-ssh-keys \
    --windows-admin-password $PASSWORD_WIN \
    --windows-admin-username $USER_WIN \
    --enable-vmss \
    --network-plugin azure
</code></pre>
<p>The script creates a single node and master controller, all Linux. From here we can now add the Windows node pool for the WCF Service.</p>
<pre><code class="language-console"># create the windows node pool
az aks nodepool add \
    --resource-group $GROUP \
    --cluster-name $CLUSTER_NAME \
    --os-type Windows \
    --name npwin \
    --node-count 1 \
    --kubernetes-version 1.14.0
</code></pre>
<p>After the new Windows node pool is creates, <code>kubectl get nodes</code> shows <code>Ready</code> for deployments.</p>
<pre><code class="language-console">NAME                                STATUS   ROLES   AGE    VERSION
aks-nodepool1-48610275-vmss000000   Ready    agent   10m    v1.14.0
aksnpwin000000                      Ready    agent   110s   v1.14.0
</code></pre>
<h3 id="deploytheapplications">Deploy the applications</h3>
<p>In order for proper deployment to the Windows node pool, specify a <code>nodeSelector</code> in the spec of your chart.</p>
<pre><code class="language-yaml">spec:
      nodeSelector:
        &quot;beta.kubernetes.io/os&quot;: windows
</code></pre>
<p>Here is a sample of the deployment file for the <strong>PeopleService</strong> WCF example I'll use and have already containerized and pushed to my Azure Container Registry.</p>
<blockquote>
<p>When you're using Azure Container Registry (ACR) with Azure Kubernetes Service (AKS), an authentication mechanism needs to be established. See <a href="https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-aks">Authenticate with Azure Container Registry from Azure Kubernetes Service</a> documentation on how to enable.</p>
</blockquote>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
  name: peoplesvc
  labels:
    app: peoplesvc
spec:
  replicas: 1
  template:
    metadata:
      name: peoplesvc
      labels:
        app: peoplesvc
    spec:
      nodeSelector:
        &quot;beta.kubernetes.io/os&quot;: windows
      containers:
      - name: peoplesvc
        image: shayne.azurecr.io/peopleservice:latest
        ports:
          - containerPort: 80
  selector:
    matchLabels:
      app: peoplesvc
---
 apiVersion: v1
 kind: Service
 metadata:
   name: peoplesvc
 spec:
   type: ClusterIP
   externalName: peoplesvc
   ports:
   - protocol: TCP
     port: 80
   selector:
     app: peoplesvc
</code></pre>
<p>The <code>Service</code> type is set to <code>ClusterIP</code> here so only an internal IP is allocated. Next, a .NET Core Razor Pages application is deployed in a Linux container to the Linux pool.</p>
<p>Same is true, container pushed to ACR. Following chart is the deployment file for the web application.</p>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
  name: peopleweb
  labels:
    app: peopleweb
spec:
  replicas: 1
  template:
    metadata:
      name: peopleweb
      labels:
        app: peopleweb
    spec:
      nodeSelector:
        &quot;beta.kubernetes.io/os&quot;: linux
      containers:
      - name: peopleweb
        image: shayne.azurecr.io/peoplewebapp-core:latest
        env:
        - name: &quot;SERVICE_URL&quot;
          value: &quot;peoplesvc&quot;
        ports:
          - containerPort: 80
  selector:
    matchLabels:
      app: peopleweb
---
apiVersion: v1
kind: Service
metadata:
  name: peopleweb
spec:
  type: LoadBalancer
  ports:
  - protocol: TCP
    port: 80
  selector:
    app: peopleweb
</code></pre>
<p>Notable points.</p>
<ul>
<li>ENV variable : <strong>SERVICE_URL</strong> used for the application to communicate with the WCF service. Notice that it is a DNS name.</li>
<li>Service type: <strong>LoadBalance</strong> allocating a public IP address for external access.</li>
</ul>
<p>The web app to service calls via DNS is made possible via Azure virtual network enabled by Azure CNI.<br>
<img src="https://docs.microsoft.com/en-us/azure/aks/media/concepts-network/advanced-networking-diagram.png" alt="Deploying WCF and .NET Core applications to a single Kubernetes cluster"></p>
<p>Deploy the applications, use the following command.</p>
<pre><code class="language-console">kubectl apply -f people.web.yaml -f people.wcf.yaml
</code></pre>
<p>Once the deployment is complete, <code>kubectl get all</code> shows:</p>
<pre><code class="language-console">NAME                             READY   STATUS    RESTARTS   AGE
pod/peoplesvc-7b46dfc9c5-gjwsc   1/1     Running   0          1d
pod/peopleweb-5dbfbf5578-8dqs2   1/1     Running   0          1d

NAME                 TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)        AGE
service/kubernetes   ClusterIP      10.0.0.1      &lt;none&gt;         443/TCP        1d
service/peoplesvc    ClusterIP      10.0.41.1**   &lt;none&gt;         80/TCP         1d
service/peopleweb    LoadBalancer   10.0.81.1**   40.**.52.***   80:31654/TCP   1d

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/peoplesvc   1/1     1            1           1d
deployment.apps/peopleweb   1/1     1            1           1d

NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/peoplesvc-7b46dfc9c5   1         1         1       1d
replicaset.apps/peopleweb-5dbfbf5578   1         1         1       1d
replicaset.apps/peopleweb-794f5b5bb8   0         0         0       1d
</code></pre>
<p>Further details are available in the Kubernetes dashboard via <code>az aks browse --name &lt;clustername&gt; --group &lt;resource-group&gt;</code></p>
<p><img src="https://tattoocoder.com/content/images/2019/06/Screen-Shot-2019-06-20-at-12.05.24-PM.png" alt="Deploying WCF and .NET Core applications to a single Kubernetes cluster"></p>
<p>Browsing to the site <code>https://ipaddress/People</code></p>
<p><img src="https://tattoocoder.com/content/images/2019/06/Screen-Shot-2019-06-20-at-12.07.20-PM.png" alt="Deploying WCF and .NET Core applications to a single Kubernetes cluster"></p>
<h3 id="summary">Summary</h3>
<p>This is a great scenario and solution for anyone looking to use the new technologies while also having an opportunity to move <s>legacy</s> heritage application to the cloud and orchestration the entire architecture. Scaling, DevOps, containers and more cloud native practices are leveraged in new and old.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Modernizing WCF Services with containers and Visual Studio]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>There are a number of reasons for moving long-standing .NET Framework applications like WCF, and ASP.NET Webforms to containers and then into containers or &quot;modernizing <s>legacy</s> heritage apps&quot;.</p>
<ol>
<li>
<p>DevOps - Once the application is set up in a container, build a CI/CD pipeline to build and</p></li></ol>]]></description><link>https://tattoocoder.com/modernizing-wcf-services-with-containers-and-visual-studio/</link><guid isPermaLink="false">5e20d712283d3500013a42f2</guid><category><![CDATA[wcf]]></category><category><![CDATA[docker]]></category><category><![CDATA[azure]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Fri, 14 Jun 2019 19:45:29 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2019/06/pablo--9-.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://tattoocoder.com/content/images/2019/06/pablo--9-.png" alt="Modernizing WCF Services with containers and Visual Studio"><p>There are a number of reasons for moving long-standing .NET Framework applications like WCF, and ASP.NET Webforms to containers and then into containers or &quot;modernizing <s>legacy</s> heritage apps&quot;.</p>
<ol>
<li>
<p>DevOps - Once the application is set up in a container, build a CI/CD pipeline to build and push the applications to the cloud in a streamlined fashion.</p>
</li>
<li>
<p>Velocity - In addition to the CI/CD features, the ability to version the container, ease of deployment and rollback in the event of failures is easier.</p>
</li>
<li>
<p>Leverage other cloud services - Add Application Insights or logging, managed database services, and other PAAS offerings.</p>
</li>
</ol>
<h2 id="wheretostart">Where to start</h2>
<p><a href="https://visualstudio.com">Visual Studio 2019</a> has the Docker tooling built into the workloads. You will need to install <a href="https://docs.docker.com/docker-for-windows/">Docker for Windows</a> and ensure <a href="https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers">Windows Containers</a> are enabled.</p>
<p>Open your WCF application in VS 2019, right-click the project file and select Add -&gt; Docker Support.</p>
<p><img src="https://tattoocoder.com/content/images/2019/06/Screen-Shot-2019-06-11-at-2.36.28-PM.png" alt="Modernizing WCF Services with containers and Visual Studio"></p>
<p>The Docker tooling for Visual Studio will inspect the application and add the appropriate Dockerfile for your application.</p>
<p>In the case of WCF, the following Dockerfile is added to your solution.</p>
<pre><code class="language-docker">FROM mcr.microsoft.com/dotnet/framework/wcf:4.7.2-windowsservercore-ltsc2019
ARG source
WORKDIR /inetpub/wwwroot
COPY ${source:-obj/Docker/publish} .
</code></pre>
<p>Now when you run your application, select &quot;Docker&quot; from the Debug menu and the WCF Test Client will launch and add the container url for the service.</p>
<blockquote>
<p>If the WCF Test Client does not load, be sure to check that the workload is selected in the Visual Studio 2019 Installer.</p>
</blockquote>
<p>Upon looking at the <code>*csproj</code> file, you should see that there are new entries for starting the new container with F5.</p>
<pre><code class="language-xml">&lt;DockerLaunchAction&gt;LaunchWcfTestClient&lt;/DockerLaunchAction&gt;&lt;DockerLaunchUrl&gt;http://{ServiceIPAddress}/MyService.svc&lt;/DockerLaunchUrl&gt;
</code></pre>
<p>The WCF Client will start and add the new container URL endpoint to test against instead of <code>http://localhost...</code>. All of your breakpoints and debugging will now happen within the container as the debugger is attached to the container as opposed to the local machine host.</p>
<h2 id="buildingthedockerimage">Building the Docker Image</h2>
<p>When you click Debug or press F5, the image is built for your application by Visual Studio, after the base image is pulled. This may take some time as this is a Windows Container image and ~1.59 Gb compressed.</p>
<p>If you are familiar with Docker, you're likely to try and use the standard <code>docker build</code> or <code>docker run</code> commands. However, will fail using the command line if the proper MSBuild command is not run to produce the appropriate output.</p>
<p>We have to build the WCF application first either using Visual Studio or MSBuild. The Docker tooling for VS, actually runs an MSBuild command behind the scenes to create the <code>obj/Docker/publish</code> folder, compile the app and copy the output there prior to running the <code>docker run</code> command.</p>
<p>This is important in the event we move to a DevOps scenario. The command need to run on the command line and in Azure DevOps is:</p>
<pre><code class="language-console">msbuild /t:ContainerBuild /p:Configuration=Release
</code></pre>
<h3 id="pushingtheimagetoaregistry">Pushing the image to a registry</h3>
<p>Give a project name i.e. <code>hellowcf</code> will produce a docker image named <code>hellowcf:latest</code>. From here, you may want to <strong>tag</strong> the image with an appropriate version number, or other identifier prior to pushing it to a registry.</p>
<p>For example, tagging with a <strong>buildId</strong> and pushing it to an Azure Container registry.</p>
<pre><code class="language-console">docker tag hellowcf:latest myregistry.azure.cr/hellowcf:1234

docker push myregistry.azure.cr/hellowcf:1234
</code></pre>
<h3 id="usingvisualstudio">Using Visual Studio</h3>
<p>Visual Studio has a rich UI for publishing your applications and with containers, the same is true.</p>
<p>The publish dialog has options for <a href="https://docs.microsoft.com/en-us/visualstudio/containers/hosting-web-apps-in-docker?view=vs-2019">deploying to a container registry (Azure Container Registry, Docker Hub, Custom)</a> or <a href="https://docs.microsoft.com/en-us/visualstudio/containers/deploy-app-service?view=vs-2019">deploying the built container image direct to Azure App Service</a> right from the UI.</p>
<p><img src="https://docs.microsoft.com/en-us/visualstudio/containers/media/hosting-web-apps-in-docker/vs-acr-provisioning-dialog.png?view=vs-2019" alt="Modernizing WCF Services with containers and Visual Studio"></p>
<h2 id="publishingtheapplication">Publishing the application</h2>
<p>In this scenario, a WCF application was used however it could as easily have been an ASP.NET WebForms app or a console service.</p>
<p>For the WCF app, Windows Containers on AppService is a great first step and if you have a number of components to your architecture that is needing to spin up at once; AKS - <a href="https://docs.microsoft.com/en-us/azure/aks/windows-container-cli">Azure Kubernetes Service</a> now supports Windows Containers as well.</p>
<p>Console apps or services that run once and while, or on timers to perform work is when a service like <a href="https://docs.microsoft.com/en-us/azure/container-instances/">Azure Container instances</a> is a great fit.</p>
<p>The point here is getting your long-standing and stable applications into a container without re-writing or re-architecting the solution and still take advantage of cloud native type practices.</p>
<h2 id="additionalreading">Additional Reading</h2>
<p><a href="https://docs.microsoft.com/en-us/dotnet/standard/modernize-with-azure-and-containers/modernize-existing-apps-to-cloud-optimized/deploy-existing-net-apps-as-windows-containers">Deploying Existing .NET Apps as Windows Containers</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Build the code, thank the contributors!]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The <a href="https://github.blog/2019-05-23-building-an-interconnected-community-together/">GitHub event</a> announced a great new feature - GitHub Sponsors. <a href="https://github.com/sponsors">GitHub Sponsors</a> is a new way to financially support the developers who build the open source software you use every day. See the <a href="https://tattoocoder.com/build-the-code-thank-the-contributors/(https://github.blog/2019-05-23-announcing-github-sponsors-a-new-way-to-contribute-to-open-source/)">full announcement blog post</a> for more information.</p>
<h4 id="recognizingcontributors">Recognizing Contributors</h4>
<p>Recently, <a href="https://twitter.com/_clarkio">Brian Clark</a> introduced me to <strong>all-contributors</strong></p>]]></description><link>https://tattoocoder.com/build-the-code-thank-the-contributors/</link><guid isPermaLink="false">5e20d712283d3500013a42f1</guid><category><![CDATA[github]]></category><category><![CDATA[community]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Fri, 24 May 2019 01:53:51 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2019/05/bit_octocat.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://tattoocoder.com/content/images/2019/05/bit_octocat.png" alt="Build the code, thank the contributors!"><p>The <a href="https://github.blog/2019-05-23-building-an-interconnected-community-together/">GitHub event</a> announced a great new feature - GitHub Sponsors. <a href="https://github.com/sponsors">GitHub Sponsors</a> is a new way to financially support the developers who build the open source software you use every day. See the <a href="https://tattoocoder.com/build-the-code-thank-the-contributors/(https://github.blog/2019-05-23-announcing-github-sponsors-a-new-way-to-contribute-to-open-source/)">full announcement blog post</a> for more information.</p>
<h4 id="recognizingcontributors">Recognizing Contributors</h4>
<p>Recently, <a href="https://twitter.com/_clarkio">Brian Clark</a> introduced me to <strong>all-contributors</strong> (<a href="https://github.com/all-contributors/all-contributors">https://github.com/all-contributors/all-contributors</a>) an awesome way to recognize contributors to your project.</p>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-23-at-9.52.10-PM.png" alt="Build the code, thank the contributors!"></p>
<p>The <a href="https://allcontributors.org/docs/en/bot/installation">installation</a> is super easy. Enable the bot on your repository, and you're ready to go.</p>
<blockquote>
<p>Good practice is to have a CONTRIBUTING.md in your repo not only to encourage good practices but to also set expectations and standards.</p>
</blockquote>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-23-at-9.29.05-PM.png" alt="Build the code, thank the contributors!"></p>
<p><strong>Adding contributors</strong></p>
<p>There are a few ways in which our contributors get added to the table on the README.</p>
<p>First, this is a go forward bot for contributions/commits; therefore they are added as commits happen.</p>
<p>For other ad-hoc acknowledgments, you may comment on a PR or Issue.</p>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-23-at-9.43.59-PM.png" alt="Build the code, thank the contributors!"></p>
<p>The comment may also be a bit more intentional. Per the docs, it uses <a href="https://github.com/all-contributors/all-contributors-bot/blob/master/src/tasks/processIssueComment/utils/parse-comment/index.js">basic Natural Language Processing</a>.</p>
<p>Here, I added <a href="https://twitter.com/jenlooper">Jen Looper</a> for her design work.</p>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-23-at-9.39.41-PM.png" alt="Build the code, thank the contributors!"></p>
<p>In either case, a PR is opened to add the user/contributor to the <strong>README</strong> and <strong>.all-contributorsrc</strong> files for the attributions.</p>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-23-at-9.43.27-PM.png" alt="Build the code, thank the contributors!"></p>
<p>Building community through code is at the heart of GitHub, but being a good human through good manners is the first step to continuing that effort. Say thank you to your contributors. It takes a few moments, they will thank you with more commits.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Auto blogging Jekyll with Logic Apps, ACI Containers and .NET Core]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>All related links: <a href="https://www.theurlist.com/autobloggerpost">https://www.theurlist.com/autobloggerpost</a></p>
<p>Jekyll is a very popular way to host a static site on GitHub and posting new content is a simple as creating a markdown file and then committing it to the relative repo. GitHub takes care of the rest.</p>
<blockquote>
<p>See the help</p></blockquote>]]></description><link>https://tattoocoder.com/auto-blogging-jekyll-with-logic-apps-aci-containers-and-net-core/</link><guid isPermaLink="false">5e20d712283d3500013a42f0</guid><category><![CDATA[docker]]></category><category><![CDATA[azure]]></category><category><![CDATA[containers]]></category><category><![CDATA[dotnetcore]]></category><category><![CDATA[logicapps]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Thu, 16 May 2019 21:51:51 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>All related links: <a href="https://www.theurlist.com/autobloggerpost">https://www.theurlist.com/autobloggerpost</a></p>
<p>Jekyll is a very popular way to host a static site on GitHub and posting new content is a simple as creating a markdown file and then committing it to the relative repo. GitHub takes care of the rest.</p>
<blockquote>
<p>See the help pages at GitHub -&gt; <a href="https://help.github.com/en/articles/setting-up-your-github-pages-site-locally-with-jekyll">Setting up your GitHub Pages site locally with Jekyll</a></p>
</blockquote>
<p>This seemed like a great way for me to get started on a blog for some content that was being stored in a CMS. The view we are interested in is updated once a week and is accessible via <a href="https://docs.microsoft.com/en-us/dotnet/standard/net-standard">.NET Standard</a> API.</p>
<p>There are a few options for making this happen. I could write a console application and execute it once a week to produce the file, then run through the <code>git</code> commands myself. Why would I do that?</p>
<h4 id="whatarewedoing">What are we doing</h4>
<p>Every Monday a new post must be created for the blog. instead of running the process manually using</p>
<pre><code class="language-console">dotnet run myapp
git add newfile.md
git commit -m 'add new file'
git push
</code></pre>
<p>I wanted to completely automate the process. Using Docker, <a href="https://docs.microsoft.com/en-us/azure/logic-apps/">Logic Apps</a>, and <a href="https://docs.microsoft.com/en-us/azure/container-instances/">Azure Container Instances (ACI)</a>; managing the when to &quot;start, stop and clean up&quot; was pretty easy. However, there isn't a full GitHub connector in Logic Apps for performing the commands in git. So, I added <code>git</code> to my container and a <strong>startup.sh</strong> script to get this done.</p>
<ul>
<li><a href="https://docs.microsoft.com/en-us/azure/logic-apps/">Logic Apps</a> kicks off the process every Monday at 10:30 AM</li>
<li><a href="https://docs.microsoft.com/en-us/azure/container-instances/">ACI Container Image</a> runs <a href="https://dot.net">.NET Core</a> Application
<ul>
<li>Clones repo</li>
<li>Calls CMS API for new data</li>
<li>Produces new Markdown file</li>
<li>Git commit, add, push</li>
</ul>
</li>
<li>Logic App removes ACI Container</li>
<li>GitHub CI/CD runs to update the blog with new content</li>
<li>Logic App emails me
<ul>
<li>Email contains logs for the container (git output)</li>
<li>Asks for approval to Tweet announcement of new content</li>
</ul>
</li>
<li>Logic App send new Tweet</li>
</ul>
<h4 id="detailshowwasitdone">Details, how was it done?</h4>
<p>We will use the following components to build our Jekyll &quot;autoblogger&quot;.</p>
<p><strong>Docker container</strong></p>
<p>Let's start with the container. It looks like an atypical <a href="https://dot.net">.NET Core</a> 2.2 image with the exception that <code>git-core</code> is installed in the final image.</p>
<pre><code class="language-docker">FROM mcr.microsoft.com/dotnet/core/sdk:2.2 as build-env
WORKDIR /app

COPY autoblog/*.csproj ./
RUN dotnet restore

COPY ./autoblog ./
RUN dotnet publish -c Release -o out

# FINAL IMAGE
FROM mcr.microsoft.com/dotnet/core/runtime:2.2
WORKDIR /app
COPY --from=build-env /app/out .

# install git
RUN apt-get update &amp;&amp; \
  apt-get upgrade -y &amp;&amp; \
  apt-get install -y git-core

COPY ./autoblog/startup.sh .
RUN chmod 777 startup.sh
ENTRYPOINT [&quot;/bin/bash&quot;, &quot;./startup.sh&quot;]
</code></pre>
<p>The <code>startup.sh</code> file is where the <em>magic</em> happens. When the container starts, we first configure git to use the deployment key stored as an environment variable ($token), clone the source repo into our working directory and re-init the repo (might be a bug only works if we do this).</p>
<p>Last, set the git user/email for any commits and then start the .NET Core console app.</p>
<pre><code class="language-console"># ensure the git deploy token is used for commits
git config --global url.&quot;https://$token:@github.com/&quot;.insteadOf &quot;https://github.com/&quot;

# clone the source repository
git clone $source /app/$dir

# bug? must re-init the repo
# set the git user/email for commits
cd /app/$dir &amp;&amp; \
  git init &amp;&amp; \
  git config --global user.email &quot;$email&quot; &amp;&amp; \
  git config --global user.name &quot;$user&quot;

# run the process for creating new entry
dotnet /app/autoblog.dll
</code></pre>
<p>All of the ENV variables are set when the ACI container is started using the Logic App</p>
<p><strong>.NET Core Application</strong></p>
<p>The console application running inside of the container which creates the formatted markdown page, git commits and pushes to the repo.</p>
<p>Here is the <code>Main()</code> paraphrased code.</p>
<pre><code class="language-csharp"> static async Task Main(string[] args)
 {

   var root = $&quot;/app/{Environment.GetEnvironmentVariable(&quot;dir&quot;)}&quot;;

   if (!Directory.Exists(root))
   {
     Directory.CreateDirectory(root);
   }

   var output = new System.Text.StringBuilder();
   output.AppendLine(Bash($&quot;git -C {root} pull&quot;));

   await GetContentRepositoryItemsAsync();

   var creator = new Creator.Post(ContentItems);
   try
   {
      var fileContents = await creator.Create();
      await File.WriteAllTextAsync(creator.FileName, fileContents);
   }
    catch (Exception ex)
   {
    Console.WriteLine(ex.ToString());
    throw ex;
   }

   output.AppendLine(Bash($&quot;git add .&quot;));
   output.AppendLine(Bash($&quot;git commit -m '{creator.FileName} added'&quot;));
   output.AppendLine(Bash(&quot;git push&quot;));

   Console.WriteLine(output.ToString());
 }
</code></pre>
<p>The <code>Creator</code> class produces the file and once complete, we execute the git commands to push the newly created file the repo.</p>
<p><strong>Azure Logic App</strong></p>
<p><a href="https://docs.microsoft.com/en-us/azure/logic-apps/">Azure Logic Apps</a> enables the creation of powerful business workflows by integrating connectors for various services into a single graphical interface. With the connector for Azure Container Instances, you can run containerized applications as part of your Logic Apps workflow.</p>
<blockquote>
<p><a href="https://docs.microsoft.com/azure/container-instances/">Azure Container Instances (ACI)</a> is the easiest way to run containers in Azure. We can use it to run containers without worrying about provisioning infrastructure and we only pay for resources that are used.</p>
</blockquote>
<p>In this case, we need to run the process every Monday at a set time to start the container process.</p>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-16-at-5.09.54-PM.png" alt="logic app overview"></p>
<p>The container image is built and stored in my private Azure Container Registry and is easily configured in the &quot;Create container group&quot; connector.</p>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-16-at-5.16.09-PM.png" alt="logic app image1"></p>
<p>The needed ENVIRONMENT variables can be configured here as well. Another option is to use the <a href="https://docs.microsoft.com/en-us/azure/key-vault/">Azure Key Vault</a> Connector to share and secure secret keys across apps.</p>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-16-at-5.16.09-PM-1.png" alt="logic app image ENV"></p>
<p>Next, a variable <code>complete</code> is set to hold the status of the container. The <code>Until</code> task will run <em>until</em> the state of the container is <strong>Succeeded</strong> and <code>complete</code> is <strong>true</strong>. If false, we add a <code>Delay</code> task of 10 seconds.</p>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-16-at-5.23.51-PM.png" alt="logic app image condition"></p>
<p>If the container group returns <strong>Succeeded</strong>, the logs are retrieved, the container group is cleaned up and an email approval is sent for the tweet.</p>
<p><img src="https://tattoocoder.com/content/images/2019/05/Screen-Shot-2019-05-16-at-5.24.57-PM.png" alt="logic app true"></p>
<h3 id="wrappingup">Wrapping up</h3>
<p><a href="https://docs.microsoft.com/en-us/azure/logic-apps/">Azure Logic Apps</a> is a fun productive way to build process flows and in this case, I was able to produce content using a code, containers and approval process without having any manual steps.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[dotnet-azure : A .NET Core global tool to deploy an application to Azure in one command]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://tattoocoder.com/content/images/2019/04/dotnet-azure-new-web-1.gif" alt="dotnet-azure-new-web"></p>
<p>The options for pushing your .NET Core application to the cloud are not lacking depending on what IDE or editor you have in front of you.</p>
<p><a href="https://visualstudio.microsoft.com/downloads/">Visual Studio</a> has a rich GUI interface with choices to pick pursuant to the architecture of your app - Web, Containers, SQL Server, Registries,</p>]]></description><link>https://tattoocoder.com/dotnet-azure-a-net-core-global-tool-to-deploy-an-application-to-azure-in-one-command/</link><guid isPermaLink="false">5e20d712283d3500013a42ef</guid><category><![CDATA[azure]]></category><category><![CDATA[dotnetcore]]></category><category><![CDATA[globaltools]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Fri, 19 Apr 2019 15:23:15 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><img src="https://tattoocoder.com/content/images/2019/04/dotnet-azure-new-web-1.gif" alt="dotnet-azure-new-web"></p>
<p>The options for pushing your .NET Core application to the cloud are not lacking depending on what IDE or editor you have in front of you.</p>
<p><a href="https://visualstudio.microsoft.com/downloads/">Visual Studio</a> has a rich GUI interface with choices to pick pursuant to the architecture of your app - Web, Containers, SQL Server, Registries, etc.; and for years has excelled at delivering a full experience.</p>
<p><a href="https://code.visualstudio.com">VS Code</a> offers a great Azure extension pack and in its own fashion delivers an experience to publish your web application directly to an AppService, Container and/or Registry too.</p>
<p>If the command line experience is more your &quot;thing&quot;, the <a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest">Azure CLI</a> is available and any resource publish option can be had through the <code>az</code> command.</p>
<p>But what if you just wanted to <code>deploy</code> your application to Azure with a single command?</p>
<h2 id="installation">Installation</h2>
<p><strong>dotnet-azure</strong> is a .NET Core global tool and available via NuGet. To install run the following command.</p>
<pre><code class="language-console">dotnet tool install dotnet-azure --global
</code></pre>
<p><em>Requirements - An Azure account is required, get one for <a href="https://aka.ms/dotnet-azure">FREE</a> at <a href="https://aka.ms/dotnet-azure">https://aka.ms/dotnet-azure</a></em></p>
<h2 id="usage">Usage</h2>
<p>Each command has a <code>-h|--help</code> option available.</p>
<p><code>dotnet azure -h|--help</code></p>
<h3 id="help">help</h3>
<pre><code class="language-console">Usage: dotnet-azure [options] [command]

Options:
  -?|-h|--help  Show help information

Commands:
  deploy        Deploy application to Azure App Service. Options are used for [NEW] application deployments only.
  login         Login into Azure
</code></pre>
<h3 id="login">login</h3>
<p>Run <code>login</code> command first to authenticate against your Azure account. You'll be prompted to use a code and URL to authenticate.</p>
<p><code>dotnet azure login</code></p>
<pre><code class="language-console">To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate.
</code></pre>
<h3 id="deploy">deploy</h3>
<p>Use defaults, random generated application and resource group name. The current directory is assumed for application for deployment.</p>
<h4 id="examples">Examples</h4>
<pre><code class="language-console">dotnet azure deploy
</code></pre>
<p>Pass project folder.</p>
<pre><code class="language-console">dotnet azure deploy \mynewproject
</code></pre>
<p>Pass all options.</p>
<pre><code class="language-console">dotnet azure deploy --location westus --name fancywebapp --group fancywebgroup --plan BasicB1
</code></pre>
<p>Short hand for <code>location</code>, <code>name</code>, and <code>group</code></p>
<pre><code class="language-console">dotnet azure deploy -l eastus2 -n fancywebapp -g fancygroup
</code></pre>
<p>Full help output for <strong>deploy</strong> command.</p>
<pre><code class="language-console">Deploy an application to Azure App Service. Options are used for [NEW] application deployments only.

Usage: dotnet-azure deploy [arguments] [options]

Arguments:
  AppPath

Options:
  -?|-h|--help                       Show help information
  -n|--name &lt;APP_NAME&gt;               Name of application, must be unique.
  -l|--location &lt;LOCATION&gt;           Region or location of app deployment. (eastus, westus, etc.)
  -g|--group &lt;RESOURCE_GROUP&gt;        Resource group name to create and use for deployment.
  -p|--plan &lt;APP_SERVICE_PLAN_TYPE&gt;  Type of App Service Plan to create for application. Options (BasicB1, SharedD1, FreeF1, PremiumP1 - more info https://aka.ms/azure-appserviceplans )
</code></pre>
<h2 id="whatsnext">What's Next?</h2>
<p>Install it, provide feedback. Have ideas, contribute. Is this a good thing? Let me know <a href="https://twitter.com/spboyer">@spboyer</a></p>
<ul>
<li>Github : <a href="https://github.com/spboyer/dotnet-azure">https://github.com/spboyer/dotnet-azure</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Finding your next .NET Open Source project using the command line]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Many years ago I wanted to jump into a project in open source but had no idea where to start. I had worked with node.js, .NET and some other web-based technology but wasn't sure where to start and GitHub was new to me. Ironically, I fell onto Omnisharp and</p>]]></description><link>https://tattoocoder.com/finding-your-next-net-open-source-project-using-the-command-line/</link><guid isPermaLink="false">5e20d712283d3500013a42ee</guid><category><![CDATA[dotnet]]></category><category><![CDATA[dotnet-cli]]></category><category><![CDATA[globaltools]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Mon, 10 Dec 2018 19:26:15 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2018/12/pablo--8-.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://tattoocoder.com/content/images/2018/12/pablo--8-.png" alt="Finding your next .NET Open Source project using the command line"><p>Many years ago I wanted to jump into a project in open source but had no idea where to start. I had worked with node.js, .NET and some other web-based technology but wasn't sure where to start and GitHub was new to me. Ironically, I fell onto Omnisharp and the .NET Core <code>yo aspnet</code> projects through my Microsoft MVP Summit meetings that year.</p>
<p>Flicking through Twitter, as one does, I came across an announcement from a friend Tierny (<a href="https://twitter.com/bitandbang">@bitandbang</a>) where he had started a CLI tool for node.js projects called &quot;<a href="https://github.com/bnb/good-first-issue">good-first-issue</a>&quot; to find random GitHub Issues for projects submitted to his tool.</p>
<p>There are a ton of open source projects asking for help on issues that have a low barrier to entry. These issues are typically tagged or labeled with <strong>good-first-issue</strong>, <strong>up-for-grabs</strong>, <strong>helpwanted</strong>, etc. Finding them can be hard, a good start is <a href="https://up-for-grabs.net">https://up-for-grabs.net</a> .</p>
<h3 id="upforgrabsnet">up-for-grabs.net</h3>
<p>There are over 700 projects currently available <a href="https://up-for-grabs.net">on the site</a>. Everything from C++, Java, TypeScript, Ruby, Django, Go and more is available in the filters.</p>
<p>If you have a project and are looking for help get it added by submitting your own project(s) via their GitHub - <a href="https://github.com/up-for-grabs/up-for-grabs.net">https://github.com/up-for-grabs/up-for-grabs.net</a>. There is even a yeoman generator for getting the yaml correct - <code>yo up-for-grabs</code>.</p>
<h3 id="upforgrabsnetprojects">upforgrabs - .NET Projects</h3>
<p>As a .NET developer, I wanted to create something like Tierny had, so I went the <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools-how-to-create">global tool</a> route.</p>
<p>Using the latest <a href="http://dot.net/download">.NET Core 2.2 SDK</a>, created <strong>upforgrabs</strong>.</p>
<p><strong>Install it now</strong>  <code>dotnet tool install -g upforgrabs</code><br>
<br><a href="https://github.com/spboyer/upforgrabs">https://github.com/spboyer/upforgrabs</a></p>
<p><img src="https://tattoocoder.com/content/images/2018/12/examples.gif" alt="Finding your next .NET Open Source project using the command line"></p>
<p>The source of the data is, in fact, the same project list from <a href="https://up-for-grabs.net">https://up-for-grabs.net</a>, which is filtered specifically to .NET type projects.</p>
<h3 id="gettingthedata">Getting the data</h3>
<p>Each project for the site is stored in a yaml file under <code>up-for-grabs.net/_data/projects/</code>. However consuming 700 or so yaml files, filtering, etc. on every call from a console app is not very efficient.</p>
<p>The solution, Docker and <a href="https://docs.microsoft.com/en-us/azure/container-instances/container-instances-overview">Azure Container Instances</a>. Here I used a .NET Core Alpine Linux container and installed Subversion.</p>
<p>Why Subversion? GitHub does not have a way to get a specific folder from a repository. Using Subversion I downloaded the <code>/projects</code> folder to process all the files.</p>
<pre><code class="language-console"># install subversion for alpine
RUN apk --no-cache add subversion
# download the data for projects
RUN svn export https://github.com/up-for-grabs/up-for-grabs.net/trunk/_data/projects data
</code></pre>
<p>Once the yaml is downloaded, using Newtonsoft.JSON, they are combined and converted to a single <strong>project.json</strong> file.</p>
<pre><code class="language-csharp">var files = from file in Directory.EnumerateFiles(@&quot;data&quot;, &quot;*.yml&quot;, SearchOption.AllDirectories)
                  select new
                  {
                    File = file,
                    Lines = File.ReadAllText(file)
                  };

      Console.WriteLine(&quot;Processing files...&quot;);
      foreach (var f in files)
      {
        //Console.WriteLine(&quot;Processing &quot; + f.File);
        try
        {
          var deserializer = new Deserializer();
          var content = new StringReader(f.Lines);
          var yamlObject = deserializer.Deserialize&lt;Project&gt;(content);

          result.Add(yamlObject);
        }
        catch (Exception ex)
        {
          errors.Add(new Error() { name = f.File, info = ex.Message, exception = ex.Source });
          continue;
        }
      }

      JsonSerializer serializer = new JsonSerializer();
      using (StreamWriter sw = new StreamWriter(outputPath))
      using (JsonWriter writer = new JsonTextWriter(sw))
      {
        serializer.Serialize(writer, result);
      }

      PostFile(outputPath).Wait();
    }
</code></pre>
<p><strong>PostFile()</strong> writes the final file to an Azure CDN using the <a href="https://docs.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-dotnet?tabs=linux">Azure SDK</a>.</p>
<blockquote>
<p>See my previous post on using an <a href="https://tattoocoder.com/use-serverless-functions-and-cdn-to-speed-up-api-data-calls/">Azure CDN and serverless</a> to speed up API calls.</p>
</blockquote>
<pre><code class="language-csharp">private static async Task PostFile(string file)
    {
      CloudStorageAccount storageAccount;
      CloudBlobContainer cloudBlobContainer;

      string storageConnectionString = Environment.GetEnvironmentVariable(&quot;storageconnectionstring&quot;);
      if (CloudStorageAccount.TryParse(storageConnectionString, out storageAccount))
      {
        try
        {
          // Create the CloudBlobClient that represents the Blob storage endpoint for the storage account.
          Console.WriteLine(&quot;Checking for/creating blob container&quot;);
          CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
          cloudBlobContainer = cloudBlobClient.GetContainerReference(&quot;up-for-grabs&quot;);
          await cloudBlobContainer.CreateIfNotExistsAsync();

          // Set the permissions so the blobs are public.
          BlobContainerPermissions permissions = new BlobContainerPermissions
          {
            PublicAccess = BlobContainerPublicAccessType.Blob
          };
          await cloudBlobContainer.SetPermissionsAsync(permissions);

          Console.WriteLine(&quot;Pushing to CDN&quot;);
          CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(&quot;projects.json&quot;);
          cloudBlockBlob.Properties.ContentType = &quot;application/json&quot;;

          await cloudBlockBlob.UploadFromFileAsync(file);

        }
        catch (StorageException ex)
        {
          Console.WriteLine(&quot;Error returned from the service: {0}&quot;, ex.Message);
        }
        finally
        {
          Console.WriteLine(&quot;Process complete.&quot;);
        }
      }
    }
  }
</code></pre>
<h3 id="keepingitfreshwazuredevops">Keeping it Fresh w/ Azure DevOps</h3>
<p>In order to keep the <strong>project.json</strong> feed up to date, I set up a scheduled build using <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/languages/dotnet-core?view=vsts&amp;tabs=yaml">Azure Devops</a> and Container Instances.</p>
<ul>
<li>Runs nightly</li>
<li>Builds the container, getting the new YAML data</li>
<li>Pushes to Azure Container Registry</li>
<li>Runs the container in Container Instances, pushing the json file to the CDN</li>
<li>Destroys the Container Instance ensuring only runtime billing.</li>
</ul>
<p>Here is the build pipeline YAML</p>
<pre><code class="language-yaml">resources:
- repo: self
queue:
  name: Hosted Ubuntu 1604
steps:
- task: Docker@1
  displayName: 'Build Docker Image'
  inputs:
    azureSubscriptionEndpoint: 'shboyer (5ca082f3-***)'
    azureContainerRegistry: shayne.azurecr.io
    arguments: '--no-cache'
    imageName: 'up-for-grabs-feed:$(Build.BuildId)'
    includeLatestTag: true

- task: Docker@1
  displayName: 'Push to ACR'
  inputs:
    azureSubscriptionEndpoint: 'shboyer (5ca082f3-***)'
    azureContainerRegistry: shayne.azurecr.io
    command: 'Push an image'
    imageName: 'up-for-grabs-feed:$(Build.BuildId)'
</code></pre>
<p>Upon successful build, the Release Pipeline executes. This has the Start/Destroy of the ACI Container.</p>
<pre><code class="language-console">az container create \
    --resource-group up-for-grabs \
    --name firsttimersfeed \
    --image $(acrLoginServer)/up-for-grabs-feed:$(Release.Artifacts._up-for-grabs-feed.BuildId) \
    --dns-name-label up-for-grabs-feed \
    --restart-policy OnFailure \
    --registry-login-server $(acrLoginServer) \
    --registry-username $(acrName) \
    --registry-password $(acrPassword) \
    -e 'storageconnectionstring'='$(storageconnectionstring)'
</code></pre>
<p>Cleanup of the container</p>
<pre><code class="language-console">az container delete -n firsttimersfeed -g up-for-grabs -y
</code></pre>
<p>The repository for the &quot;feed project&quot; is available here - <a href="https://github.com/spboyer/up-for-grabs-feed">https://github.com/spboyer/up-for-grabs-feed</a>.</p>
<h3 id="feedback">Feedback</h3>
<p>There are more than 290 .NET open source projects currently in the list. If you're looking for a new project to get into, this is an easy way to get there.</p>
<p>Open a command line and type <code>upforgrabs</code>.</p>
<p>Let me know what you think!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Using ASP.NET Core with MongoDB in containers for local dev, CosmosDB for production]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>If nothing else is true, containers have made local development on a platform so much easier. If you want to use SQL Server for your backend just <code>docker pull microsoft/mssql-server-linux</code> and you can start up an instance with a few parameters.</p>
<p><a href="https://docs.microsoft.com/en-us/azure/cosmos-db/">Azure CosmosDB </a>is not available as a container,</p>]]></description><link>https://tattoocoder.com/using-asp-net-core-with-mongodb-in-containers-for-local-dev-cosmosdb-for-production/</link><guid isPermaLink="false">5e20d712283d3500013a42ed</guid><category><![CDATA[azure]]></category><category><![CDATA[mongodb]]></category><category><![CDATA[cosmosdb]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Thu, 18 Oct 2018 19:08:22 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-18-at-3.07.47-PM.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-18-at-3.07.47-PM.png" alt="Using ASP.NET Core with MongoDB in containers for local dev, CosmosDB for production"><p>If nothing else is true, containers have made local development on a platform so much easier. If you want to use SQL Server for your backend just <code>docker pull microsoft/mssql-server-linux</code> and you can start up an instance with a few parameters.</p>
<p><a href="https://docs.microsoft.com/en-us/azure/cosmos-db/">Azure CosmosDB </a>is not available as a container, however, MongoDB is available and happens to be a database I have used in previous applications. <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-introduction">MongoDB is one of the many APIs that CosmosDB supports</a>; locally I can develop against an instance of Mongo either in a container or installed and simply change the connection string for my production instance.</p>
<p>The flexibility of being able to use MongoDB and then just changing a connection string to use CosmosDB is a nice capability if you have exisiting applications that are using Mongo and you are looking for the globally scalable and features that CosmosDB offers.</p>
<blockquote>
<p>If you need to <strong>migrate data</strong> from MongoDB applications to CosmosDB <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-migrate">see this doc for the steps</a>.</p>
</blockquote>
<h3 id="creatingthedatabases">Creating the Databases</h3>
<p>For MongoDB locally, using Docker is super simple. Run <code>docker pull mongo</code>, and now you can use this in your application.</p>
<pre><code class="language-console">docker run --name mongo mongo
</code></pre>
<p>Visual Studio Code has a CosmosDB extension as a part of the <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-azureextensionpack">Azure Extension pack</a> that allows you to interact with Mongo Databases as well as CosmosDB instances.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-18-at-2.38.22-PM.png" alt="Using ASP.NET Core with MongoDB in containers for local dev, CosmosDB for production"></p>
<p>This extension also allows you to create your CosmosDB instance right from VS Code, or you can create it in the Azure portal or even using the <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/cli-samples">Azure CLI</a>.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-18-at-2.41.22-PM.png" alt="Using ASP.NET Core with MongoDB in containers for local dev, CosmosDB for production"></p>
<p>However you like to create the instance, it can all happen in the same tool and that's awesome for me.</p>
<h3 id="localdevelopment">Local Development</h3>
<p>The app is a basic <a href="https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-2.1&amp;tabs=visual-studio-code">ASP.NET Core Razor Pages</a> application which list &quot;Running Races&quot; that have been reviewed.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-18-at-1.58.52-PM.png" alt="Using ASP.NET Core with MongoDB in containers for local dev, CosmosDB for production"></p>
<p>Both the app and the database are set to use containers and docker-compose to orchestrate them.</p>
<p><strong>Application Dockerfile</strong></p>
<pre><code class="language-docker">FROM microsoft/dotnet:2.1.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 443

FROM microsoft/dotnet:2.1.403-sdk AS build
WORKDIR /src
COPY runracereview.csproj .
RUN dotnet restore
COPY . .
WORKDIR /src
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT [&quot;dotnet&quot;, &quot;runracereview.dll&quot;]
</code></pre>
<p><strong>docker-compose</strong></p>
<pre><code class="language-docker">version: &quot;3&quot;
services:
  runracreview:
    container_name: runracereview
    restart: always
    build:
      context: ./runracereview
      dockerfile: Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://+:80
    ports:
      - &quot;57270:80&quot;
      - &quot;44348:443&quot;
    volumes:
      - ${HOME}/.microsoft/usersecrets/:/root/.microsoft/usersecrets
      - ${HOME}/.aspnet/https:/root/.aspnet/https/
    links:
      - mongo
  mongo:
    container_name: mongo
    image: mongo
    volumes:
      - ${WEBAPP_STORAGE_HOME}/site:/data/db
      #- ./data:/data/db
    ports:
      - &quot;27017:27017&quot;
</code></pre>
<p>Notice that in the compose file that the <strong>mongo</strong> image has a volume mapped to <code>${WEBAPP_STORAGE_HOME}/site:/data/db</code>, this is done to persist the test data locally as to not reload the data everytime the container is spun up.</p>
<blockquote>
<p>Check out the Microsoft Learn course : <a href="https://docs.microsoft.com/en-us/learn/modules/build-cosmos-db-app-with-vscode/">Build a .NET Core app for Azure Cosmos DB in Visual Studio Code</a> - <strong>FREE</strong></p>
</blockquote>
<h4 id="settinguptheapp">Setting up the app</h4>
<p>Getting the connection to the database are done using the Configuration settings base on the Environment.</p>
<p>In <strong>appsettings.Development.json</strong>, the configuration for Mongo is added, and for Production, the CosmosDB connection string is set in <strong>appsettings.Production.json</strong>. The <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1">ConfigurationBuilder</a> loads the appropriate file based on the environment.</p>
<pre><code class="language-javascript">  &quot;MongoDB&quot;: {
    &quot;ConnectionString&quot;: &quot;mongodb://localhost:27017&quot;,
    &quot;Container&quot; : &quot;mongodb://mongo:27017&quot;,
    &quot;Database&quot;: &quot;Races&quot;
  },
</code></pre>
<p><strong>Startup.cs</strong> configures the <strong>Settings</strong> options.</p>
<pre><code class="language-csharp"> services.Configure&lt;Settings&gt;(
      options =&gt;
      {
        options.ConnectionString = Configuration.GetSection(&quot;MongoDb:ConnectionString&quot;).Value;
        options.Database = Configuration.GetSection(&quot;MongoDb:Database&quot;).Value;
        options.Container = Configuration.GetSection(&quot;MongoDb:Container&quot;).Value;
        options.IsContained = Configuration[&quot;DOTNET_RUNNING_IN_CONTAINER&quot;] != null;
      });
</code></pre>
<blockquote>
<p>If you are running .NET Core applications in a container you can inspect the Environment variable <code>DOTNET_RUNNING_IN_CONTAINER</code> to determine if this is true.</p>
</blockquote>
<p>If the application is running in a container and in Development then the <a href="https://github.com/spboyer/runracereview/blob/master/runracereview/Settings.cs#L13">Settings class</a> returns the proper connection string for the container.</p>
<h3 id="simplebut">Simple but ...</h3>
<p>Being able to work locally and iterate on a simple set of data without having to hit the production data constantly, or be concerned with the <strong>UH OH</strong> moments when trying new things is an advantage of this setup.</p>
<p>Code for this application is available on GitHub : <a href="https://github.com/spboyer/runracereview">https://github.com/spboyer/runracereview</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Using Azure DevOps Pipelines and NuKeeper to Automate NuGet Package updates]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Keeping your code update to with the latest references can at times be a challenge with the rate of speed third-party dependencies can revise. However, with security patches and bug fixes constantly plaguing us it is a necessary exercise.</p>
<p>I have been using <a href="http://tattoocoder.com/using-global-tool-dotnet-outdated-to-check-for-the-latest-nuget-package-updates/">dotnet-outdated</a> to quickly run checks on my</p>]]></description><link>https://tattoocoder.com/using-azuredevops-pipelines-and-nukeeper-to-automate-nuget-package-updates/</link><guid isPermaLink="false">5e20d712283d3500013a42ec</guid><category><![CDATA[azure]]></category><category><![CDATA[devops]]></category><category><![CDATA[nuget]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Tue, 16 Oct 2018 18:53:07 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2018/10/Slide1-1.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://tattoocoder.com/content/images/2018/10/Slide1-1.png" alt="Using Azure DevOps Pipelines and NuKeeper to Automate NuGet Package updates"><p>Keeping your code update to with the latest references can at times be a challenge with the rate of speed third-party dependencies can revise. However, with security patches and bug fixes constantly plaguing us it is a necessary exercise.</p>
<p>I have been using <a href="http://tattoocoder.com/using-global-tool-dotnet-outdated-to-check-for-the-latest-nuget-package-updates/">dotnet-outdated</a> to quickly run checks on my projects and it has even been a huge help when getting some non-descript error messages in my code realizing I was missing a recent update.</p>
<p>Looking at a way to extend this functionality or automate it, I came across <a href="https://github.com/NuKeeperDotNet/NuKeeper">Nukeeper</a> and a write up from <a href="https://www.hanselman.com/blog/NuKeeperForAutomatedNuGetPackageReferenceUpdatesOnBuildServers.aspx">Scott Hanselman</a> that mentioned that this one had a <a href="https://github.com/NuKeeperDotNet/NuKeeper/wiki/Getting-Started#repository-command">Repository Feature</a> where running the command <code>nukeeper repo &lt;myrepo&gt;</code> would do the similar functions as dotnet outdated, BUT would also send a PR to the project!</p>
<p>This got me thinking, what if I could use NuKeeper and <a href="https://azure.microsoft.com/en-us/services/devops/pipelines/">Azure Devops</a> to watch my repo? I already have a pipeline building and deploying the project when commits are being made to a branch; we could set up an additional pipeline to do this process and when PRs are sent build the project for validation as well.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Slide1-1.png" alt="Using Azure DevOps Pipelines and NuKeeper to Automate NuGet Package updates"></p>
<h3 id="settingupnukeeperinazuredevops">Setting up NuKeeper in Azure DevOps</h3>
<p>The first step is to make sure that you have a  <a href="https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/">GitHub personal access token or PAT</a>. This is needed for executing the <a href="https://github.com/NuKeeperDotNet/NuKeeper/wiki/Getting-Started#repository-command"><code>repo</code> command</a> of NuKeeper.</p>
<p>I set my PAT as a variable <strong>&quot;Nukeepeer__github__token&quot;</strong> for the pipeline.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-15-at-2.15.46-PM-2.png" alt="Using Azure DevOps Pipelines and NuKeeper to Automate NuGet Package updates"></p>
<p>Moving over to the pipeline, the first task here is to install the .NET Core SDK that I want to target. In this case 2.1.403.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-15-at-2.16.08-PM.png" alt="Using Azure DevOps Pipelines and NuKeeper to Automate NuGet Package updates"></p>
<p>The next task uses the <code>dotnet</code> command to install the NuKeeper global tool,  for local dev; <code>dotnet tool install -g NuKeeper</code>.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-15-at-2.16.22-PM.png" alt="Using Azure DevOps Pipelines and NuKeeper to Automate NuGet Package updates"></p>
<p>There are two additional steps here to set the git user and name. These steps are needed only due to personal access token being used does not have a publically exposed email address. Typically you'd have this configured on your local machine in your <code>.gitconfig</code>.</p>
<p>Now that the SDK and global tool are set, the final task in the pipeline is the command to check our repo. Here the <code>repo</code> command is configured to use the PAT variable <code>$(NuKeeper_github_token)</code> and we are passing additional options for getting updates for 3 weeks or older minor changes.</p>
<p><code>nukeeper repo &quot;https://github.com/spboyer/runracereview&quot; $(NuKeeper_github_token) --age=3w --change=minor</code></p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-15-at-2.16.44-PM.png" alt="Using Azure DevOps Pipelines and NuKeeper to Automate NuGet Package updates"></p>
<p>Here is the <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&amp;tabs=schema">Azure DevOps Pipeline in YAML</a>.</p>
<pre><code class="language-yaml">queue:
  name: Hosted Linux Preview
variables:
  NuKeeper_github_token: 'your_github_personal_access_token'
steps:
- task: DotNetCoreInstaller@0
  displayName: 'Install .NET Core SDK'
  inputs:
    version: 2.1.403


- task: DotNetCoreCLI@2
  displayName: 'dotnet global tool install'
  inputs:
    command: custom

    custom: 'tool '

    arguments: 'install -g NuKeeper'


- script: 'git config --global user.email %git_email%' 
  displayName: 'Set git email address'

- script: 'git config --global user.name %git_username%' 
  displayName: 'Set git user name'

- script: 'nukeeper repo &quot;https://github.com/spboyer/runracereview&quot; $(NuKeeper_github_token) --age=3w --change=minor' 
  displayName: 'Run Race Review Project'

</code></pre>
<h3 id="schedulingchecks">Scheduling Checks</h3>
<p>Under the <strong>Triggers</strong> tab we can set a schedule as to when to run the pipeline. Every Saturday at 3 AM, it will run the checks and perform the Pull Requests to notify our other pipeline that there are needed updates to run tests, build and deployments against.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-15-at-2.14.06-PM.png" alt="Using Azure DevOps Pipelines and NuKeeper to Automate NuGet Package updates"></p>
<p>The most recent run revealed that there were needed updates -</p>
<pre><code class="language-console">2018-10-15T18:05:51.1414374Z Found 2 packages in use, 2 distinct, in 1 projects.
2018-10-15T18:05:51.1414982Z Bogus, MongoDB.Driver
2018-10-15T18:05:52.1161425Z Found 1 possible updates
2018-10-15T18:05:52.1162171Z Bogus from 23.0.3 to 24.3.0 in runracereview/runracereview.csproj
2018-10-15T18:05:52.1162436Z 
2018-10-15T18:05:52.1182228Z Found 1 package update
2018-10-15T18:05:52.1208829Z Bogus to 24.3.0 from 23.0.3 in 1 place since 13 days ago.
2018-10-15T18:05:52.2247646Z Selection of package updates: 1 candidates
2018-10-15T18:05:52.2248371Z Selected package update of Bogus to 24.3.0
2018-10-15T18:05:52.2334021Z Updating'Bogus' from 23.0.3 to 24.3.0 in 1 projects
2018-10-15T18:06:03.1689000Z Making PR onto 'https://api.github.com/ spboyer/runracereview from nukeeper-update-Bogus-to-24.3.0
2018-10-15T18:06:03.9890259Z Adding label(s) 'nukeeper' to issue 'https://api.github.com/ spboyer/runracereview 5'
2018-10-15T18:06:04.2032755Z Done 1 updates
</code></pre>
<p>Sending the PR over.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-16-at-2.45.40-PM.png" alt="Using Azure DevOps Pipelines and NuKeeper to Automate NuGet Package updates"></p>
<p>The whole process now being automated using <a href="https://azure.microsoft.com/en-us/services/devops/pipelines/">Azure DevOps</a> and a <a href="https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools">.NET Core global tool</a>. That's pretty slick.  How are you keeping your apps up to date?</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Exploring the Docker Extension for VS Code and .NET Core]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The <a href="https://marketplace.visualstudio.com/items?itemName=PeterJausovec.vscode-docker">Docker extension for VS Code</a> was recently updated to better support .NET Core applications and the experience is super nice!</p>
<p>The extension already has great support for building your containers, pushing images to Docker Hub, <a href="https://docs.microsoft.com/en-us/azure/container-registry/">Azure Container Registry</a> and tasks such as running a specific image or tagging an</p>]]></description><link>https://tattoocoder.com/exploring-the-docker-extension-for-vs-code-and-net-core/</link><guid isPermaLink="false">5e20d712283d3500013a42eb</guid><category><![CDATA[docker]]></category><category><![CDATA[vscode]]></category><category><![CDATA[dotnetcore]]></category><category><![CDATA[azure]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Thu, 04 Oct 2018 15:56:49 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-04-at-11.56.04-AM.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-04-at-11.56.04-AM.png" alt="Exploring the Docker Extension for VS Code and .NET Core"><p>The <a href="https://marketplace.visualstudio.com/items?itemName=PeterJausovec.vscode-docker">Docker extension for VS Code</a> was recently updated to better support .NET Core applications and the experience is super nice!</p>
<p>The extension already has great support for building your containers, pushing images to Docker Hub, <a href="https://docs.microsoft.com/en-us/azure/container-registry/">Azure Container Registry</a> and tasks such as running a specific image or tagging an image too. However, adding a Dockerfile to an ASP.NET Core application was not updated to support the <a href="https://hub.docker.com/r/microsoft/dotnet/">microsoft/dotnet</a> base images.</p>
<p>The Docker extension can be downloaded separately or is also available as a part of the <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-azureextensionpack">Azure extension pack for VS Code</a> which provides a number of other extensions for working with the many cloud services without leaving the editor.</p>
<p>First, I'll start by creating a quick Razor Pages app with the .NET CLI, change to the output directory and open in VS Code.</p>
<pre><code class="language-console">&gt; dotnet new razor -o dotnet-docker-vscode
&gt; cd dotnet-docker-vscode
&gt; code .
</code></pre>
<p>Using the extension, I can now add the needed Dockerfile using the Command Pallete, CMD + Shift + P (MacOS) or Ctrl + Shift + P (Win), type <strong>Docker</strong> and the options are presented.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/adddockerfile.gif" alt="Exploring the Docker Extension for VS Code and .NET Core"></p>
<p>The extension adds the appropriate Dockerfile for ASP.NET Core 2.1</p>
<pre><code class="language-dockerfile">FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY [&quot;dotnet-docker-vscode.csproj&quot;, &quot;./&quot;]
RUN dotnet restore &quot;./dotnet-docker-vscode.csproj&quot;
COPY . .
WORKDIR &quot;/src/.&quot;
RUN dotnet build &quot;dotnet-docker-vscode.csproj&quot; -c Release -o /app

FROM build AS publish
RUN dotnet publish &quot;dotnet-docker-vscode.csproj&quot; -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT [&quot;dotnet&quot;, &quot;dotnet-docker-vscode.dll&quot;]
</code></pre>
<p>Again using the extension we can build the image. When doing so it does ask for a tag, and in this case I will prefix it with my Azure Container Registry name for pushing to later.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/buildimage.gif" alt="Exploring the Docker Extension for VS Code and .NET Core"></p>
<p>Expanding the <strong>Images</strong> section, we can see the <strong>shayne.azurecr.io/dotnet-docker-vscode</strong> image available now. Right-clicking the entry show the options you would expect; aligning with the most common commands from the Docker CLI.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/Screen-Shot-2018-10-04-at-11.26.40-AM.png" alt="Exploring the Docker Extension for VS Code and .NET Core"></p>
<p>The option I can select here is to <strong>Push</strong> the image now to my Azure Container Registry.</p>
<blockquote>
<p>You may need to authenticate to your ACR which can be accomplished in the terminal using <code>az acr login --name {name of your registry}</code> should you get an error when pushing your image.</p>
</blockquote>
<p>Now that the image is available in my private registry I can use the App Service extension to create an instance of the application using <a href="https://docs.microsoft.com/en-us/azure/app-service/containers/">App Service on Linux</a> and push my container.</p>
<p><img src="https://tattoocoder.com/content/images/2018/10/create-app-service.gif" alt="Exploring the Docker Extension for VS Code and .NET Core"></p>
<p>All of these tasks we can accomplish without leaving Visual Studio Code. There are a bunch of great extensions for developing whatever language or stack you like. For .NET Core, Azure and Docker development the following are some of my favorites.</p>
<ul>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-azureextensionpack">Azure extension pack</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=PeterJausovec.vscode-docker">Docker extension for VS Code</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens">GitLens</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-mssql.mssql">mssql</a></li>
<li><a href="https://marketplace.visualstudio.com/items?itemName=ms-kubernetes-tools.vscode-kubernetes-tools">Kubernetes</a></li>
</ul>
<h3 id="challenge">Challenge</h3>
<p>There is a challenge here for you...go download the extension. Build something, publish it and let me know. I want to hear the feedback on the extension and experience.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[dotnet new templates for serverless functions]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Since <a href="https://www.microsoft.com/net/download/dotnet-core/2.0?utm_source=shboyer&amp;utm_medium=blog&amp;utm_campaign=blog&amp;WT.mc_id=none-blog-shboyer">.NET Core</a> was announced, I've really been loving the command line experience for .NET Core. Being able to use <code>dotnet new</code> to start a new application regardless of the OS or what shell/terminal experience is on a machine is the way to happiness.</p>
<p>The <a href="https://docs.microsoft.com/en-us/azure/azure-functions/">Azure Functions</a> team has</p>]]></description><link>https://tattoocoder.com/dotnet-new-templates-for-serverless-functions/</link><guid isPermaLink="false">5e20d712283d3500013a42ea</guid><category><![CDATA[azure-functions]]></category><category><![CDATA[azure mobile services]]></category><category><![CDATA[serverless]]></category><dc:creator><![CDATA[Shayne Boyer]]></dc:creator><pubDate>Wed, 08 Aug 2018 15:01:27 GMT</pubDate><media:content url="https://tattoocoder.com/content/images/2018/08/pablo--5-.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://tattoocoder.com/content/images/2018/08/pablo--5-.png" alt="dotnet new templates for serverless functions"><p>Since <a href="https://www.microsoft.com/net/download/dotnet-core/2.0?utm_source=shboyer&amp;utm_medium=blog&amp;utm_campaign=blog&amp;WT.mc_id=none-blog-shboyer">.NET Core</a> was announced, I've really been loving the command line experience for .NET Core. Being able to use <code>dotnet new</code> to start a new application regardless of the OS or what shell/terminal experience is on a machine is the way to happiness.</p>
<p>The <a href="https://docs.microsoft.com/en-us/azure/azure-functions/">Azure Functions</a> team has put together some fancy new templates for creating serverless apps now.</p>
<h2 id="gettingthenewtemplatesinstalled">Getting the new templates installed</h2>
<p>.NET Core templates are all just NuGet packages and installed using <code>dotnet new -i &lt;package-path&gt;</code>. In this case, the templates are on a private feed, so you need to get them <strong>nupkg</strong> files from <a href="https://functionscdn.azureedge.net/public/cli-feed-v3.json">https://functionscdn.azureedge.net/public/cli-feed-v3.json</a>.</p>
<p>The latest current version right now is from the feed:</p>
<pre><code class="language-javascript">    &quot;2.3.3&quot;: {
      &quot;Microsoft.NET.Sdk.Functions&quot;: &quot;1.0.14&quot;,
      &quot;cli&quot;: &quot;https://functionscdn.azureedge.net/public/2.0.1-beta.34/Azure.Functions.Cli.win-x86.2.0.1-beta.34.zip&quot;,
      &quot;nodeVersion&quot;: &quot;8.11.1&quot;,
      &quot;localEntryPoint&quot;: &quot;func.exe&quot;,
      &quot;itemTemplates&quot;: &quot;https://www.myget.org/F/azure-appservice/api/v2/package/Azure.Functions.Templates/2.0.0-beta-10224&quot;,
      &quot;projectTemplates&quot;: &quot;https://www.myget.org/F/azure-appservice/api/v2/package/Microsoft.AzureFunctions.ProjectTemplates/2.0.0-beta-10224&quot;,
      &quot;templateApiZip&quot;: &quot;https://functionscdn.azureedge.net/public/TemplatesApi/2.0.0-beta-10224.zip&quot;,
      &quot;sha2&quot;: &quot;4A2B808E86AE4C4DEF38A2A14270D19EC384648AD1FDF635921A64F609D41098&quot;,
      &quot;FUNCTIONS_EXTENSION_VERSION&quot;: &quot;beta&quot;,
      &quot;requiredRuntime&quot;: &quot;.NET Core&quot;,
      &quot;minimumRuntimeVersion&quot;: &quot;2.1&quot;
</code></pre>
<p>Download the <strong>projectTemplates</strong> and <strong>itemTemplates</strong> nupkg files and install them using the command:</p>
<pre><code class="language-console">dotnet new -i ~/Downloads/Azure.Functions.Templates.2.0.0-beta-10224.nupkg&quot;
dotnet new -i ~/Downloads/Microsoft.AzureFunctions.ProjectTemplates.2.0.0-beta-10224.nupkg&quot;
</code></pre>
<p>Now when <code>dotnet new</code> is run, the Azure Function templates are available.</p>
<pre><code class="language-console">Templates                                         Short Name                          Language          Tags
-------------------------------------------------------------------------------------------------------------------------------
QueueTrigger                                      Queue                               [C#]              Azure Function
HttpTrigger                                       Http                                [C#]              Azure Function
BlobTrigger                                       Blob                                [C#]              Azure Function
TimerTrigger                                      Timer                               [C#]              Azure Function
DurableFunctionsOrchestration                     DurableFunctionsOrchestration       [C#]              Azure Function
SendGrid                                          SendGrid                            [C#]              Azure Function
EventHubTrigger                                   EventHub                            [C#]              Azure Function
ServiceBusQueueTrigger                            SBQueue                             [C#]              Azure Function
ServiceBusTopicTrigger                            SBTopic                             [C#]              Azure Function
EventGridTrigger                                  EventGrid                           [C#]              Azure Function
Azure Functions                                   azureFunctionsProjectTemplates      [C#]              AzureFunctions/ClassLib
</code></pre>
<h2 id="creatingaquickfunctionapp">Creating a quick function app</h2>
<pre><code class="language-console">
# initial a new Azure Function application
dotnet new azurefunction --output myfunctionapp

# change dir
cd myfunctionapp

# add a new HttpTrigger Function 
dotnet new http --name echo 

# directory
.
├── echo.cs
├── host.json
├── local.settings.json
└── myfunctionapp.csproj
</code></pre>
<p>Now that I have initialized my app and first function, I could start the app using the <a href="https://github.com/Azure/azure-functions-core-tools#readme">functions cli</a> with <code>func host start</code> but I want to be able to be able to debug the app, and deploy. I can open the project using <a href="https://code.visualstudio.com/">VS Code</a> using <code>code .</code> or in my case I use the <a href="https://code.visualstudio.com/insiders">Insiders Build</a> <code>code-insiders .</code></p>
<blockquote>
<p>I have the <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.vscode-azureextensionpack">Azure Extension Pack for VS Code</a> installed which includes the <a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions">Azure Functions extension</a> which allows you quickly browse, create, manage, deploy, and even <a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local">debug functions locally</a>.</p>
</blockquote>
<p>I am prompted with a notification that this is an Azure Function created outside of VS Code, and it is asking to add the assets for setting up debugging. Click Yes.</p>
<p><img src="https://tattoocoder.com/content/images/2018/08/Screen-Shot-2018-08-08-at-9.50.19-AM.png" alt="dotnet new templates for serverless functions"></p>
<p>Now I can hit F5, add break points, and inspect my code just as I would expect from a great tooling experience but also have the ability to add new functions. Using the integrated terminal in VS Code you can see that the endpoint <code>http://localhost:7071/api/echo</code> is available.</p>
<p><img src="https://tattoocoder.com/content/images/2018/08/Screen-Shot-2018-08-08-at-10.34.20-AM.png" alt="dotnet new templates for serverless functions"></p>
<p>If we wanted to add an additional HttpTrigger, use the following command:</p>
<pre><code class="language-console"># using -n as the short form for --name and -na short for namespace
dotnet new http -n echo2 -na myfunctionapp 
</code></pre>
<p>Or if you prefer a UI experience in VS Code, there is the Functions Extension for adding a new one as well.</p>
<p><img src="https://tattoocoder.com/content/images/2018/08/Screen-Shot-2018-08-08-at-10.40.44-AM.png" alt="dotnet new templates for serverless functions"></p>
<ul>
<li>Click on the &quot;Add new function&quot;</li>
<li>Select the folder you want to work in</li>
<li>Select the type of function</li>
<li>Type the name of the function</li>
<li>Type the name of the namespace</li>
<li>... potentially other options.</li>
</ul>
<p>Both options are great depending on how you like to work. The templates are in line with how I work for all .NET Core applications now and I spend much of my time using command line tools like Docker, Kubernetes and the Azure CLI.</p>
<p>The Azure Functions are open source at <a href="https://github.com/Azure/azure-functions-templates">https://github.com/Azure/azure-functions-templates</a> please provide feedback. <a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-develop-vs">Azure Function development, debugging and deployment in Visual Studio</a> is available as well.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>