<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>ChrisRisner.com</title>
		<description>The home for Chris Risner's thoughts on the internet.</description>
		<link>/</link>
		<atom:link href="/feed.xml" rel="self" type="application/rss+xml" />
		
			<item>
				<title>Open Sourcing Azure Storage Explorer for Mobile</title>
				<description>&lt;p&gt;Some time ago, I started working on a mobile version of the &lt;a href=&quot;http://storageexplorer.com&quot;&gt;Azure Storage Explorer&lt;/a&gt;.  The intent of this app was that anything you could do from the ASE app on Windows, MacOS, or Linux, you’d be able to do on Android and iOS.  There were a few different reasons I wanted to build this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I wanted to spend time building out a real application using &lt;a href=&quot;http://xamarin.com&quot;&gt;Xamarin&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;There were a few situations where I thought it would be handy to have access to my storage accounts while away from my computer.&lt;/li&gt;
  &lt;li&gt;I wanted to start auto-backing up any photos I took with my phone to Azure Storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fast forward through several months of working on the app in my spare time (which is to say not very frequently) and I had a number of scenarios around Storage working.  What I didn’t have, was a strong use case or motivation to release and support the app.  Additionally, after talking with more people, it didn’t seem like there was a very strong use case for the mobile version of ASE.  As with many other things, if there wasn’t a customer need, there probably wasn’t going to be much usage, and therefore there wouldn’t be much in the way of support.  So rather than releasing an app to the App Store and Google Play and let it languish, I decided it would be better to just open source the app.&lt;/p&gt;

&lt;h2 id=&quot;releasing-the-souce-code-for-ase-mobile&quot;&gt;Releasing the Souce Code for ASE Mobile&lt;/h2&gt;

&lt;p&gt;Effective today, you can now access all source code and assets for &lt;a href=&quot;https://github.com/ChrisRisner/AzureStorageExplorer&quot;&gt;Azure Storage Explorer for Android and iOS on GitHub&lt;/a&gt;.  I think this is a great reference app as it details:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How to build a semi-sophisticated Xamarin app for Android and iOS.&lt;/li&gt;
  &lt;li&gt;How to use different UI elements depending on the platform (iOS makes use of tabs while Android uses the slide out menu).&lt;/li&gt;
  &lt;li&gt;How to access a number of different Azure Storage capabilities (see below).&lt;/li&gt;
  &lt;li&gt;How to mix usage of Azure REST APIs and libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;credit-to-other-devs&quot;&gt;Credit to Other Devs&lt;/h2&gt;

&lt;p&gt;I couldn’t have built this without &lt;del&gt;stealing&lt;/del&gt; borrowing from many other devs.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I heavily referenced the app architecture and patterns from the &lt;a href=&quot;https://github.com/xamarinhq/app-evolve&quot;&gt;Xamarin Evolve 2016 Mobile App&lt;/a&gt;.  James and Pierce did a great job with this app and made it very easy to look through and reuse.&lt;/li&gt;
  &lt;li&gt;I’ll call out &lt;a href=&quot;https://montemagno.com/&quot;&gt;James Montemagno&lt;/a&gt; again as I made use of a large assortment of the Xamarin plugins he builds and supports.&lt;/li&gt;
  &lt;li&gt;Developers at &lt;a href=&quot;https://realm.io/&quot;&gt;Realm&lt;/a&gt; and &lt;a href=&quot;https://github.com/rotorgames/Rg.Plugins.Popup&quot;&gt;Rg.Plugins.Popup&lt;/a&gt; for their technical support.&lt;/li&gt;
  &lt;li&gt;Everyone that works on &lt;a href=&quot;https://www.visualstudio.com/vso/&quot;&gt;Visual Studio Team Services&lt;/a&gt; and &lt;a href=&quot;https://appcenter.ms/&quot;&gt;Visual Studio App Center&lt;/a&gt;.  Throughout developement, I used VSTS for continuous integration and App Center to deliver the app to test devices and track errors and analytics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;outstanding-issues&quot;&gt;Outstanding Issues&lt;/h2&gt;

&lt;p&gt;There are a number of issues I never got around to including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Testing against a large quantity of blobs, table rows, etc.&lt;/li&gt;
  &lt;li&gt;Editing table schema and rows.&lt;/li&gt;
  &lt;li&gt;Any sort of advanced querying of data.&lt;/li&gt;
  &lt;li&gt;Currently the app only works with Classic Storage Accounts due to how I am pulling subscriptions and storage accounts (i.e. the APIs I used).  This wouldn’t be very difficult to convert over but I never got to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;how-to-build-it&quot;&gt;How to Build it?&lt;/h2&gt;

&lt;p&gt;In order to build and run the application, there are a few things you should do and a few things you need to do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In the &lt;a href=&quot;https://github.com/ChrisRisner/AzureStorageExplorer/blob/master/src/AzureStorageExplorer/Helpers/Constants.cs&quot;&gt;src/AzureStorageExplorer/Helpers/Constants.cs&lt;/a&gt; class, there are a number of API Keys that need to be set.  First is the &lt;strong&gt;AuthClientId&lt;/strong&gt; which is the value you get from Azure Active Directory after you create an app with appropriate permissions.  Second is the &lt;strong&gt;MobileCenterId&lt;/strong&gt; which is the value you get after creating an app in Visual Studio App Center (yeah it used to be called Mobile Center).  You’ll note that there are different values based off of if you’re in Debug or not as well as if you’re in iOS or Android.&lt;/li&gt;
  &lt;li&gt;If you’re building and running in iOS, you’ll need to create an App ID and all the appropriate bundle identifiers, etc.  Because there is certain functionality that requires iCloud access, for the App ID, you’ll need to set up iCloud access (I used iCloud.azurestorageexplorer as the container name).&lt;/li&gt;
  &lt;li&gt;I haven’t compiled against the absolute latest versions of iOS / Android / Xamarin but I don’t anticipate any issues.&lt;/li&gt;
  &lt;li&gt;One thing to keep in mind is that I pulled in the actual code for the Rg.Plugins.Popup library.  This is only directly used in the iOS project and was done to alleviate an issue where popups weren’t working if you were &lt;em&gt;too deep&lt;/em&gt; down the navigational stack.  I believe they’ve fixed this in a preview version of the plugin (v1.1.0-pre1 and beyond) but haven’t tested this yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;would-you-use-it&quot;&gt;Would you use it?&lt;/h2&gt;

&lt;p&gt;If you see this and think you’d have use for the app if it was easily available on the App Store and Google Play, please let me know.  I left this project because it didn’t seem like there was a solid enough use case for it.  I’d love to be wrong about that.  If you need any help getting the &lt;a href=&quot;https://github.com/ChrisRisner/AzureStorageExplorer&quot;&gt;app&lt;/a&gt; built, please reach out or file an issue on the &lt;a href=&quot;https://github.com/ChrisRisner/AzureStorageExplorer&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
</description>
				<pubDate>Wed, 07 Feb 2018 09:16:00 +0000</pubDate>
				<link>/Open-Sourcing-Azure-Storage-Explorer-for-Mobile</link>
				<guid isPermaLink="true">/Open-Sourcing-Azure-Storage-Explorer-for-Mobile</guid>
			</item>
		
			<item>
				<title>Switching Comments to StaticMan</title>
				<description>&lt;p&gt;Six years ago, when I was still using my own custom built blog engine, I switched the comment system over to using &lt;a href=&quot;https://chrisrisner.com/Importing-Comments-into-Disqus&quot;&gt;Disqus&lt;/a&gt;.  At the time, this change made a lot of sense.  With just a little bit of additional markup per page, Disqus would render all of the comments and the comment form and handle everything for me, including the ability to do moderation.  Recently, when I &lt;a href=&quot;https://chrisrisner.com/Changing-Blog-Platforms-Again&quot;&gt;switched over to GitHub&lt;/a&gt;, I kept on with Disqus as it was relatively easy and there were instructions on how to integrate.  Unfortunately, one of the issues with Disqus is that it loads quite a bit of JavaScript including ads.  While the JavaScript is not blocking, I wouldn’t be entirely surprised if the long time for the page to actually finish loading didn’t impact some ratings by a few certain search engines.  Plus, the only way to remove the ads (which aren’t even relevant to the material of the site in anyway), is to pay.&lt;/p&gt;

&lt;h3 id=&quot;a-first-replacement-commentit&quot;&gt;A First Replacement: CommentIt&lt;/h3&gt;

&lt;p&gt;I’d taken a very brief look some months ago about finding a replacement that would work with GitHub pages.  Since GitHub pages are generated using &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; there isn’t really a backend that can be used to run the comment engine.  I was chatting about it with one of my teammates at work and he mentioned he’d recently setup a new site on GitHub pages and had used &lt;a href=&quot;https://commentit.io/&quot;&gt;CommentIt&lt;/a&gt; to handle this comments.  Once you give CommentIt access to your GitHub repo and put some markdown on your site (to display comments and to put a comment form on the page), everything works.  CommentIt runs the backend javascript that actually handles processing comments.  Whenever a comment is made, it creates a pull request against your repo.  The one big issue both he and I had with CommentIt was that it puts comments into the Front Matter for your blog posts.  I’d much rather prefer comments end up in a different file or location.&lt;/p&gt;

&lt;h3 id=&quot;staticman&quot;&gt;StaticMan&lt;/h3&gt;

&lt;p&gt;While looking around further, I stumbled upon &lt;a href=&quot;https://mademistakes.com/articles/jekyll-static-comments/&quot;&gt;this post on mademistakes.com&lt;/a&gt; about changing from Disqus or an external site to use &lt;a href=&quot;https://staticman.net/&quot;&gt;StaticMan&lt;/a&gt; for comments on GitHub Pages.  StaticMan functions similarly to CommentIt except it puts every comment in a separate file in your repo under the &lt;em&gt;/data/comments/[slug]&lt;/em&gt; path.  Additionally, there is support for replies, notifications, and Captchas. &lt;a href=&quot;https://staticman.net/docs/&quot;&gt;Getting started is quite easy&lt;/a&gt; and fully documented.  I did go down the route of trying to further customize my rendering and interface similar to what MadeMistakes.com had done and thought it would be good to share some of the implementation details.  Of particular importance, I’d look at the following files (on top of the JS and SCSS files):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ChrisRisner/chrisrisner.github.io/blob/master/_includes/comments.html&quot;&gt;/_includes/comments.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ChrisRisner/chrisrisner.github.io/blob/master/_includes/comment.html&quot;&gt;/_includes/comment.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ChrisRisner/chrisrisner.github.io/blob/master/_config.yml&quot;&gt;_config.yml&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ChrisRisner/chrisrisner.github.io/blob/master/staticman.yml&quot;&gt;staticman.yml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the big things I want to call out because I ran into issues with it multiple times is the ordering of the comments.  Specifically, ordering didn’t seem to be the same when running the site locally and when it was showing up in GitHub Pages.  I want to share what the &lt;strong&gt;comments.html&lt;/strong&gt; looks like:&lt;/p&gt;

&lt;div class=&quot;language-liquid highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where_exp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'item'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'item.replying_to == &quot;&quot;'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'date'&lt;/span&gt;)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;              
  &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;replying_to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;    
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;forloop.index&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;minus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;           &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;replying_to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;replying_to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_integer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;avatar&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;avatar&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;comment.html&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;replying_to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;replying_to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;avatar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;avatar&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
    
  &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;assign&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;plus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;endif&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;endfor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For some reason, the query where we’re trying to get comments that have nothing in the &lt;em&gt;replying_to&lt;/em&gt; field doesn’t work.  I’ve seen other examples where they compare against blank as in &lt;em&gt;where_exp: ‘item’, ‘item.replying to == blank’&lt;/em&gt; but that didn’t work for me either.  The sorting was very bizarre and didn’t make very much sense as, as near as I could tell, different rebuilds of the site lead to different ordering of the comments.&lt;/p&gt;

&lt;h3 id=&quot;importing-disqus-comments&quot;&gt;Importing Disqus Comments&lt;/h3&gt;

&lt;p&gt;The next step was to export the comments from Disqus which I did with &lt;a href=&quot;https://help.disqus.com/customer/portal/articles/472149-comments-export&quot;&gt;these instructions&lt;/a&gt;.  From there, I built a &lt;a href=&quot;https://github.com/ChrisRisner/DisqusToStaticManComments&quot;&gt;program to translate the XML into YML comment files&lt;/a&gt;.  Once that was done, I just needed to copy the comments over and push them up to my repo.  Now all of my comments are showing and their in the correct order.&lt;/p&gt;
</description>
				<pubDate>Wed, 27 Dec 2017 09:16:00 +0000</pubDate>
				<link>/Switching-Comments-to-StaticMan</link>
				<guid isPermaLink="true">/Switching-Comments-to-StaticMan</guid>
			</item>
		
			<item>
				<title>Running OpenWhisk on a VM in Azure</title>
				<description>&lt;p&gt;I’ve recently been doing some evaluations of open source Serverless frameworks and seeing how well they run on Azure.  One of the first such projects I tried out was &lt;a href=&quot;https://openwhisk.incubator.apache.org/&quot;&gt;OpenWhisk&lt;/a&gt;. OpenWhisk is a project created and open sourced by IBM.  You are able to run it on-prem and in the cloud, on top of IBM offering a managed service as part of their cloud.  As a first step in getting OpenWhisk to run, I wanted to deploy it on to a single VM running in Azure.  As I ran into a few issues, I wanted to share a walkthrough of how to get OpenWhisk running on a Linux VM in Azure.&lt;/p&gt;

&lt;h3 id=&quot;creating-an-azure-vm&quot;&gt;Creating an Azure VM&lt;/h3&gt;

&lt;p&gt;Your first step should be to create a Linux VM in Azure.  For this walk-through, I created an Ubuntu Server 16.04 LTS vm.  I chose the DS1_V2 Standard size though you’d probably get by with something smaller if desired.  In the interest of being very specific, I used the default VM settings at the time including:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;No Availability Set&lt;/li&gt;
  &lt;li&gt;Managed Disks for storage&lt;/li&gt;
  &lt;li&gt;Default Virtual Network, Subnet, Public IP, Network security group&lt;/li&gt;
  &lt;li&gt;No extensions&lt;/li&gt;
  &lt;li&gt;Auto-shutdown set to Off&lt;/li&gt;
  &lt;li&gt;Boot Diagnostics turned On&lt;/li&gt;
  &lt;li&gt;Guest OS diagnostics disabled&lt;/li&gt;
  &lt;li&gt;Default storage account name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once your VM is up and running (just a couple of minutes max), if you’ve done it in the Azure Portal, you should be taken to the blade in the portal for the VM.  If you didn’t use the portal, you can &lt;a href=&quot;http://portal.azure.com&quot;&gt;open it&lt;/a&gt; and navigate to your VM.  Clicking the &lt;strong&gt;Connect&lt;/strong&gt; button at the top of that blade will give you the &lt;strong&gt;SSH&lt;/strong&gt; command to use to connect which should be similar to “ssh adminUserName@publicIPAddress”.  Copy that into a terminal / SSH tool and connect to your VM.&lt;/p&gt;

&lt;h3 id=&quot;installing-and-setting-up-openwhisk&quot;&gt;Installing and Setting Up OpenWhisk&lt;/h3&gt;

&lt;p&gt;The first step is going to be pulling down the source code for the &lt;a href=&quot;https://github.com/apache/incubator-openwhisk&quot;&gt;Apache OpenWhisk&lt;/a&gt; project:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  git clone https://github.com/apache/incubator-openwhisk.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;They’ve provided a set up script for Ubuntu which will do a decent amount of the prep work for your VM so you should run that next:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  ./incubator-openwhisk/tools/ubuntu-setup/all.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will run for a few minutes and you’ll follow it up with a few more package installs:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  pip install --upgrade pip
  sudo pip install ansible==2.3.0.0
  sudo apt-get install couchdb
  sudo apt-get install docker.io
  sudo pip install docker-py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that I’ve tried to minimize the need to run most of these things as root though, as near as I can tell, this is necessary for some package installs.  Next, now that CouchDB (which backs OpenWhisk) is installed, we need to create an Admin user:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  curl -s -X PUT http://localhost:5984/_config/admins/username -d '&quot;password&quot;'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The response to that command should just be an empty set of quotes (“”).  Next we need to tell CouchDB to listen on more than just 127.0.0.1 so that we can access it from the docker containers that we’ll soon be deploying.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  sudo nano /etc/couchdb/local.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Near the top of this file, you should see a commented out line that starts with &lt;strong&gt;bind_address&lt;/strong&gt;.  You’ll want to uncomment it and set the IP to all zeros:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  bind_address = 0.0.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save that file and then restart CouchDB:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  sudo systemctl restart couchdb.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’re now ready to output some variables that will be used during the OpenWhisk setup:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  export OW_DB=CouchDB
  export OW_DB_USERNAME=username
	export OW_DB_PASSWORD=password
	export OW_DB_PROTOCOL=http
	export OW_DB_HOST=VMHOSTNAME
	export OW_DB_PORT=5984
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now here, the &lt;strong&gt;username&lt;/strong&gt; nad &lt;strong&gt;password&lt;/strong&gt; should match the values you’ve used when you created the CouchDB admin user above.  Also, you’ll want to replace &lt;strong&gt;VMHOSTNAME&lt;/strong&gt; with the name of your actual VM.  Next we’ll run our Ansible playbooks:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  cd incubator-openwhisk/ansible
  ansible-playbook setup.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since we ran the earlier Ubuntu-setup/all.sh script, some default values will have been applied for the database connection info that we’ll need to override.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  nano db_local.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you’ll need to replace &lt;strong&gt;db_username&lt;/strong&gt;, &lt;strong&gt;db_password&lt;/strong&gt;, and &lt;strong&gt;db_host&lt;/strong&gt; with the same values you used up above.  Save your changes to that file.&lt;/p&gt;

&lt;p&gt;Now we need to grant our user Docker access so we don’t need to run future playbooks as root:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  sudo usermod -aG docker cloudadmin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We need to make this change take affect and as near as I can tell, just disconnecting and reconnecting won’t do it.  To be safe, I have gone in and restarted the VM from the Azure Portal and then reconnected.  Next we’ll run a nice long gradle build:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  cd ~/incubator-openwhisk
  ./gradlew distDocker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can execute the rest of the playbooks:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  cd ansible
  ansible-playbook initdb.yml
  ansible-playbook wipe.yml
  ansible-playbook apigateway.yml
  ansible-playbook openwhisk.yml
  ansible-playbook postdeploy.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;testing-openwhisk&quot;&gt;Testing OpenWhisk&lt;/h3&gt;

&lt;p&gt;With all of our Ansible playbooks run, we can now use the &lt;strong&gt;wsk&lt;/strong&gt; command line tool to talk to execute functions on OpenWhisk.  In order to do so, we need to either pass, or set, the API Host and Auth values for the command line.  We’ll do the latter:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  cd ../bin
  ./wsk property set --apihost http://172.17.0.1:10001
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order to get the auth value out, we’ll print out the value from the auth.guest file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  cat ../ansible/files/auth.guest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Copy that value into this command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  ./wsk property set --auth AUTHVALUE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now finally, we can invoke something:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  ./wsk action invoke /whisk.system/utils/echo -p message hello --result
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If all goes well, your output should look like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  {
    &quot;message&quot;: &quot;hello&quot;
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And now you’re running OpenWhisk.  From here you might expand by running on a Kubernetes cluster, deploying applications that also run on-prem, etc.&lt;/p&gt;

</description>
				<pubDate>Thu, 21 Sep 2017 09:16:00 +0000</pubDate>
				<link>/Running-OpenWhisk-on-a-VM-in-Azure</link>
				<guid isPermaLink="true">/Running-OpenWhisk-on-a-VM-in-Azure</guid>
			</item>
		
			<item>
				<title>Xamarin iOS Error Confusion</title>
				<description>&lt;p&gt;As I’ve continued working on the Xamarin.Forms application I’ve been building, 
I’ve learned a lot.  One of the issues I ran into was an error in the iOS version of
my application and as I didn’t find an easy to understand solution, I thought I would
document it here.  I’ll list the error first then explain the scenario and how to fix
it.&lt;/p&gt;

&lt;h3 id=&quot;ax-exchange-error-error-domainaccessibility-code0-remote-service-does-not-respond-to-_accessibilitymachport-userinfonslocalizeddescriptionremote-service-does-not-respond-to-_accessibilitymachport&quot;&gt;AX Exchange error: Error Domain=Accessibility Code=0 “Remote service does not respond to _accessibilityMachPort” UserInfo={NSLocalizedDescription=Remote service does not respond to _accessibilityMachPort}&lt;/h3&gt;

&lt;p&gt;Part of the application revolves around uploading files.  For Android this isn’t very
difficult and it even makes &lt;em&gt;sense&lt;/em&gt; as Android has a file system you can access and
external storage in the form of SD cards.  With iOS you can store files for your own
app but not others (for the most part).  However, you can access a user’s iCloud
if they grant you permission.  To this end, I started looking at the &lt;a href=&quot;https://github.com/Studyxnet/FilePicker-Plugin-for-Xamarin-and-Windows&quot;&gt;FilePicker Plugin for Xamarin and Windows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In theory what this plugin would do is with one call open up a file picker connected
to iCloud on iOS and to the disk on Android (and who knows on Windows).  This plugin
works great for Android.  However, for iOS calling the &lt;strong&gt;PickFile&lt;/strong&gt; method results in 
this error:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the time of writing, it appears the author &lt;a href=&quot;https://github.com/Studyxnet/FilePicker-Plugin-for-Xamarin-and-Windows/issues/28&quot;&gt;knows&lt;/a&gt;
about the issue but hasn’t yet pushed a fix out to NuGet.  So instead, I took that code
and baked it into my app for Android and iOS and it worked for both.  However, when the
picker pops up to let you pick a file from iCloud, it comes along with the error 
being printed out to Application Output over and over and over again:&lt;/p&gt;

&lt;h3 id=&quot;ax-exchange-error-error-domainaccessibility-code0-remote-service-does-not-respond-to-_accessibilitymachport-userinfonslocalizeddescriptionremote-service-does-not-respond-to-_accessibilitymachport-1&quot;&gt;AX Exchange error: Error Domain=Accessibility Code=0 “Remote service does not respond to _accessibilityMachPort” UserInfo={NSLocalizedDescription=Remote service does not respond to _accessibilityMachPort}&lt;/h3&gt;

&lt;p&gt;I did a bit of searching and didn’t find anything &lt;strong&gt;DIRECTLY&lt;/strong&gt; related to the FilePicker
but I did find something about custom keyboards and external testing frameworks.&lt;br /&gt;
Xamarin.iOS apps are wired to use &lt;strong&gt;Calabash&lt;/strong&gt; for testing with Xamarin Test Cloud and
you will find this in the &lt;strong&gt;AppDelegate&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-C#&quot;&gt;#if ENABLE_TEST_CLOUD
			Xamarin.Calabash.Start();
#endif
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Commenting that out led to the error no longer occurring.  I’m not 100% sure what the
is causing this issue but at least there is a quick fix.&lt;/p&gt;
</description>
				<pubDate>Mon, 06 Mar 2017 09:16:00 +0000</pubDate>
				<link>/Xamarin-iOS-Error-Confusion</link>
				<guid isPermaLink="true">/Xamarin-iOS-Error-Confusion</guid>
			</item>
		
			<item>
				<title>Getting Realm to Build Xamarin Apps with VSTS</title>
				<description>&lt;p&gt;I’ve recently been working on a Xamarin.Forms project for Android and 
iOS and recently came across an issue that took some experimenting to get
fixed so I thought I would share it for anyone else that might run into it.&lt;/p&gt;

&lt;p&gt;Realm is a database designed for mobile applications and offers a safe,
easy, non-ORM replacement for SQLite.  The intent is that you can, for the
most part, mark your data model objects as &lt;strong&gt;RealmObject&lt;/strong&gt;s and Realm 
will handle all of the persistence for you.  As with anything, it gets
more complicated than that but so far it’s still much better for what
I’m doing than SQLite.  If I needed the ability to do offline synchronization
with an online data source, I’d be looking at &lt;a href=&quot;https://azure.microsoft.com/en-us/services/app-service/mobile/&quot;&gt;Azure Mobile Apps&lt;/a&gt;
, but as I don’t I’m fine with what Realm will do for me.&lt;/p&gt;

&lt;p&gt;Adding Realm to your Xamarin.Forms application just requires adding the 
&lt;a href=&quot;https://www.nuget.org/packages/Realm/&quot;&gt;Realm NuGet&lt;/a&gt; package to your projects.
From there, you should be able to compile your projects without any issues.&lt;/p&gt;

&lt;p&gt;However, if you have Continuous Integration set up to auto-build your projects
and run tests with every build, it’s possible to run into an issue.  I use
&lt;a href=&quot;https://www.visualstudio.com/team-services/&quot;&gt;Visual Studio Team Services&lt;/a&gt; to
build all of my mobile projects and then deliver them to &lt;a href=&quot;http://hockeyapp.net&quot;&gt;HockeyApp&lt;/a&gt;
for beta testing.  I’ll have to post more about setting up the Build Definition
(the steps for building and uploading my compiled applications) but want to 
focus on the issue that having Realm in your projects has with the build
process.&lt;/p&gt;

&lt;p&gt;When you add Realm to your projects, it adds a Target as part of the package.&lt;br /&gt;
That step, called &lt;strong&gt;CopyRealmWeaver&lt;/strong&gt; which copies &lt;strong&gt;RealmWeaver.Fody.dll&lt;/strong&gt; as
part of the build process.  I won’t get into what &lt;a href=&quot;https://github.com/Fody/Fody&quot;&gt;Fody&lt;/a&gt;
is but it’s a necessary part of using Realm.  The XML found in the &lt;strong&gt;Realm.targets&lt;/strong&gt;
has the following inside of it:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Target&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CopyRealmWeaver&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;BeforeTargets=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;FodyTarget&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Message&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CopyRealmWeaver&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Error&lt;/span&gt; 
    &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Solution directory was not set. If you are building via xbuild, specify by adding a /p:SolutionDir=/path/to/solution/folder argument. See github.com/realm/realm-dotnet/issues/656&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;Condition=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;'$(SolutionDir)' == ''&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Copy&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;SourceFiles=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(MSBuildThisFileDirectory)../tools/RealmWeaver.Fody.dll&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;DestinationFolder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;$(SolutionDir)/Tools&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What this does is check to make sure &lt;strong&gt;$(SolutionDir)&lt;/strong&gt; has been specified
as part of the call to xbuild, or in the case of VSTS, msbuild.  Provided that
value has been specified, it then copies the &lt;strong&gt;RealmWeaver.Fody.dll&lt;/strong&gt; from a tools
directory in the packages folder into the Solution directory.&lt;/p&gt;

&lt;h2 id=&quot;whats-wrong-here&quot;&gt;What’s wrong here&lt;/h2&gt;

&lt;p&gt;The problem here is that when compiling with VSTS, there is some step that changes
the SolutionDir value to &lt;strong&gt;*undefined*&lt;/strong&gt;.  When I ran into this, it was 
especially weird as I couldn’t seem to find a reference to VSTS, build, and
&lt;strong&gt;*undefined*&lt;/strong&gt; anywhere.  I did find a &lt;a href=&quot;http://stackoverflow.com/questions/635346/prebuild-event-in-visual-studio-replacing-solutiondir-with-undefined&quot;&gt;Stack Overflow post&lt;/a&gt; 
about Visual Studio replacing &lt;strong&gt;$(SolutionDir)&lt;/strong&gt; with &lt;strong&gt;*undefined*&lt;/strong&gt; which
wasn’t the solution to my problem exactly but did get me on the right path.  From there, 
I took a look at the call to MSBuild to see what was showing up:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2016-12-13T19:23:38.1392477Z ##[command]&quot;C:\Program Files (x86)\MSBuild\14.0\bin\msbuild.exe&quot; &quot;C:\a\1\s\src\Droid\MyApp.Android.csproj&quot; /nologo /nr:false /dl:CentralLogger,&quot;C:\a\_tasks\XamarinAndroid_27edd013-36fd-43aa-96a3-7d73e1e35285\1.1.1\ps_modules\MSBuildHelpers\Microsoft.TeamFoundation.DistributedTask.MSBuild.Logger.dll&quot;;&quot;RootDetailId=39592de0-fb1c-4156-a73e-b2e8ee77129e|SolutionDir=C:\a\1\s\src\Droid&quot;*ForwardingLogger,&quot;C:\a\_tasks\XamarinAndroid_27edd013-36fd-43aa-96a3-7d73e1e35285\1.1.1\ps_modules\MSBuildHelpers\Microsoft.TeamFoundation.DistributedTask.MSBuild.Logger.dll&quot;  /p:configuration=&quot;Release&quot; /p:_MSDeployUserAgent=&quot;VSTS_db204fe6-401b-4488-b9c9-02229bdeafd2_build_25_317&quot; /t:PackageForAndroid /p:OutputPath=&quot;C:\a\1\b/Release&quot; /p:JavaSdkDirectory=&quot; C:\Program Files (x86)\Java\jdk1.8.0_102&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What I want to highlight from that call to msbuild is &lt;strong&gt;SolutionDir=C:\a\1\s\src\Droid&lt;/strong&gt;.  It 
&lt;em&gt;seems&lt;/em&gt; like we’re specifying a Solution Directory, but the error shows us that somehow,
that is being overwritten.  So we need to override that overwrite and ensure a value
is in fact being passed in.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://chrisrisner.com/upload/realm-vsts-build-arguments.png&quot; alt=&quot;Build Xamarin Additional Arguments&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Thankfully, the Build Xamarin project build step has a spot for &lt;strong&gt;Additional Arguments&lt;/strong&gt; at
the bottom.  In this case, I set the solution directory to the directory of my overall solution
file and where the tools directory containing the RealmWeaver.Fody.dll is at.  The format
of the argument is important so this is what you should be using (adjusting the path for your)
tools folder location of course:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/p:SolutionDir=”src”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With that done, I was able to run builds without any issue.  This seem to be an Android only
issue so you shouldn’t need to change anything on your iOS build.&lt;/p&gt;

&lt;h2 id=&quot;update-2-16-2017-a-new-error&quot;&gt;Update 2-16-2017: A new error&lt;/h2&gt;

&lt;p&gt;After a recent update (to my code base), I found that my workaround was no longer working.  The new error I was seeing was:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;FodyTarget:
  Fody: Fody (version 1.29.4.0) Executing
  Fody: ProjectDirectory: 'D:\a\1\s\src\MyApp\MyApp.PCL\'.
  Fody: AssemblyPath: 'D:\a\1\s\src\MyApp\MyApp.PCL\obj\Release\MyApp.PCL.dll'
  Fody: Found path to weavers file 'D:\a\1\s\src\MyApp\MyApp.PCL\FodyWeavers.xml'.
##[error]Fody: SolutionDir &quot;D:\a\1\s\src\MyApp\MyApp.PCL\src&quot; does not exist.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What this appears to be doing is adding the &lt;strong&gt;SolutionDir&lt;/strong&gt; that I specified above to the end of the PCL’s path.  I was able to fix this once again by changing my &lt;strong&gt;Additional Arguments&lt;/strong&gt; to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;/p:SolutionDir=”/”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I suspect this was due to a change in the &lt;strong&gt;Realm.targets&lt;/strong&gt; XML file for the newer version of Realm that I updated to when I updated NuGets.&lt;/p&gt;
</description>
				<pubDate>Wed, 14 Dec 2016 09:16:00 +0000</pubDate>
				<link>/Getting-Realm-to-Build-in-Xamarin-with-VSTS</link>
				<guid isPermaLink="true">/Getting-Realm-to-Build-in-Xamarin-with-VSTS</guid>
			</item>
		
			<item>
				<title>Announcing the Azure Usage and Billing Portal</title>
				<description>&lt;p&gt;Today I’m excited to &lt;a href=&quot;https://azure.microsoft.com/en-us/blog/announcing-the-release-of-the-azure-usage-and-billing-portal/&quot;&gt;announce&lt;/a&gt; that we’ve released the &lt;a href=&quot;https://github.com/Microsoft/AzureUsageAndBillingPortal&quot;&gt;Azure Usage and Billing Portal&lt;/a&gt; as an open source project on GitHub.  The Azure Usage and Billing Portal is a solution which enables you to review the usage and resulting billing information across multiple subscriptions.  Currently, if you are an Azure consumer using multiple subscriptions, you’re options for viewing all of the usage over any given time period aren’t that great.  The Azure Portal enables you to view usage and billing for individual subscriptions one at a time (both a breakdown of current charges, cost by service, and cost by resource) but if you’re using multiple subscriptions, trying to review all of the information there is inefficient.  Furthermore, you are able to download a CSV file of Azure consumption for each subscription, but that is a manual process and would require processing afterwards.&lt;/p&gt;

&lt;p&gt;Last year, Microsoft announced &lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/billing-usage-rate-card-overview/&quot;&gt;new APIs&lt;/a&gt; to provide a way to programmatically pull information on usage and rate cards for your subscriptions.  Included in that announcement were a number of &lt;a href=&quot;https://azure.microsoft.com/documentation/samples/?term=billing&quot;&gt;samples&lt;/a&gt; demonstrating how you can pull information for your own subscriptions.  When this announcment came out, we had already been seeing requests from customers we were working with for a way to visualize and track their spend.  This spurred my team into action to build something which would make consuming and seeing this data easier.&lt;/p&gt;

&lt;p&gt;Once deployed, you can now register any subscriptions you want so that the daily usage will be polled and displayed in an easy to use Power BI dashboard.  This dashboard enables you to slice data in many ways including by subscription, by resource type, by resource name, by geo, by date, and more.  Furthermore, you can use the SQL Database that stores the usage and billing to build any sort of interface / alerting on top of the data you want.&lt;/p&gt;

&lt;p&gt;Mustafa Kasap, the lead engineer on this project, wrote up a &lt;a href=&quot;https://blogs.msdn.microsoft.com/mustafakasap/2016/07/14/welcome-azure-usage-and-billing-portal/&quot;&gt;great blog post&lt;/a&gt; describing the project a bit more including some helpful images.&lt;/p&gt;

&lt;p&gt;We’ve got a lot of plans for future feature additions and already a few issues to fix.  We welcome any contributions or feedback on the project either on the blog posts or as issues on the &lt;a href=&quot;https://github.com/Microsoft/AzureUsageAndBillingPortal&quot;&gt;GitHub site&lt;/a&gt;.&lt;/p&gt;
</description>
				<pubDate>Thu, 14 Jul 2016 09:16:00 +0000</pubDate>
				<link>/Announcing-the-Azure-Usage-and-Billing-Portal</link>
				<guid isPermaLink="true">/Announcing-the-Azure-Usage-and-Billing-Portal</guid>
			</item>
		
			<item>
				<title>Going from Mobile Services to Mobile Apps</title>
				<description>&lt;p&gt;I’ve held off on updating my blog to really talk about Azure Mobile Apps as I was waiting for the .NET and Node.js backends for Mobile Apps to GA.  Now that they have, I think it’s time to point every one in that direction.  I’ve posted quite a lot on using Azure Mobile Services as the backend for Android, iOS, Windows, Xamarin, and PhoneGap apps, and many of the things I’ve talked about are still important, but people should be thinking about using Azure Mobile Apps instead of Mobile Services to backend their mobile apps going forward.  I’ve put a link in all of my posts directing people here so that I can explain what’s new with Azure Mobile Apps and why you should look at them.&lt;/p&gt;

&lt;h3 id=&quot;azure-mobile-apps&quot;&gt;Azure Mobile Apps&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-value-prop/&quot;&gt;Azure Mobile Apps&lt;/a&gt; is a Platform-as-a-Service that exist to provide an easy way to set up a backend for mobile applications (running on any OS).  These backends support several features out of the box including: easy data storage, user authentication and authorization, push notifications, backend job processing, and much more.  Using something like Mobile Apps enables you to have a powerful backend that you don’t have to spend valuable time building so that you can focus on building the best client applications you can.  Several years ago, Microsoft released a service named Azure Mobile Services.  This was effectively the first version of a backend service inside Azure.  That means that Azure Mobile Apps is version 2.  In addition to all of the features that Mobile Services provided, Mobile Apps provides additional funcationlity including easy and more powerful scaling, deployment slots, traffic routing and management, VPN support, and much more.&lt;/p&gt;

&lt;p&gt;Going forward, anyone looking at using a backend service in Azure for their mobile applications should be looking at the Azure Mobile Apps service.  I’ll be posting more about using Azure Mobile Apps soon, but wanted to point people in the right direction.  You can find below a number of links relevant to Azure Mobile Apps and converting from Mobile Services:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-value-prop/&quot;&gt;What are Mobile Apps?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-migrating-from-mobile-services/&quot;&gt;Migrating your existing Mobile Service to Mobile Apps&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-value-prop-migration-from-mobile-services/&quot;&gt;How does App Service help if you’re using Mobile Services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/learning-paths/appservice-mobileapps/&quot;&gt;Mobile Apps learning map&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-dotnet-backend-how-to-use-server-sdk/&quot;&gt;Working with the Mobile Apps .NET backend&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-node-backend-how-to-use-server-sdk/&quot;&gt;Working with the Mobile Apps Node.js backend&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
				<pubDate>Fri, 04 Mar 2016 20:16:00 +0000</pubDate>
				<link>/Going-from-Mobile-Services-to-Mobile-Apps</link>
				<guid isPermaLink="true">/Going-from-Mobile-Services-to-Mobile-Apps</guid>
			</item>
		
			<item>
				<title>Creating a Node.js Azure Mobile App from OS X or Linux</title>
				<description>&lt;p&gt;In today’s post, I’m going to walk through how you can set up a new Azure Mobile App backend running Node.js entirely from OS X or Linux.  To do this we’ll use the following tools:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-install/&quot;&gt;Azure CLI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://yeoman.io/&quot;&gt;Yeoman&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/pricing/free-trial/?WT.mc_id=A3F51C28C&quot;&gt;Azure Subscription&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nodejs.org/en/&quot;&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I won’t go through installation steps for each of those pieces, you can find that at the accompanying link.  Instead we’ll focus on what to do once you have everything installed.&lt;/p&gt;

&lt;h3 id=&quot;connecting-to-you-azure-account-from-the-cli&quot;&gt;Connecting to you Azure account from the CLI&lt;/h3&gt;

&lt;p&gt;The first step is to turn on Azure Resource Management mode using the following command:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azure config mode arm&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, authenticate to your Azure account.  Open a Terminal window and enter&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azure login&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will be prompted to open a web browser and given a URL like http://aka.ms/devicelogin and a code to enter.  After entering the code and logging in with your Azure account, return to the terminal.&lt;/p&gt;

&lt;p&gt;All subscriptions available to your account will be &lt;em&gt;added&lt;/em&gt; to your local account and you’ll be connected to the first Azure subscription as the default.  If you have multiple subscriptions and want to change to a different subscription, you can first list them off with&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azure account list&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and then change subscriptions with&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azure account set &amp;lt;subscriptionNameOrId&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;creating-a-resource-group&quot;&gt;Creating a Resource Group&lt;/h3&gt;

&lt;p&gt;Within Azure, instances of any services you create are done so as part of a &lt;strong&gt;Resource Group&lt;/strong&gt;.  This is a logical container that holds related resources for an application.  What matters here is that we need to create a Resource Group before we can create any resources.  You can &lt;a href=&quot;https://azure.microsoft.com/en-us/documentation/articles/resource-group-overview/&quot;&gt;read more about Resource Groups and Azure Resource Manager (which we’ll mention a bit more delow) here&lt;/a&gt;.  To create our group, we run this command:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azure group create -n &amp;lt;ResourceGroupName&amp;gt; -l &quot;&amp;lt;Location&amp;gt;&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So for my group, I ran this command:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azure group create -n MyMobileAppResourceGroup -l &quot;West US&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Shortly there after, you’ll get the output of that command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;info:    Executing command group create
+ Getting resource group MyMobileAppResourceGroup                              
+ Creating resource group MyMobileAppResourceGroup                             
info:    Created resource group MyMobileAppResourceGroup
data:    Id:                  /subscriptions/&amp;lt;SubscriptionID&amp;gt;/resourceGroups/MyMobileAppResourceGroup
data:    Name:                MyMobileAppResourceGroup
data:    Location:            westus
data:    Provisioning State:  Succeeded
data:    Tags: null
data:    
info:    group create command OK
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now we’re ready to create our Mobile App.&lt;/p&gt;

&lt;h3 id=&quot;creating-our-mobile-app-and-sql-db&quot;&gt;Creating our Mobile App (and SQL DB)&lt;/h3&gt;

&lt;p&gt;Many resources in Azure have specific sections under them for manipulation of those resources.  You can see a full list by just running&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azure&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;at the command line.  As of writing, that includes resources such as webapps, vms, storage accounts,and many more.  What it currently doesn’t include is anything for Mobile Apps.  This means that we have to handle the creation of our Mobile App a bit differently.  Thankfully, Azure Resource Manager has support for templates (JSON files) which declaritively define a deployment.  Put planely, these are JSON files that detail the pieces involved in a deployment such as what services to create (a SQL DB and Mobile App) along with any information needed to create those resources (i.e. names, locations, usernames, passwords, etc).  You can take an existing architecture and get a template from it, or you can start with the many &lt;a href=&quot;https://github.com/Azure/azure-quickstart-templates&quot;&gt;pre-created templates available on GitHub&lt;/a&gt; to start your deployment.  Today we’re specifcially going to make use of a &lt;a href=&quot;https://github.com/Azure/azure-quickstart-templates/tree/master/101-mobile-app-create&quot;&gt;template for a Mobile App&lt;/a&gt;.  Within that repository there are two JSON files:  &lt;a href=&quot;https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-mobile-app-create/azuredeploy.json&quot;&gt;azuredeploy.json&lt;/a&gt; and &lt;a href=&quot;https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-mobile-app-create/azuredeploy.parameters.json&quot;&gt;azuredeploy.parameters.json&lt;/a&gt;.  You’ll want to download both of those files locally to your computer.&lt;/p&gt;

&lt;p&gt;Before we can deploy the template, you’ll need to edit the &lt;strong&gt;azuredeploy.parameters.json&lt;/strong&gt; file to specify the name of your Mobile App, the SQL Server username and password, and the location:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
  &quot;$schema&quot;: &quot;http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#&quot;,
  &quot;contentVersion&quot;: &quot;1.0.0.0&quot;,
  &quot;parameters&quot;: {
    &quot;appName&quot;: {
      &quot;value&quot;: &quot;mobileappfromthecli&quot;
    },
    &quot;location&quot;: {
      &quot;value&quot;: &quot;West US&quot;
    },
    &quot;sqlServerAdminLogin&quot;: {
      &quot;value&quot;: &quot;NewAdmin&quot;
    },
    &quot;sqlServerAdminPassword&quot;: {
      &quot;value&quot;: &quot;My$up3rPassWERD&quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that done, we can now deploy to Azure with this command:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azure group deployment create -f azuredeploy.json -e azuredeploy.parameters.json -g MyMobileAppResourceGroup -n MyMobileAppDeployment&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here we’re specifying the template file, the parameters file, the group to deploy to, and the name of the deployment.  This command will take a few minutes to complete but when it’s done, you should see something like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;info:    Executing command group deployment create
+ Initializing template configurations and parameters                          
+ Creating a deployment                                                        
info:    Created template deployment &quot;MyMobileAppDeployment&quot;
+ Waiting for deployment to complete                                           
data:    DeploymentName     : MyMobileAppDeployment
data:    ResourceGroupName  : MyMobileAppResourceGroup
data:    ProvisioningState  : Succeeded
data:    Timestamp          : 2016-03-04T06:25:53.9360068Z
data:    Mode               : Incremental
data:    Name                     Type          Value                       
data:    -----------------------  ------------  ----------------------------
data:    appName                  String        mobileappfromthecli         
data:    location                 String        West US                     
data:    hostingPlanSettings      Object        [object Object]             
data:    sqlServerAdminLogin      String        NewAdmin                    
data:    sqlServerAdminPassword   SecureString  undefined                   
data:    sqlDatabaseEdition       String        Basic                       
data:    sqlDatabaseCollation     String        SQL_Latin1_General_CP1_CI_AS
data:    sqlDatabaseMaxSizeBytes  String        1073741824                  
info:    group deployment create command OK
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we get a lot of details back indicating that everything was provisioned successfully.  This means that we’ve succesfully created a Mobile App, a SQL Server, a SQL Database, and a Notification Hub.  Today we’re just focusing on the Mobile App.&lt;/p&gt;

&lt;h3 id=&quot;setting-up-a-git-repo&quot;&gt;Setting up a Git repo&lt;/h3&gt;

&lt;p&gt;Unfortunately, we’ve reached an impasse as far as what can be done from the command line.  We can (and will) generate our app backend using the command line, but we can’t really set up a way to deploy that code to our Mobile App.  Instead, we’ll go to the Azure Portal to star the next step.&lt;/p&gt;

&lt;p&gt;Open up the &lt;a href=&quot;http://portal.azure.com&quot;&gt;Azure Portal&lt;/a&gt; and look for &lt;strong&gt;App Services&lt;/strong&gt; on the left navigation (if it isn’t showing up, look for &lt;strong&gt;Browse&lt;/strong&gt; at the bottom and then find &lt;strong&gt;App Services&lt;/strong&gt; from there).  Find your App Service in the list (if this is the first thing you’ve created, there will only be one listed).  We’re focusing on doing as much as possible from the command line today, but everything we’ve done so far (create our App Service and connected services) can be done from the portal along with MANY things that can’t (like what we’re about to do).  When oyu first open your App Service, the &lt;strong&gt;Settings&lt;/strong&gt; blade should be open by default, but if not, at the top of your App Service’s blade, you should see &lt;strong&gt;Settings&lt;/strong&gt; with the familiar gear image.  Click that and then in the Settings blade (to the right of your App Service), look for &lt;strong&gt;Continuous Deployment&lt;/strong&gt; underneath &lt;strong&gt;PUBLISHING&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here we’ll need to choose &lt;strong&gt;Choose Source&lt;/strong&gt; to configure deployment.  There are many (7 at writing) different options for deployment, to make things easy today, we’ll just choose &lt;strong&gt;Local Git Repository&lt;/strong&gt;.  This will create a Git repository within Azure which we can push and pull from to deploy changes to our Mobile App backend.  After a few moments, the process will complete and the body should change to say “No deployments found.”&lt;/p&gt;

&lt;p&gt;Next we need to set up credentials.  Under &lt;strong&gt;Continuous Deployment&lt;/strong&gt; you should see &lt;strong&gt;Deployment credentials&lt;/strong&gt;.  Once you’ve gone into that blade you can enter a username and password for Git and FTP.&lt;/p&gt;

&lt;p&gt;The last thing we’ll do in the portal for now is get our Git URL.  Return to the &lt;strong&gt;Settings&lt;/strong&gt; blade and scroll up to &lt;strong&gt;Properties&lt;/strong&gt;.  Within that blade you’ll see &lt;strong&gt;Git URL&lt;/strong&gt;.  Grab that for later.&lt;/p&gt;

&lt;h3 id=&quot;creating-a-node-backend&quot;&gt;Creating a Node backend&lt;/h3&gt;

&lt;p&gt;You should have already installed Yeoman (listed in the tools at the top).  I left out one tool that plugs into Yeoman.  If you haven’t used Yeoman before, it’s a tool for scaffolding out projects.  If you’ve used something like Visual Studio, Eclipse, or Xcode before, you’ve almost certainly had the File -&amp;gt; New Project experience.  When it comes to developing in Visual Studio Code (or sublime text, atom, etc), trying to create a new project type wizard for each editor would be a bit excessive.  For that reason, ther are thousands of generators that can be installed into Yeoman to help scaffold our &lt;em&gt;projects&lt;/em&gt; of all types (Node, wordpress, jeykll, asp.net, etc).  For today, you’ll need to install the azure-mobile-apps generator with this command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo npm install -g yo generator-azure-mobile-apps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that you may not &lt;em&gt;need&lt;/em&gt; to use &lt;em&gt;sudo&lt;/em&gt; but I did so I’ve included it.  Next we create our backend:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yo azure-mobile-apps&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt; that this drops files into the directory you’re in so create a directory for your app first.  That will generate a bunch of files including a fully functioning backend for our apps.&lt;/p&gt;

&lt;h3 id=&quot;deploying-to-azure&quot;&gt;Deploying to Azure&lt;/h3&gt;

&lt;p&gt;First we need to setup git locally in the directory you just created your mobile app in:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we add the remote using the Git URL that you got above:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git remote add origin https://username@MyMobileApp.scm.azurewebsites.net:443/MyMobileApp.git&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we can add, commit our files, and push to Azure:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git add .
git commit -m &quot;Initial check-in&quot;
git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’ll be prompted for the password which you entered in the credentials blade above.  It will take a few minutes to push the code up to the server and restart your site.  If you now browse to the site (you can do so easily by returning to the portal and clicking the &lt;strong&gt;Browse&lt;/strong&gt; button in the blade for your App Service) you’ll be taken to a page which says:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You’ve encountered an Azure Mobile Apps Site&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is our default homepage.  The next step is to test out the Tables and APIs functionality provided by our Mobile App.  Currently, the mobile app generator creates one table and one API, though both of them require authenticated clients.  We’ll turn off authentication in order to properly test things out (in an easier manner).&lt;/p&gt;

&lt;h3 id=&quot;turning-off-auth-and-adding-todo-items&quot;&gt;Turning off Auth and adding Todo Items&lt;/h3&gt;

&lt;p&gt;Open up &lt;a href=&quot;http://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt; (or your editor of choice) and open the directory for your Mobile App.  Inside of hte &lt;strong&gt;server&lt;/strong&gt; folder, you’ll see the folders &lt;strong&gt;api&lt;/strong&gt; and &lt;strong&gt;tables&lt;/strong&gt;.  Start by opening &lt;strong&gt;api/example.js&lt;/strong&gt;.  Near the bottom, you’ll see:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;api.get.access = 'authenticated';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You’ll need to change that to anonymous like so:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;api.get.access = 'anonymous';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you haven’t played with Mobile Apps / Services before, changing from authenticated to anonymous means we don’t have to send over a Mobile Apps Auth Token in order to call the API.  Since we’re just going to test out our APIs and tables from the command line (without a real app) we aren’t going to authenticate today.&lt;/p&gt;

&lt;p&gt;Next open up &lt;strong&gt;tables/example.js&lt;/strong&gt; and edit:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;table.access = 'disabled';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To be:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;table.access = 'anonymous';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The last thing we’ll do is add a new table for Todo Items.  Create a new file within the &lt;strong&gt;tables&lt;/strong&gt; directory and name it &lt;strong&gt;todoitem.js&lt;/strong&gt; and put in the following contents:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var azureMobileApps = require('azure-mobile-apps');

var table = azureMobileApps.table();

// Defines the list of columns
table.columns = {
    &quot;text&quot;: &quot;string&quot;,
    &quot;complete&quot;: &quot;boolean&quot;
};
// Turns off dynamic schema
table.dynamicSchema = false;

module.exports = table;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you can push all of your changes back up to Azure:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git add .
git commit -m &quot;Updating tables and APIs&quot;
git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;testing-from-the-command-line&quot;&gt;Testing from the command line&lt;/h3&gt;

&lt;p&gt;Normally, the next step would be to create an iOS, Android, or Windows app to start hitting your Mobile App backend.  That’s outside the scope of today (but if you want to get started quickly, you can go to the &lt;strong&gt;Quick Start&lt;/strong&gt; option under the &lt;strong&gt;Settings&lt;/strong&gt; for your Mobile App to generate clients quickly).  Today we’re going to test wiht CURL which is a command line tool for creating HTTP requests.  We’ll start simple and just pull down the home page.  Go to the command line and enter this (make sure you change the URL to match your app’s):&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl http://&amp;lt;YourMobileApp&amp;gt;.azurewebsites.net/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This should output the HTMl for your web page.  Next let’s try hitting our APIs:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl --header &quot;ZUMO-API-VERSION:2.0.0&quot; http://&amp;lt;YourMobileApp&amp;gt;.azurewebsites.net/api/example&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you took a look at the &lt;strong&gt;api/example.js&lt;/strong&gt; you’ll know when you do a GET request against it, it just take a data object with one value in it and returns it as JSON.  So when we make the above request, we get the following:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&quot;example&quot;:20}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next up, let’s call the tables:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl --header &quot;ZUMO-API-VERSION:2.0.0&quot; http://mobileappfromthecli-n3ajngt3gbvjs.azurewebsites.net/tables/example&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will just return &lt;strong&gt;[]&lt;/strong&gt; because the &lt;em&gt;example&lt;/em&gt; table isn’t set up to really do anything.  The Todo Item table will be much better:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;url --header &quot;ZUMO-API-VERSION:2.0.0&quot; http://mobileappfromthecli-n3ajngt3gbvjs.azurewebsites.net/tables/todoitem&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Right now, this will also return &lt;strong&gt;[]&lt;/strong&gt; becuase there is no data in our table.  Let’s add some:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl --data '{&quot;text&quot;:&quot;test&quot;,&quot;complete&quot;:false}' --header &quot;Content-Type: application/json&quot; -X POST --header &quot;ZUMO-API-VERSION:2.0.0&quot; http://mobileappfromthecli-n3ajngt3gbvjs.azurewebsites.net/tables/todoitem&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, we’re doing a similar request as before but we’re passing in &lt;strong&gt;data&lt;/strong&gt;, changing the &lt;strong&gt;Content-Type&lt;/strong&gt; with an additional header, and lastly we’re changing the request type with the &lt;strong&gt;-X&lt;/strong&gt; parameter so we can do a POST instead of a GET.  When we post that item, we’ll get back the updated item which includes the content of what we sent up in addition to the following field: id, version, createdAt, updatedAt, and deleted.&lt;/p&gt;

&lt;p&gt;Now that we’ve inserted data, let’s pull the data again and see what comes out:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;url --header &quot;ZUMO-API-VERSION:2.0.0&quot; http://mobileappfromthecli-n3ajngt3gbvjs.azurewebsites.net/tables/todoitem&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We should get back a list of all items we’ve saved so far (so in our case one item):&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[{&quot;id&quot;:&quot;427a9e3d-32a6-483f-9e51-9c4a82349d96&quot;,&quot;version&quot;:&quot;AAAAAAAAB9I=&quot;,&quot;createdAt&quot;:&quot;2016-03-04T17:48:04.368Z&quot;,&quot;updatedAt&quot;:&quot;2016-03-04T17:48:04.384Z&quot;,&quot;deleted&quot;:false,&quot;text&quot;:&quot;test&quot;,&quot;complete&quot;:false}]&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;Today we walked through how you can create an Azure Mobile App from the command line using open source tools like Yeoman, the Azure CLI, Node.js, and Visual Studio Code.  The &lt;a href=&quot;http://portal.azure.com&quot;&gt;Azure Portal&lt;/a&gt; provides a great experience for doing all of this as well, in addition to even more features that Azure Web Apps provides.&lt;/p&gt;
</description>
				<pubDate>Fri, 04 Mar 2016 20:16:00 +0000</pubDate>
				<link>/Creating-a-Node-JS-Azure-Mobile-App-from-OS-X-or-Linux</link>
				<guid isPermaLink="true">/Creating-a-Node-JS-Azure-Mobile-App-from-OS-X-or-Linux</guid>
			</item>
		
			<item>
				<title>Codemash 2016</title>
				<description>&lt;p&gt;&lt;img style=&quot;margin: 0px 0px 5px 5px; display: inline&quot; src=&quot;../upload/logo_codemash_2016.png&quot; align=&quot;right&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I just finished giving my presentation at &lt;a href=&quot;http://codemash.org&quot;&gt;Codemash 2016&lt;/a&gt; and thought it went great.  I presented on running .NET on Linux and OS X and had a nearly full room of very engaged people.  My presentation focused on ASP.NET 5 and .NET Core, their recent status as a Release Candidate, and how developers can use, run, and deploy them on Linux and OS X.  People were &lt;a href=&quot;https://twitter.com/jesseobrien_/status/685114919432404992&quot;&gt;super excited&lt;/a&gt; to see how fast you could get up to speed on running .NET on Linux.  If you’re interested in checking out my slides, you can find them &lt;a href=&quot;../presentations/2016-CodeMash-DotNetOnLinuxOSX.pptx&quot;&gt;here&lt;/a&gt;.  Thanks to all who attended and reach out to me if you have questions.&lt;/p&gt;
</description>
				<pubDate>Thu, 07 Jan 2016 20:16:00 +0000</pubDate>
				<link>/Codemash-2016</link>
				<guid isPermaLink="true">/Codemash-2016</guid>
			</item>
		
			<item>
				<title>Using Fragments with the Navigation Drawer Activity</title>
				<description>&lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt;: If you want to grab the sample code, it’s &lt;a href=&quot;https://github.com/ChrisRisner/AndroidFragmentNavigationDrawer&quot;&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve been working on a new Android application and just recently ran into a problem that I was surprised didn’t have a clearer solution.  The primary means of navigation in the app was going to be a &lt;a href=&quot;https://www.google.com/design/spec/patterns/navigation-drawer.html#navigation-drawer-specs&quot;&gt;Navigation Drawer&lt;/a&gt;.  If you’ve used an Android device, you’ve almost certainly seen and used this design pattern:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://storage.chrisrisner.com/images/android-navigation-drawer.png&quot; alt=&quot;HockeyApp Versions&quot; class=&quot;centeredInContent&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The Navigation Drawer is a slide out menu that enables users to navigate around the different areas of the application.  Typically, when the user taps one of the items on the menu, the content page is reloaded.  Instead of starting a new activity where the user has to go &lt;em&gt;back&lt;/em&gt; (via the back button or a back button in the top left of the screen), the navigation drawer (usually via the familiar &lt;a href=&quot;https://en.wikipedia.org/wiki/Hamburger_button&quot;&gt;hamburger button&lt;/a&gt;) stays available as you go from one area of the app to others (it seems like it’s common for a few pages to launch and require the back button such as Settings and Help).&lt;/p&gt;

&lt;p&gt;If you go into Android Studio right now and create a new application and base it off the Navigation Drawer Activity, you’ll get a very basic app with a single activity and the nav drawer will be set up fairly similarly to what you see above.  What you won’t see though, is how to actually navigate between different “content pages” when you tap the different menu options in the nav drawer!  If you are familiar with some Android development, this might be a bit surprising.  In earlier days of Android development the way you got from one &lt;em&gt;page&lt;/em&gt; to another was to have several &lt;em&gt;Activities&lt;/em&gt; and to use an &lt;a href=&quot;http://chrisrisner.com/31-Days-of-Android--Day-5-Adding-Multiple-Activities-and-using-Intents/&quot;&gt;intent to launch each new activity&lt;/a&gt;.  This doesn’t really mesh with the nav drawer though as you’d have to have the same nav drawer on several activities&lt;/p&gt;

&lt;h3 id=&quot;enter-the-fragment&quot;&gt;Enter the Fragment&lt;/h3&gt;
&lt;p&gt;When Android moved from 2.X to 3.X, they were moving from only focusing on phone form factors to also tablets.  3.X was never officially released to run on phones, but they started thinking about how to make page constructs that weren’t just in the form of activities tied to layouts.  The solution they came up with was &lt;a href=&quot;http://developer.android.com/guide/components/fragments.html&quot;&gt;Fragments&lt;/a&gt;.  A fragment is a way of composing a part of an activity.  It has it’s own life cycle, deals with it’s own inputs, and each activity can contain multiple fragments.  The easiest way to see fragments in action is to create a new application and use the &lt;strong&gt;Master / Detail Flow&lt;/strong&gt;.  This creates an application that works on both tablets and phones and shows how you can show multiple fragments at once (on the tablet) or a single fragment (on the phone).  The bulk of the code is the same regardless of if you’re showing one fragment or both which is part of the reason you use fragments, so you don’t have to reproduce code in multiple places.&lt;/p&gt;

&lt;h3 id=&quot;the-problem&quot;&gt;The Problem&lt;/h3&gt;
&lt;p&gt;The problem I ran into with the Navigation Drawer sample is again that it doesn’t really demonstrate how you should do navigation inside of it.  As I said before, you can always use the old route of launching new activities.  However, you’ll need to then reuse the navigation drawer everywhere.  This can be done and someone I was tweeting with about this issue even put together a &lt;a href=&quot;https://github.com/karnamsupreeth/drawersample&quot;&gt;sample of it on GitHub&lt;/a&gt;.  Unfortunately, if you run that, you’ll see that the navigation between different activities isn’t as smooth as I’d like it to be.  Namely, the nav drawer doesn’t slide back before showing the new activities content.  What I want to happen is when the user taps an item on the nav drawer, the content page should already be loading / loaded while the drawer slides back to be closed.  As far as I’ve seen so far, this can’t be done with multiple activities.  But it can with fragments.  One thing to note is that I believe you could also do custom view inflation and deflation though you’d be wrapping everything in one activity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: After I’d already started this post, &lt;em&gt;karnamsupreeth&lt;/em&gt; updated his code sample to provide a brief delay after tapping a nav item and launching the new activity.  This was MUCH closer to what I originally thought of and is a valid way of handling things if you want to use Activities.  I’ll continue to post the fragment solution but I’d definitely consider using his example as well.  It still doesn’t actually &lt;em&gt;load&lt;/em&gt; the new activity until after the delay so you’re note sliding the drawer back to reveal the new content that has been loaded.&lt;/p&gt;

&lt;h3 id=&quot;whats-wrong-with-fragments&quot;&gt;What’s wrong with Fragments&lt;/h3&gt;
&lt;p&gt;Before I get into the specifics of adding fragments to the nav drawer sample, I just want to say that I don’t hate fragments, I just don’t like them.  Just a few &lt;a href=&quot;https://www.google.com/webhp?sourceid=chrome-instant&amp;amp;ion=1&amp;amp;espv=2&amp;amp;ie=UTF-8#q=fragments%20vs%20activities&quot;&gt;searches&lt;/a&gt; online will yield a lot of conversations about whether fragments are good or &lt;a href=&quot;https://corner.squareup.com/2014/10/advocating-against-android-fragments.html&quot;&gt;bad&lt;/a&gt;.  Because fragments live inside of an activity, and both the activity and fragment have life cycle and event handling, things can be overly complex.  Additionally there are memory implications and other concerns you might run into.  Suffice to say, I’m going forward with fragments in my solution though that doesn’t mean I’m sold on them being the best solution.&lt;/p&gt;

&lt;h3 id=&quot;the-initial-layout&quot;&gt;The Initial Layout&lt;/h3&gt;
&lt;p&gt;When you first create the Navigation Drawer Activity, there are 5 files we’ll look at:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;MainActivity.java - this is the code behind for everything in our app.&lt;/li&gt;
  &lt;li&gt;activity_main.xml - this is the layout for the app including the nav drawer and an &lt;em&gt;include&lt;/em&gt; for the app_bar_main.&lt;/li&gt;
  &lt;li&gt;app_bar_main.xml - this is the layout with the toolbar (at the top), a floating action button (at the bottom right), and an &lt;em&gt;include&lt;/em&gt; for content_main.&lt;/li&gt;
  &lt;li&gt;content_main.xml - this is the layout for the &lt;em&gt;content&lt;/em&gt; of the main page.&lt;/li&gt;
  &lt;li&gt;nav_header_main.xml - this is the UI for the top part of the nav drawer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now I’ve already said that I don’t think this is the best example of how to do navigation because it doesn’t show you what to do when you tap an item in the nav drawer (it only demonstrates how to get the event when an item is tapped in the &lt;strong&gt;onNavigationItemSelected&lt;/strong&gt; method).  Furthermore, from looking at how it displays the content, it’s not clear what to do.  In the &lt;strong&gt;MainActivity&lt;/strong&gt;’s &lt;em&gt;onCreate&lt;/em&gt; method there is a call to:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;setContentView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;activity_main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is what you typically see in an Activity and binds the UI of a layout file to the Activity code.  In this case, the activity_main layout contains the nav drawer and an &lt;em&gt;include&lt;/em&gt; statement for the app_bar_main.  The app_bar_main in turn contains the toolbar at the top and does an &lt;em&gt;include&lt;/em&gt; on the content_main.  It would seem like the solution is to replace the content of the second &lt;em&gt;include&lt;/em&gt; whenever the user taps an item on the menu.  However, you can’t really replace an &lt;em&gt;include&lt;/em&gt; like that.  We could use custom views and inflate and replace them whenever we want, but that might require a significant amount of additional work (or maybe not, hopefully someone can provide a solution that does that).  Adding fragments ends up being relatively easy.&lt;/p&gt;

&lt;h3 id=&quot;adding-fragments-to-the-sample&quot;&gt;Adding Fragments to the Sample&lt;/h3&gt;
&lt;p&gt;First, open up the &lt;strong&gt;app_bar_main.xml&lt;/strong&gt;, comment out the &lt;em&gt;include&lt;/em&gt; and add a new &lt;em&gt;FrameLayout&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!--&amp;lt;include layout=&quot;@layout/content_main&quot; /&amp;gt;--&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;FrameLayout&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;android:id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@+id/flContent&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;android:layout_width=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;match_parent&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;android:layout_height=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;match_parent&quot;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;android:layout_marginTop=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;?attr/actionBarSize&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This &lt;em&gt;FrameLayout&lt;/em&gt; is what we’ll use to load our fragments into.  Next, you’ll want to add a few fragments.  To do so, right click on your project, or go to File –&amp;gt; New and from the Fragment list choose &lt;em&gt;Fragment (Blank)&lt;/em&gt;.  Add at least two fragments to your project so you can demonstrate moving between them.  The next step is to load a fragment when the app first launches.  Go to the &lt;strong&gt;MainActivity&lt;/strong&gt;’s &lt;em&gt;onCreate&lt;/em&gt; method and put the following in after the call to &lt;strong&gt;setSupportActionBar&lt;/strong&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nc&quot;&gt;Fragment&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FragmentOne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fragment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Fragment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;newInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;FragmentManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragmentManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSupportFragmentManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fragmentManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;beginTransaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flContent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You’ll then need to add &lt;strong&gt;OnFragmentInteractionListener&lt;/strong&gt; to the interfaces your MainActivity implements and also implement the &lt;strong&gt;onFragmentInteraction&lt;/strong&gt; method.  Finally, in the &lt;strong&gt;onNavigationItemSelected&lt;/strong&gt; method, you can add the ability to load different fragments when menu items are tapped:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onNavigationItemSelected&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MenuItem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Handle navigation view item clicks here.&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getItemId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Fragment&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nav_camera&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FragmentOne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nav_gallery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FragmentTwo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nav_slideshow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FragmentOne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nav_manage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FragmentTwo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nav_share&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FragmentOne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nav_send&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FragmentTwo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fragment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Fragment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragmentClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;newInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;FragmentManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragmentManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSupportFragmentManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fragmentManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;beginTransaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flContent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fragment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;nc&quot;&gt;DrawerLayout&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drawer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DrawerLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;findViewById&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;drawer_layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;drawer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;closeDrawer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GravityCompat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;START&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here I’m just loading one of the two fragments I’ve added to my app.  Note that because I have two different fragments, I had to implement the interfaces for both &lt;strong&gt;FragmentOne.OnFragmentInteractionListener&lt;/strong&gt; and &lt;strong&gt;FragmentTwo.OnFragmentInteractionListener&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s all you need to do to implement fragment loading in your Navigation Drawer.  What the user taps a menu item, the drawer will slide back in smoothly and the new fragment will have already started / finished loading.  This also prevents any possible jankiness that you &lt;em&gt;could&lt;/em&gt; see when launching a new activity.  One last thing to note is that if you switch to a different fragment and then rotate the device or cause another recreation of the activity, the code above will cause the first fragment to be reloaded.  One easy way to deal with that is to  wrap the fragment block in the &lt;em&gt;onCreate&lt;/em&gt; method in a check to see if the &lt;strong&gt;savedInstanceState&lt;/strong&gt; is not null like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onCreate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Bundle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;savedInstanceState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;savedInstanceState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//Fragment load code&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;One actual last thing is that there are definitely optimizations you could make on the code and event handling here but this is a good start.  You can grab the &lt;a href=&quot;https://github.com/ChrisRisner/AndroidFragmentNavigationDrawer&quot;&gt;source code from this demo on GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
				<pubDate>Mon, 07 Dec 2015 20:16:00 +0000</pubDate>
				<link>/Using-Fragments-with-the-Navigation-Drawer-Activity</link>
				<guid isPermaLink="true">/Using-Fragments-with-the-Navigation-Drawer-Activity</guid>
			</item>
		
	</channel>
</rss>
