<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>DevHawk</title>
    <link>http://devhawk.net/</link>
    <description>Passion * Technology * Ruthless Competence</description>
    <lastBuildDate>Mon, 21 Oct 2019 13:48:00 GMT</lastBuildDate>
    <item>
      <title>Hawk Notes, Volume 4</title>
      <link>http://devhawk.net/blog/2019/10/21/hawk-notes-vol-4</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Mon, 21 Oct 2019 13:48:00 GMT</pubDate>
      <guid>http://devhawk.net/blog/2019/10/21/hawk-notes-vol-4</guid>
      <category domain="urn:devhawk-net:category">General Geekery</category>
      <category domain="urn:devhawk-net:tag">Blogging</category>
      <category domain="urn:devhawk-net:tag">Hawk</category>
      <category domain="urn:devhawk-net:tag">ASP.NET</category>
      <description><![CDATA[<p>I rolled out a small update to my blog: It's now reading the blog posts
from a <a href="https://github.com/devhawk/blog-posts">GitHub repo</a> instead of an
Azure DevOps repo.</p>
<p>Only reason for the swap is to get programmatic public access to the repo.
Azure DevOps
<a href="https://docs.microsoft.com/en-us/azure/devops/organizations/public/about-public-projects?view=azure-devops">supports public projects</a>
but REST access still appears to
<a href="https://docs.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/authentication-guidance?view=azure-devops">require authentication</a>.
Personal Access Tokens work just fine, but they expire which is a pain
in the backside.</p>
<p>Maybe anonymous access to Azure Repos REST services gets enabled in the future,
but I didn't want to wait. It was pretty easy to port the
<a href="https://docs.microsoft.com/en-us/azure/devops/integrate/concepts/dotnet-client-libraries?view=azure-devops">Azure DevOps REST Wrapper</a>
to <a href="https://github.com/octokit/octokit.net">Octokit</a>. My code was already using
<a href="https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/dataflow-task-parallel-library">TPL Dataflow</a>
to load all the post metadata from the Azure Git repo. All I really needed to do
was change the client initialization code and the URL construction scheme
and I was good to go.</p>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I rolled out a small update to my blog: It's now reading the blog posts
from a <a href="https://github.com/devhawk/blog-posts">GitHub repo</a> instead of an
Azure DevOps repo.</p>
<p>Only reason for the swap is to get programmatic public access to the repo.
Azure DevOps
<a href="https://docs.microsoft.com/en-us/azure/devops/organizations/public/about-public-projects?view=azure-devops">supports public projects</a>
but REST access still appears to
<a href="https://docs.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/authentication-guidance?view=azure-devops">require authentication</a>.
Personal Access Tokens work just fine, but they expire which is a pain
in the backside.</p>
<p>Maybe anonymous access to Azure Repos REST services gets enabled in the future,
but I didn't want to wait. It was pretty easy to port the
<a href="https://docs.microsoft.com/en-us/azure/devops/integrate/concepts/dotnet-client-libraries?view=azure-devops">Azure DevOps REST Wrapper</a>
to <a href="https://github.com/octokit/octokit.net">Octokit</a>. My code was already using
<a href="https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/dataflow-task-parallel-library">TPL Dataflow</a>
to load all the post metadata from the Azure Git repo. All I really needed to do
was change the client initialization code and the URL construction scheme
and I was good to go.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Hawk Notes, Volume 3</title>
      <link>http://devhawk.net/blog/2019/6/17/hawk-notes-vol-3</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Mon, 17 Jun 2019 13:48:00 GMT</pubDate>
      <guid>http://devhawk.net/blog/2019/6/17/hawk-notes-vol-3</guid>
      <category domain="urn:devhawk-net:category">General Geekery</category>
      <category domain="urn:devhawk-net:tag">Blogging</category>
      <category domain="urn:devhawk-net:tag">Hawk</category>
      <category domain="urn:devhawk-net:tag">ASP.NET</category>
      <description><![CDATA[<p>I just rolled out a new feature for my blog: <a href="/blog/series">Series</a>.</p>
<p>Back when I was working for the IronPython team, I would write series of posts on a single topic, such as <a href="/blog/2009/2/27/writing-an-ironpython-debugger-introduction">writing an IronPython debugger</a> or <a href="/blog/2009/4/20/introducing-__clrtype__-metaclasses">using IronPython's __clrtype__ metaclass feature</a>. I've also written series on <a href="/blog/2007/12/10/practical-parsing-in-f">building parsers in F#</a>, <a href="/blog/2014/4/25/brokered-winrt-components-step-by-step">a step-by-step guide to brokered WinRT components</a> and the <a href="/2015/9/8/hawk-notes-vol-1">home grown engine I use for this blog</a>. And with the <a href="/blog/2019/6/2/my-next-adventure">new job</a>, I suspect I'll be writing even more.</p>
<p>So I decided to make series a first class construct in my blog. You can go to a top level page to see <a href="/blog/series">all my series</a>. Or you can go to a specific series page, such as the one for <a href="/blog/series/hawk-notes">Hawk Notes</a>. One thing I really like about Series is that they display in chronological order. That makes reading a series like the <a href="/blog/series/writing-an-ironpython-debugger">IronPython Debugger</a> much easier to follow.</p>
<p>Implementing Series was fairly straightforward...or at least it would have been if I hadn't decided to significantly refactor the service code. I didn't like how I was handling configuration - too much direct config reading that was better handled by <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options">options</a>. I made some poor service design decisions that limited the use of <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection">dependency injection</a>. Most of all, I wanted to change the way <a href="https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory">memory caching</a> worked so that more data loaded on demand instead of ahead of time. I also took the opportunity to use newer language constructs like <a href="https://docs.microsoft.com/en-us/dotnet/api/system.valuetuple">value tuples</a> and <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions">local functions</a>.</p>
<p>I still have two different sources for posts - the local file system and an <a href="https://azure.microsoft.com/en-us/services/devops/repos/">Azure Repo</a>. I used to use <a href="https://docs.microsoft.com/en-us/azure/storage/">Azure Storage</a> but I got rid of that source as part of this refactoring. I have a simple interface PostLoader<a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a> which the AzureGitLoader and FileSystemLoader classes implement. In order to select between them at run time, I have a third PostLoader implementation named PostLoaderSelector. PostLoaderSelector chooses between the sources based on configuration and uses <a href="https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider">IServiceProvider</a> to activate the specified type from the DI container. PostLoaderSelector gets the IServiceProvider instance via constructor injection. I couldn't find a good example of how to manually activate types from ASP.NET's DI container, so for future reference it looks like this:</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#0000FF;">public</span> Task&lt;IEnumerable&lt;Post&gt;&gt; LoadPostsAsync()
{
    <span style="color:#008000;">// Look Ma, a Local Function!</span>
    PostLoader GetLoader()
    {
        <span style="color:#0000FF;">switch</span> (options.PostStorage)
        {
            <span style="color:#0000FF;">case</span> BlogOptions.PostStorageType.FileSystem:
                <span style="color:#0000FF;">return</span> serviceProvider.GetService&lt;FileSystemLoader&gt;();
            <span style="color:#0000FF;">case</span> BlogOptions.PostStorageType.AzureGit:
                <span style="color:#0000FF;">return</span> serviceProvider.GetService&lt;AzureGitLoader&gt;();
            <span style="color:#0000FF;">default</span>:
                <span style="color:#0000FF;">throw</span> <span style="color:#0000FF;">new</span> NotImplementedException();
        }
    };

    <span style="color:#0000FF;">var</span> loader = GetLoader();
    <span style="color:#0000FF;">return</span> loader.LoadPostsAsync();
}
</pre></div>
<div class="footnotes">
<hr />
<ol>
<li id="fn:1">
<p>Note the lack of the &quot;I&quot; prefix for my interface type names. Death to this final vestigal Hungarian notation!<a href="#fnref:1" class="footnote-back-ref">&#8617;</a></p>
</li>
</ol>
</div>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>I just rolled out a new feature for my blog: <a href="/blog/series">Series</a>.</p>
<p>Back when I was working for the IronPython team, I would write series of posts on a single topic, such as <a href="/blog/2009/2/27/writing-an-ironpython-debugger-introduction">writing an IronPython debugger</a> or <a href="/blog/2009/4/20/introducing-__clrtype__-metaclasses">using IronPython's __clrtype__ metaclass feature</a>. I've also written series on <a href="/blog/2007/12/10/practical-parsing-in-f">building parsers in F#</a>, <a href="/blog/2014/4/25/brokered-winrt-components-step-by-step">a step-by-step guide to brokered WinRT components</a> and the <a href="/2015/9/8/hawk-notes-vol-1">home grown engine I use for this blog</a>. And with the <a href="/blog/2019/6/2/my-next-adventure">new job</a>, I suspect I'll be writing even more.</p>
<p>So I decided to make series a first class construct in my blog. You can go to a top level page to see <a href="/blog/series">all my series</a>. Or you can go to a specific series page, such as the one for <a href="/blog/series/hawk-notes">Hawk Notes</a>. One thing I really like about Series is that they display in chronological order. That makes reading a series like the <a href="/blog/series/writing-an-ironpython-debugger">IronPython Debugger</a> much easier to follow.</p>
<p>Implementing Series was fairly straightforward...or at least it would have been if I hadn't decided to significantly refactor the service code. I didn't like how I was handling configuration - too much direct config reading that was better handled by <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options">options</a>. I made some poor service design decisions that limited the use of <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection">dependency injection</a>. Most of all, I wanted to change the way <a href="https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory">memory caching</a> worked so that more data loaded on demand instead of ahead of time. I also took the opportunity to use newer language constructs like <a href="https://docs.microsoft.com/en-us/dotnet/api/system.valuetuple">value tuples</a> and <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions">local functions</a>.</p>
<p>I still have two different sources for posts - the local file system and an <a href="https://azure.microsoft.com/en-us/services/devops/repos/">Azure Repo</a>. I used to use <a href="https://docs.microsoft.com/en-us/azure/storage/">Azure Storage</a> but I got rid of that source as part of this refactoring. I have a simple interface PostLoader<a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a> which the AzureGitLoader and FileSystemLoader classes implement. In order to select between them at run time, I have a third PostLoader implementation named PostLoaderSelector. PostLoaderSelector chooses between the sources based on configuration and uses <a href="https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider">IServiceProvider</a> to activate the specified type from the DI container. PostLoaderSelector gets the IServiceProvider instance via constructor injection. I couldn't find a good example of how to manually activate types from ASP.NET's DI container, so for future reference it looks like this:</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#0000FF;">public</span> Task&lt;IEnumerable&lt;Post&gt;&gt; LoadPostsAsync()
{
    <span style="color:#008000;">// Look Ma, a Local Function!</span>
    PostLoader GetLoader()
    {
        <span style="color:#0000FF;">switch</span> (options.PostStorage)
        {
            <span style="color:#0000FF;">case</span> BlogOptions.PostStorageType.FileSystem:
                <span style="color:#0000FF;">return</span> serviceProvider.GetService&lt;FileSystemLoader&gt;();
            <span style="color:#0000FF;">case</span> BlogOptions.PostStorageType.AzureGit:
                <span style="color:#0000FF;">return</span> serviceProvider.GetService&lt;AzureGitLoader&gt;();
            <span style="color:#0000FF;">default</span>:
                <span style="color:#0000FF;">throw</span> <span style="color:#0000FF;">new</span> NotImplementedException();
        }
    };

    <span style="color:#0000FF;">var</span> loader = GetLoader();
    <span style="color:#0000FF;">return</span> loader.LoadPostsAsync();
}
</pre></div>
<div class="footnotes">
<hr />
<ol>
<li id="fn:1">
<p>Note the lack of the &quot;I&quot; prefix for my interface type names. Death to this final vestigal Hungarian notation!<a href="#fnref:1" class="footnote-back-ref">&#8617;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Hawk Notes, Volume 2</title>
      <link>http://devhawk.net/blog/2019/6/6/hawk-notes-vol-2</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Thu, 06 Jun 2019 20:20:00 GMT</pubDate>
      <guid>http://devhawk.net/blog/2019/6/6/hawk-notes-vol-2</guid>
      <category domain="urn:devhawk-net:category">General Geekery</category>
      <category domain="urn:devhawk-net:tag">Blogging</category>
      <category domain="urn:devhawk-net:tag">Hawk</category>
      <category domain="urn:devhawk-net:tag">ASP.NET</category>
      <description><![CDATA[<p>Obviously, I've been pretty bad about keeping this blog up to date. That applies to both the content of the blog as well as the blog engine. Frankly, the <a href="http://devhawk.net/blog/2015/9/8/hawk-notes-vol-1">last time I updated my blog code</a> before last weekend was <em>four years ago</em>. At the time, ASP.NET Core was still called ASP.NET 5 and the latest version was Preview 7. Before posting <a href="http://devhawk.net/blog/2019/6/2/my-next-adventure">my recent announcement</a>, I thought it might be a good idea to get this blog running on a released and supported version of ASP.NET Core.</p>
<p>Once I got my code updated to the latest version of ASP.NET, I decided actually add some functionality. When I built Hawk, I focused primarily on how the site was going to render my existing content. I didn't give much though to how I would write new blog posts. That turned out to be a bad decision. Getting new posts published turned out to be such a huge pain in the butt that I bothered to write new posts. With the new job, I want to go back to blogging much more often. So I figured I should update the engine to make publishing new posts easier.</p>
<p>As I wrote in <a href="http://devhawk.net/blog/2015/9/8/hawk-notes-vol-1">my previous Hawk Note</a>, Hawk loads all the post metadata into memory on startup. It supports loading posts from either the file system as well as from Azure Storage. The master copy of my posts are stored in their own <del>Visual Studio Online</del> <del>Visual Studio Team Services</del> Azure DevOps Repos. Moving posts from the git repo into azure storage turned out the be the biggest publishing obstacle. So I decided to eliminate that step. If you're reading this, I guess it worked!</p>
<p>Since Hawk already supported loading posts from two different repositories, it was pretty straight forward to add a third that reads directly from the Azure Repo. I also added code to render the markdown to HTML using <a href="https://github.com/lunet-io/markdig">Markdig</a>, eliminating the need <a href="http://devhawk.net/blog/2015/9/2/the-brilliant-magic-of-edgejs">to use Edge.js</a><a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a>.</p>
<p>Originally, I decided to store my blog posts in what is now called Azure Repos because it offered free private repos for personal use. While GitHub <a href="https://github.blog/2016-05-11-introducing-unlimited-private-repositories/">now offers</a> free private repos, I've decided to keep my posts in an Azure Repos because I find the <a href="https://docs.microsoft.com/en-us/rest/api/azure/devops/git/?view=azure-devops-rest-5.0">Azure DevOps REST interface</a> much easier to wrap my head around than <a href="https://github.blog/2016-09-14-the-github-graphql-api/">GitHub's GraphQL based approach</a>. Yeah, I'm sure GraphQL is the better approach. But I was able to add the ability to load posts from Azure Repos in roughly 150 lines of code. For now anyway, easy and proven beats newer and more powerful.</p>
<p>Hawk pulling from the Azure Repo is the first step for creating a simple publishing process. Next, I will to set up a <a href="https://docs.microsoft.com/en-us/azure/devops/integrate/concepts/service-hooks?view=azure-devops">service hook</a> to automatically trigger a Hawk refresh when I push to the post repo master branch. Eventually, I also want to add image publishing and maybe some type tool to help author the post metadata (auto set the date, auto slugify the title, validate categories and tags, etc). I also want to re-enable comments, though social media makes that somewhat less important than it was back in the day. Regardless, I figure it's best to tackle improvements incrementally. Last thing I want is another long silence on this blog.</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:1">
<p>Note, I might not use Edge.js in Hawk anymore, but I <em>still</em> think <a href="http://tomasz.janczuk.org/">Tomasz Janczuk</a> must be some kind of a wizard.<a href="#fnref:1" class="footnote-back-ref">&#8617;</a></p>
</li>
</ol>
</div>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Obviously, I've been pretty bad about keeping this blog up to date. That applies to both the content of the blog as well as the blog engine. Frankly, the <a href="http://devhawk.net/blog/2015/9/8/hawk-notes-vol-1">last time I updated my blog code</a> before last weekend was <em>four years ago</em>. At the time, ASP.NET Core was still called ASP.NET 5 and the latest version was Preview 7. Before posting <a href="http://devhawk.net/blog/2019/6/2/my-next-adventure">my recent announcement</a>, I thought it might be a good idea to get this blog running on a released and supported version of ASP.NET Core.</p>
<p>Once I got my code updated to the latest version of ASP.NET, I decided actually add some functionality. When I built Hawk, I focused primarily on how the site was going to render my existing content. I didn't give much though to how I would write new blog posts. That turned out to be a bad decision. Getting new posts published turned out to be such a huge pain in the butt that I bothered to write new posts. With the new job, I want to go back to blogging much more often. So I figured I should update the engine to make publishing new posts easier.</p>
<p>As I wrote in <a href="http://devhawk.net/blog/2015/9/8/hawk-notes-vol-1">my previous Hawk Note</a>, Hawk loads all the post metadata into memory on startup. It supports loading posts from either the file system as well as from Azure Storage. The master copy of my posts are stored in their own <del>Visual Studio Online</del> <del>Visual Studio Team Services</del> Azure DevOps Repos. Moving posts from the git repo into azure storage turned out the be the biggest publishing obstacle. So I decided to eliminate that step. If you're reading this, I guess it worked!</p>
<p>Since Hawk already supported loading posts from two different repositories, it was pretty straight forward to add a third that reads directly from the Azure Repo. I also added code to render the markdown to HTML using <a href="https://github.com/lunet-io/markdig">Markdig</a>, eliminating the need <a href="http://devhawk.net/blog/2015/9/2/the-brilliant-magic-of-edgejs">to use Edge.js</a><a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a>.</p>
<p>Originally, I decided to store my blog posts in what is now called Azure Repos because it offered free private repos for personal use. While GitHub <a href="https://github.blog/2016-05-11-introducing-unlimited-private-repositories/">now offers</a> free private repos, I've decided to keep my posts in an Azure Repos because I find the <a href="https://docs.microsoft.com/en-us/rest/api/azure/devops/git/?view=azure-devops-rest-5.0">Azure DevOps REST interface</a> much easier to wrap my head around than <a href="https://github.blog/2016-09-14-the-github-graphql-api/">GitHub's GraphQL based approach</a>. Yeah, I'm sure GraphQL is the better approach. But I was able to add the ability to load posts from Azure Repos in roughly 150 lines of code. For now anyway, easy and proven beats newer and more powerful.</p>
<p>Hawk pulling from the Azure Repo is the first step for creating a simple publishing process. Next, I will to set up a <a href="https://docs.microsoft.com/en-us/azure/devops/integrate/concepts/service-hooks?view=azure-devops">service hook</a> to automatically trigger a Hawk refresh when I push to the post repo master branch. Eventually, I also want to add image publishing and maybe some type tool to help author the post metadata (auto set the date, auto slugify the title, validate categories and tags, etc). I also want to re-enable comments, though social media makes that somewhat less important than it was back in the day. Regardless, I figure it's best to tackle improvements incrementally. Last thing I want is another long silence on this blog.</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:1">
<p>Note, I might not use Edge.js in Hawk anymore, but I <em>still</em> think <a href="http://tomasz.janczuk.org/">Tomasz Janczuk</a> must be some kind of a wizard.<a href="#fnref:1" class="footnote-back-ref">&#8617;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>My Next Adventure</title>
      <link>http://devhawk.net/blog/2019/6/2/my-next-adventure</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Sun, 02 Jun 2019 15:30:00 GMT</pubDate>
      <guid>http://devhawk.net/blog/2019/6/2/my-next-adventure</guid>
      <category domain="urn:devhawk-net:category">Personal</category>
      <category domain="urn:devhawk-net:tag">Working at MSFT</category>
      <category domain="urn:devhawk-net:tag">NEO</category>
      <category domain="urn:devhawk-net:tag">NEO Global Development</category>
      <description><![CDATA[<p>Friday June 7th will be my last day at Microsoft.</p>
<p>I've been at Microsoft longer than I've been a husband, longer than I've been a father, longer than I've lived in the Pacific Northwest. It's been an awesome twenty year plus ride, but the time has come for me to take on new challenges.</p>
<p>I'm joining NEO Global Development's <a href="https://neonewstoday.com/general/neo-global-development-to-open-new-office-in-seattle-us/">brand new Seattle office</a> (which is really in Redmond). NEO is a <a href="https://github.com/neo-project">community driven open source project</a> delivering the technical underpinnings for the Smart Economy. NEO Global Development (aka NGD) is the technical R&amp;D arm of the NEO Foundation, the NEO project's governing body. I'm going to be the Chief Architect for the Seattle office.</p>
<p>This move will reunite me with former colleague and long-time friend John deVadoss. I worked for John for back in my <a href="http://devhawk.net/blog/2004/7/9/architecture-center-banner">Architecture Strategy Team days</a>. John is the director of NGD's Seattle office and I'm thrilled to be working with him again.</p>
<p>I had the privilege of <a href="https://www.youtube.com/watch?v=DjSSvE7OmOI&amp;t=22191s">presenting</a> at <a href="https://devcon.neo.org/">NEO DevCon</a> back in February. It was inspiring to meet folks from NEO's global community. NGD's main office is in Shanghai, <a href="https://nspcc.ru/en/">NSPCC</a> is in St. Petersberg, <a href="https://neoresearch.io/">NeoResearch</a> is in Brasil and the <a href="https://cityofzion.io">City of Zion</a> community has <a href="https://cityofzion.io/team/">team members</a> from all corners of the Earth. I can't lie - the opportunity to work with this far reaching and diverse global community was a big selling point for me joining NGD Seattle.</p>
<p>NGD Seattle's primary focus is on developer tools and experience ('natch) for the NEO platform. John and my-soon-to-be-colleague Longfei Wang <a href="https://neonewstoday.com/development/john-devadoss-longfei-wang-introduce-neo-toolkit-for-visual-studio-and-neo-express-node-at-consensus-2019/">previewed</a> a few things we're working on last month at Consensus 2019. In particular <a href="https://www.youtube.com/watch?v=GE-3qhtQ9GI">John showed off</a> NEO Express Node, a private NEO blockchain management tool that I built. Of course, the Consensus preview is just a small taste of what we plan to deliver - especially once I join NGD full time and we build out more of our Seattle based engineering team.</p>
<p>While developer experience will be my primary focus, I also expect to pitch in on the core NEO platform. NEO 3.0 development is <a href="https://medium.com/neo-smart-economy/roadmap-of-neo-3-0-development-e2ae64edf226">already in full swing</a>. Core platform might not be my focus, but platform capabilities and developer experience go hand in hand. I'm sure I'll have plenty of opportunity to contibute to the core as we work towards our 3.0 release.</p>
<p>I'll miss Microsoft - especially the amazing people I've had the opportunity to work with over the years. It's particularly hard to leave the <a href="https://github.com/Microsoft/xlang">xlang project</a>. Cross platform language projection has been a passion project of mine for several years now. Knowing xlang is in the capable hands of folks like <a href="https://codeandacookie.wordpress.com/">Ben</a>, <a href="https://twitter.com/scottj1s">Scott</a>, <a href="https://twitter.com/RyanocerosBone">Ryan</a> and <a href="https://kennykerr.ca/">Kenny</a> does make it easier. Besides, xlang is open source so I can still submit PRs if I get really Microsoft-homesick, right?</p>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Friday June 7th will be my last day at Microsoft.</p>
<p>I've been at Microsoft longer than I've been a husband, longer than I've been a father, longer than I've lived in the Pacific Northwest. It's been an awesome twenty year plus ride, but the time has come for me to take on new challenges.</p>
<p>I'm joining NEO Global Development's <a href="https://neonewstoday.com/general/neo-global-development-to-open-new-office-in-seattle-us/">brand new Seattle office</a> (which is really in Redmond). NEO is a <a href="https://github.com/neo-project">community driven open source project</a> delivering the technical underpinnings for the Smart Economy. NEO Global Development (aka NGD) is the technical R&amp;D arm of the NEO Foundation, the NEO project's governing body. I'm going to be the Chief Architect for the Seattle office.</p>
<p>This move will reunite me with former colleague and long-time friend John deVadoss. I worked for John for back in my <a href="http://devhawk.net/blog/2004/7/9/architecture-center-banner">Architecture Strategy Team days</a>. John is the director of NGD's Seattle office and I'm thrilled to be working with him again.</p>
<p>I had the privilege of <a href="https://www.youtube.com/watch?v=DjSSvE7OmOI&amp;t=22191s">presenting</a> at <a href="https://devcon.neo.org/">NEO DevCon</a> back in February. It was inspiring to meet folks from NEO's global community. NGD's main office is in Shanghai, <a href="https://nspcc.ru/en/">NSPCC</a> is in St. Petersberg, <a href="https://neoresearch.io/">NeoResearch</a> is in Brasil and the <a href="https://cityofzion.io">City of Zion</a> community has <a href="https://cityofzion.io/team/">team members</a> from all corners of the Earth. I can't lie - the opportunity to work with this far reaching and diverse global community was a big selling point for me joining NGD Seattle.</p>
<p>NGD Seattle's primary focus is on developer tools and experience ('natch) for the NEO platform. John and my-soon-to-be-colleague Longfei Wang <a href="https://neonewstoday.com/development/john-devadoss-longfei-wang-introduce-neo-toolkit-for-visual-studio-and-neo-express-node-at-consensus-2019/">previewed</a> a few things we're working on last month at Consensus 2019. In particular <a href="https://www.youtube.com/watch?v=GE-3qhtQ9GI">John showed off</a> NEO Express Node, a private NEO blockchain management tool that I built. Of course, the Consensus preview is just a small taste of what we plan to deliver - especially once I join NGD full time and we build out more of our Seattle based engineering team.</p>
<p>While developer experience will be my primary focus, I also expect to pitch in on the core NEO platform. NEO 3.0 development is <a href="https://medium.com/neo-smart-economy/roadmap-of-neo-3-0-development-e2ae64edf226">already in full swing</a>. Core platform might not be my focus, but platform capabilities and developer experience go hand in hand. I'm sure I'll have plenty of opportunity to contibute to the core as we work towards our 3.0 release.</p>
<p>I'll miss Microsoft - especially the amazing people I've had the opportunity to work with over the years. It's particularly hard to leave the <a href="https://github.com/Microsoft/xlang">xlang project</a>. Cross platform language projection has been a passion project of mine for several years now. Knowing xlang is in the capable hands of folks like <a href="https://codeandacookie.wordpress.com/">Ben</a>, <a href="https://twitter.com/scottj1s">Scott</a>, <a href="https://twitter.com/RyanocerosBone">Ryan</a> and <a href="https://kennykerr.ca/">Kenny</a> does make it easier. Besides, xlang is open source so I can still submit PRs if I get really Microsoft-homesick, right?</p>
]]></content:encoded>
    </item>
    <item>
      <title>Hawk Notes, Volume 1</title>
      <link>http://devhawk.net/blog/2015/9/8/hawk-notes-vol-1</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Tue, 08 Sep 2015 05:32:00 GMT</pubDate>
      <guid>http://devhawk.net/blog/2015/9/8/hawk-notes-vol-1</guid>
      <category domain="urn:devhawk-net:category">General Geekery</category>
      <category domain="urn:devhawk-net:tag">Blogging</category>
      <category domain="urn:devhawk-net:tag">Hawk</category>
      <category domain="urn:devhawk-net:tag">ASP.NET</category>
      <description><![CDATA[<p>This is the first in a series of blog posts about <a href="https://github.com/devhawk/Hawk">Hawk</a>, the engine that powers this site.
My plan is to make a post like this for every significant update to the site. We'll see well that plan works.</p>
<ul>
<li>I just pushed out a new version of Hawk on my website. The primary feature of this release is support for
<a href="http://blogs.msdn.com/b/webdev/archive/2015/09/02/announcing-availability-of-asp-net-5-beta7.aspx">ASP.NET 5 Beta 7</a>.
I also published the <a href="https://github.com/devhawk/Hawk">source code</a> up on GitHub. Feedback welcome!</li>
<li>As I mentioned in <a href="/blog/2015/09/02/the-brilliant-magic-of-edgejs">my post on Edge.js</a>, the publishing tools
for Hawk is little more than duct tape and bailing wire at this point. Eventually, I'd like to have a
dedicated tool, but for now it's a manual three step process:
<ol>
<li>Run the <a href="https://github.com/devhawk/Hawk/tree/master/src/PublishDraft">PublishDraft</a> to publish a post from
my draft directory to a local git repo of all my content. As part of this, I update some of the metadata and
render the markdown to HTML.</li>
<li>Run my <a href="https://github.com/devhawk/Hawk/blob/master/src/Hawk/CustomCommands.cs#L79">WritePostsToAzure Custom Command</a>
to publish posts from my local git repo to Azure. I have a blog post on my custom command
infrastructure in the works.</li>
<li>Trigger a content refresh via an <a href="https://github.com/devhawk/Hawk/blob/ae0431ffc0a816a218f00e4c1815adbe95e445f1/src/Hawk/Controllers/HomeController.cs#L50">unpublished URL</a>.</li>
</ol>
</li>
<li>I need to trigger a content refresh because Hawk loads all of the post metadata from Azure on startup.
The combined metadata for all my posts is pretty small - about 2/3 of a megabyte stored on disk as JSON.
Having the data in memory makes it easy to query as well as support multiple post repositories (
<a href="https://github.com/devhawk/Hawk/blob/master/src/Hawk/Services/AzureRepo.cs">Azure storage</a> and the
<a href="https://github.com/devhawk/Hawk/blob/master/src/Hawk/Services/FileSystemRepo.cs">file system</a>).</li>
<li>I felt comfortable publishing the Hawk source code now because I added a secret key
to the data refresh URL. Previously, the refresh URL was unsecured. I didn't think giving
random, anonymous people on the Interet the ability to kick off a data refresh was a
good idea, so I held off publishing source until I secured that endpoint.</li>
<li>Hawk caches blog post content and legacy comments <a href="https://github.com/aspnet/Caching/tree/dev/src/Microsoft.Framework.Caching.Memory">in memory</a>.
This release also adds cache invalidation logic so that everything gets reloaded
from storage on data refresh, not just the blog post metadata.</li>
<li>I don't understand what the ASP.NET team is doing with the BufferedHtmlContent class.
In beta 7 it's <a href="https://github.com/aspnet/Common/blob/dev/src/Microsoft.Framework.BufferedHtmlContent.Sources/BufferedHtmlContent.cs">been moved</a>
to the Common repo and <a href="https://www.myget.org/F/aspnetmaster/api/v2/package/Microsoft.Framework.BufferedHtmlContent.Sources/1.0.0-beta7">published as source</a>.
However, I couldn't get it to compile because it depends on an <a href="https://github.com/aspnet/Common/blob/dev/src/Microsoft.Framework.BufferedHtmlContent.Sources/BufferedHtmlContent.cs#L119">internal <code>[NotNull]</code>
attribute</a>.
I decided to scrap my use of BufferedHtmlContent and built out several classes that
implement <code>IHtmlContent</code> directly instead. For example, the links at the bottom
of my master layout are rendered by the <a href="https://github.com/devhawk/Hawk/blob/master/src/Hawk/Views/Shared/_Layout.cshtml#L7">SocialLink class</a>.
Frankly, I'm not sure if rolling your own  <code>IHtmlContent</code> class for snippet
of HTML code you want to automate is a best practice. It seems like it's harder than
it should be. It feels like ASP.NET needs a built-in class like BufferedHtmlContent,
so I'm not sure why it's been removed.</li>
</ul>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>This is the first in a series of blog posts about <a href="https://github.com/devhawk/Hawk">Hawk</a>, the engine that powers this site.
My plan is to make a post like this for every significant update to the site. We'll see well that plan works.</p>
<ul>
<li>I just pushed out a new version of Hawk on my website. The primary feature of this release is support for
<a href="http://blogs.msdn.com/b/webdev/archive/2015/09/02/announcing-availability-of-asp-net-5-beta7.aspx">ASP.NET 5 Beta 7</a>.
I also published the <a href="https://github.com/devhawk/Hawk">source code</a> up on GitHub. Feedback welcome!</li>
<li>As I mentioned in <a href="/blog/2015/09/02/the-brilliant-magic-of-edgejs">my post on Edge.js</a>, the publishing tools
for Hawk is little more than duct tape and bailing wire at this point. Eventually, I'd like to have a
dedicated tool, but for now it's a manual three step process:
<ol>
<li>Run the <a href="https://github.com/devhawk/Hawk/tree/master/src/PublishDraft">PublishDraft</a> to publish a post from
my draft directory to a local git repo of all my content. As part of this, I update some of the metadata and
render the markdown to HTML.</li>
<li>Run my <a href="https://github.com/devhawk/Hawk/blob/master/src/Hawk/CustomCommands.cs#L79">WritePostsToAzure Custom Command</a>
to publish posts from my local git repo to Azure. I have a blog post on my custom command
infrastructure in the works.</li>
<li>Trigger a content refresh via an <a href="https://github.com/devhawk/Hawk/blob/ae0431ffc0a816a218f00e4c1815adbe95e445f1/src/Hawk/Controllers/HomeController.cs#L50">unpublished URL</a>.</li>
</ol>
</li>
<li>I need to trigger a content refresh because Hawk loads all of the post metadata from Azure on startup.
The combined metadata for all my posts is pretty small - about 2/3 of a megabyte stored on disk as JSON.
Having the data in memory makes it easy to query as well as support multiple post repositories (
<a href="https://github.com/devhawk/Hawk/blob/master/src/Hawk/Services/AzureRepo.cs">Azure storage</a> and the
<a href="https://github.com/devhawk/Hawk/blob/master/src/Hawk/Services/FileSystemRepo.cs">file system</a>).</li>
<li>I felt comfortable publishing the Hawk source code now because I added a secret key
to the data refresh URL. Previously, the refresh URL was unsecured. I didn't think giving
random, anonymous people on the Interet the ability to kick off a data refresh was a
good idea, so I held off publishing source until I secured that endpoint.</li>
<li>Hawk caches blog post content and legacy comments <a href="https://github.com/aspnet/Caching/tree/dev/src/Microsoft.Framework.Caching.Memory">in memory</a>.
This release also adds cache invalidation logic so that everything gets reloaded
from storage on data refresh, not just the blog post metadata.</li>
<li>I don't understand what the ASP.NET team is doing with the BufferedHtmlContent class.
In beta 7 it's <a href="https://github.com/aspnet/Common/blob/dev/src/Microsoft.Framework.BufferedHtmlContent.Sources/BufferedHtmlContent.cs">been moved</a>
to the Common repo and <a href="https://www.myget.org/F/aspnetmaster/api/v2/package/Microsoft.Framework.BufferedHtmlContent.Sources/1.0.0-beta7">published as source</a>.
However, I couldn't get it to compile because it depends on an <a href="https://github.com/aspnet/Common/blob/dev/src/Microsoft.Framework.BufferedHtmlContent.Sources/BufferedHtmlContent.cs#L119">internal <code>[NotNull]</code>
attribute</a>.
I decided to scrap my use of BufferedHtmlContent and built out several classes that
implement <code>IHtmlContent</code> directly instead. For example, the links at the bottom
of my master layout are rendered by the <a href="https://github.com/devhawk/Hawk/blob/master/src/Hawk/Views/Shared/_Layout.cshtml#L7">SocialLink class</a>.
Frankly, I'm not sure if rolling your own  <code>IHtmlContent</code> class for snippet
of HTML code you want to automate is a best practice. It seems like it's harder than
it should be. It feels like ASP.NET needs a built-in class like BufferedHtmlContent,
so I'm not sure why it's been removed.</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>The Brilliant Magic of Edge.js</title>
      <link>http://devhawk.net/blog/2015/9/2/the-brilliant-magic-of-edgejs</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Wed, 02 Sep 2015 14:00:54 GMT</pubDate>
      <guid>http://devhawk.net/blog/2015/9/2/the-brilliant-magic-of-edgejs</guid>
      <category domain="urn:devhawk-net:category">Development</category>
      <category domain="urn:devhawk-net:tag">Blogging</category>
      <category domain="urn:devhawk-net:tag">Hawk</category>
      <category domain="urn:devhawk-net:tag">C#</category>
      <category domain="urn:devhawk-net:tag">JavaScript</category>
      <category domain="urn:devhawk-net:tag">Node.js</category>
      <description><![CDATA[<p>In my <a href="/blog/2015/8/31/go-ahead-call-it-a-comeback">post relaunching DevHawk</a>, I mentioned that
the site is written entirely in C# except for about 30 lines of JavaScript. Like
many modern web content systems, Hawk uses <a href="https://en.wikipedia.org/wiki/Markdown">Markdown</a>.
I write blog posts in Markdown and then my publishing &quot;tool&quot; (frankly little more than
duct tape and bailing wire at this point) coverts the Markdown to HTML and
uploads it to Azure.</p>
<p>However, as I went thru and converted all my old content to Markdown, I
discovered that I needed some features that aren't supported by either the <a href="http://daringfireball.net/projects/markdown/">original
implementation</a> or the new
<a href="http://commonmark.org/">CommonMark</a> project. Luckily, I discovered the
<a href="https://github.com/markdown-it/markdown-it">markdown-it</a> project which implements
the CommonMark spec but also supports <a href="https://github.com/markdown-it/markdown-it#syntax-extensions">syntax extensions</a>.
Markdown-it already had extensions for all of the extra features I needed - things like
<a href="https://github.com/markdown-it/markdown-it#syntax-highlighting">syntax highlighting</a>,
<a href="https://github.com/markdown-it/markdown-it-footnote">footnotes</a> and
<a href="https://github.com/markdown-it/markdown-it-container">custom containers</a>.</p>
<p>The only problem with using markdown-it in Hawk is that it's written in JavaScript.
JavaScript <del>is a fine language</del> has lots of great libraries, but I
find it a chore to write significant amounts of code in JavaScript - especially async code.
I did try and rewrite my blog post upload tool in JavaScript.
It was much more difficult than the equivalent C# code.
Maybe once <a href="https://github.com/lukehoban/es6features#promises">promises</a>
become more widely used and <a href="https://github.com/tc39/ecmascript-asyncawait">async/await</a>
is available, JavaScript will feel like it has a reasonable developer experience to me.
Until then, C# remains my weapon of choice.</p>
<p>I wasn't willing to use JavaScript for the entire publishing tool, but I still needed
to use markdown-it <a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a>. So I started looking for a way to integrate the small amount of
JavaScript code that renders Markdown into HTML in with the rest of my C# code base.
I was expecting to have to setup some kind of local web service with Node.js to host
the markdown-it code in and call out to it from C# with HttpClient.</p>
<p>But then I discovered <a href="http://tjanczuk.github.io/edge/">Edge.js</a>. Holy frak, Edge.js blew my mind.</p>
<p>Edge.js provides nearly seamless interop between .NET and Node.js.
I was able to drop the 30 lines of JavaScript code into my C# app and call it directly.
It took all of about 15 minutes to prototype and it's less than 5 lines of C# code.</p>
<p>Seriously, I think <a href="http://tomasz.janczuk.org/">Tomasz Janczuk</a> must be some kind of a wizard.</p>
<p>To demonstrate how simple Edge.js is to use, let me show you how I integrated markdown-it
into my publishing tool. Here is a somewhat simplified version of the JavaScript code
I use to render markdown in my tool using markdown-it, including syntax highlighting
and some other extensions.</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#008000;">// highlight.js integration lifted unchanged from </span>
<span style="color:#008000;">// https://github.com/markdown-it/markdown-it#syntax-highlighting</span>
<span style="color:#0000FF;">var</span> hljs  = require(<span style="color:#A31515;">&#39;highlight.js&#39;</span>);
<span style="color:#0000FF;">var</span> md = require(<span style="color:#A31515;">&#39;markdown-it&#39;</span>)({
  highlight: <span style="color:#0000FF;">function</span> (str, lang) {
    <span style="color:#0000FF;">if</span> (lang &amp;&amp; hljs.getLanguage(lang)) {
      <span style="color:#0000FF;">try</span> { 
        <span style="color:#0000FF;">return</span> hljs.highlight(lang, str).value;
      } <span style="color:#0000FF;">catch</span> (__) {}
    }

    <span style="color:#0000FF;">try</span> {
      <span style="color:#0000FF;">return</span> hljs.highlightAuto(str).value;
    } <span style="color:#0000FF;">catch</span> (__) {}

    <span style="color:#0000FF;">return</span> <span style="color:#A31515;">&#39;&#39;</span>; 
  }
});

<span style="color:#008000;">// I use a few more extensions in my publishing tool, but you get the idea</span>
md.use(require(<span style="color:#A31515;">&#39;markdown-it-footnote&#39;</span>));
md.use(require(<span style="color:#A31515;">&#39;markdown-it-sup&#39;</span>));

<span style="color:#0000FF;">var</span> html = <span style="color:#0000FF;">return</span> md.render(markdown);
</pre></div>
<p>As you can see, most of the code is just setting up markdown-it and its extensions.
Actually rendering the markdown is just a single line of code.</p>
<p>In order to call this code from C#, we need to wrap the call to <code>md.render</code> with a
JavaScript function that follows the <a href="http://docs.nodejitsu.com/articles/getting-started/control-flow/what-are-callbacks">Node.js callback style</a>.
We pass this wrapper function back to Edge.js by returning it from the JavaScript code.</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#008000;">// Ain&#39;t first order functions grand? </span>
<span style="color:#0000FF;">return</span> <span style="color:#0000FF;">function</span> (markdown, callback) {
    <span style="color:#0000FF;">var</span> html = md.render(markdown);
    callback(<span style="color:#0000FF;">null</span>, html);
}
</pre></div>
<p>Note, I have to use the callback style in this case even though my code is syncronous.
I suspect I'm the outlier here. There's a lot more async Node.js code
out in the wild than syncronous.</p>
<p>To make this code available to C#, all you have to do is pass the JavaScript code into the
Edge.js <code>Func</code> function. Edge.js includes a embedded copy of Node.js as a DLL.
The <code>Func</code> function executes the JavaScript and wraps the returned Node.js callback
function in a .NET async delegate. The .NET delegate takes an <code>object</code> input
parameter and returns a <code>Task&lt;object&gt;</code>. The delegate input parameter is passed in
as the first parameter to the JavaScript function. The second parameter passed to the
callback function becomes the return value from the delegate (wrapped in a Task of course).
I haven't tested, but I assume Edge.js will convert the callback function's first
parameter to a C# exception if you pass a value other than null.</p>
<p>It sounds complex, but it's a trivial amount of code:</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#008000;">// markdown-it setup code omitted for brevity</span>
Func&lt;<span style="color:#0000FF;">object</span>, Task&lt;<span style="color:#0000FF;">object</span>&gt;&gt; _markdownItFunc = EdgeJs.Edge.Func(<span style="color:#A31515;">@&quot;
var md = require(&#39;markdown-it&#39;)() 

return function (markdown, callback) {
    var html = md.render(markdown);
    callback(null, html);
}&quot;</span>);
  
<span style="color:#0000FF;">async</span> Task&lt;<span style="color:#0000FF;">string</span>&gt; MarkdownItAsync(<span style="color:#0000FF;">string</span> markdown)
{
    <span style="color:#0000FF;">return</span> (<span style="color:#0000FF;">string</span>)<span style="color:#0000FF;">await</span> _markdownItFunc(markdown);
}
</pre></div>
<p>To make it easier to use from the rest of my C# code, I wrapped the Edge.js delegate
with a statically typed C# function. This handles type checking and casting as well as
provides intellisense for the rest of my app.</p>
<p>The only remotely negative thing I can say about Edge.js is that it
<a href="https://github.com/tjanczuk/edge/issues/279">doesn't support</a>
<a href="http://dotnet.github.io/core/">.NET Core</a> yet. I had to build my markdown rendering
tool as a &quot;traditional&quot; C# console app instead of a
<a href="http://jameschambers.com/2015/08/writing-custom-commands-for-dnx-with-asp-net-5-0/">DNX Custom Command</a>
like the rest of Hawk's command line utilities.
However, <a href="https://github.com/lstratman">Luke Stratman</a>
is <a href="https://github.com/medicomp/edge">working on</a> .NET Core support for Edge.js. So maybe I'll be able to migrate my
markdown rendering tool to DNX sooner rather than later.</p>
<p>Rarely have I ever discovered such an elegant solution to a problem I was having. Edge.js
simply rocks. As I <a href="https://twitter.com/DevHawk/status/637359972091752448">said on Twitter</a>,
I owe Tomasz a beer or five. Drop me a line Tomasz and let me know when you want to collect.</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:1">
<p>I also investigated what it would take to update an existing .NET Markdown implementation
like <a href="https://github.com/Knagis/CommonMark.NET">CommonMark.NET</a> or
<a href="http://tpetricek.github.io/FSharp.Formatting/">F# Formatting</a> to support custom syntax extensions.
That would have been dramatically more code than simply biting the bullet and rewriting the post upload
tool in JavaScript.<a href="#fnref:1" class="footnote-back-ref">&#8617;</a></p>
</li>
</ol>
</div>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>In my <a href="/blog/2015/8/31/go-ahead-call-it-a-comeback">post relaunching DevHawk</a>, I mentioned that
the site is written entirely in C# except for about 30 lines of JavaScript. Like
many modern web content systems, Hawk uses <a href="https://en.wikipedia.org/wiki/Markdown">Markdown</a>.
I write blog posts in Markdown and then my publishing &quot;tool&quot; (frankly little more than
duct tape and bailing wire at this point) coverts the Markdown to HTML and
uploads it to Azure.</p>
<p>However, as I went thru and converted all my old content to Markdown, I
discovered that I needed some features that aren't supported by either the <a href="http://daringfireball.net/projects/markdown/">original
implementation</a> or the new
<a href="http://commonmark.org/">CommonMark</a> project. Luckily, I discovered the
<a href="https://github.com/markdown-it/markdown-it">markdown-it</a> project which implements
the CommonMark spec but also supports <a href="https://github.com/markdown-it/markdown-it#syntax-extensions">syntax extensions</a>.
Markdown-it already had extensions for all of the extra features I needed - things like
<a href="https://github.com/markdown-it/markdown-it#syntax-highlighting">syntax highlighting</a>,
<a href="https://github.com/markdown-it/markdown-it-footnote">footnotes</a> and
<a href="https://github.com/markdown-it/markdown-it-container">custom containers</a>.</p>
<p>The only problem with using markdown-it in Hawk is that it's written in JavaScript.
JavaScript <del>is a fine language</del> has lots of great libraries, but I
find it a chore to write significant amounts of code in JavaScript - especially async code.
I did try and rewrite my blog post upload tool in JavaScript.
It was much more difficult than the equivalent C# code.
Maybe once <a href="https://github.com/lukehoban/es6features#promises">promises</a>
become more widely used and <a href="https://github.com/tc39/ecmascript-asyncawait">async/await</a>
is available, JavaScript will feel like it has a reasonable developer experience to me.
Until then, C# remains my weapon of choice.</p>
<p>I wasn't willing to use JavaScript for the entire publishing tool, but I still needed
to use markdown-it <a id="fnref:1" href="#fn:1" class="footnote-ref"><sup>1</sup></a>. So I started looking for a way to integrate the small amount of
JavaScript code that renders Markdown into HTML in with the rest of my C# code base.
I was expecting to have to setup some kind of local web service with Node.js to host
the markdown-it code in and call out to it from C# with HttpClient.</p>
<p>But then I discovered <a href="http://tjanczuk.github.io/edge/">Edge.js</a>. Holy frak, Edge.js blew my mind.</p>
<p>Edge.js provides nearly seamless interop between .NET and Node.js.
I was able to drop the 30 lines of JavaScript code into my C# app and call it directly.
It took all of about 15 minutes to prototype and it's less than 5 lines of C# code.</p>
<p>Seriously, I think <a href="http://tomasz.janczuk.org/">Tomasz Janczuk</a> must be some kind of a wizard.</p>
<p>To demonstrate how simple Edge.js is to use, let me show you how I integrated markdown-it
into my publishing tool. Here is a somewhat simplified version of the JavaScript code
I use to render markdown in my tool using markdown-it, including syntax highlighting
and some other extensions.</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#008000;">// highlight.js integration lifted unchanged from </span>
<span style="color:#008000;">// https://github.com/markdown-it/markdown-it#syntax-highlighting</span>
<span style="color:#0000FF;">var</span> hljs  = require(<span style="color:#A31515;">&#39;highlight.js&#39;</span>);
<span style="color:#0000FF;">var</span> md = require(<span style="color:#A31515;">&#39;markdown-it&#39;</span>)({
  highlight: <span style="color:#0000FF;">function</span> (str, lang) {
    <span style="color:#0000FF;">if</span> (lang &amp;&amp; hljs.getLanguage(lang)) {
      <span style="color:#0000FF;">try</span> { 
        <span style="color:#0000FF;">return</span> hljs.highlight(lang, str).value;
      } <span style="color:#0000FF;">catch</span> (__) {}
    }

    <span style="color:#0000FF;">try</span> {
      <span style="color:#0000FF;">return</span> hljs.highlightAuto(str).value;
    } <span style="color:#0000FF;">catch</span> (__) {}

    <span style="color:#0000FF;">return</span> <span style="color:#A31515;">&#39;&#39;</span>; 
  }
});

<span style="color:#008000;">// I use a few more extensions in my publishing tool, but you get the idea</span>
md.use(require(<span style="color:#A31515;">&#39;markdown-it-footnote&#39;</span>));
md.use(require(<span style="color:#A31515;">&#39;markdown-it-sup&#39;</span>));

<span style="color:#0000FF;">var</span> html = <span style="color:#0000FF;">return</span> md.render(markdown);
</pre></div>
<p>As you can see, most of the code is just setting up markdown-it and its extensions.
Actually rendering the markdown is just a single line of code.</p>
<p>In order to call this code from C#, we need to wrap the call to <code>md.render</code> with a
JavaScript function that follows the <a href="http://docs.nodejitsu.com/articles/getting-started/control-flow/what-are-callbacks">Node.js callback style</a>.
We pass this wrapper function back to Edge.js by returning it from the JavaScript code.</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#008000;">// Ain&#39;t first order functions grand? </span>
<span style="color:#0000FF;">return</span> <span style="color:#0000FF;">function</span> (markdown, callback) {
    <span style="color:#0000FF;">var</span> html = md.render(markdown);
    callback(<span style="color:#0000FF;">null</span>, html);
}
</pre></div>
<p>Note, I have to use the callback style in this case even though my code is syncronous.
I suspect I'm the outlier here. There's a lot more async Node.js code
out in the wild than syncronous.</p>
<p>To make this code available to C#, all you have to do is pass the JavaScript code into the
Edge.js <code>Func</code> function. Edge.js includes a embedded copy of Node.js as a DLL.
The <code>Func</code> function executes the JavaScript and wraps the returned Node.js callback
function in a .NET async delegate. The .NET delegate takes an <code>object</code> input
parameter and returns a <code>Task&lt;object&gt;</code>. The delegate input parameter is passed in
as the first parameter to the JavaScript function. The second parameter passed to the
callback function becomes the return value from the delegate (wrapped in a Task of course).
I haven't tested, but I assume Edge.js will convert the callback function's first
parameter to a C# exception if you pass a value other than null.</p>
<p>It sounds complex, but it's a trivial amount of code:</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#008000;">// markdown-it setup code omitted for brevity</span>
Func&lt;<span style="color:#0000FF;">object</span>, Task&lt;<span style="color:#0000FF;">object</span>&gt;&gt; _markdownItFunc = EdgeJs.Edge.Func(<span style="color:#A31515;">@&quot;
var md = require(&#39;markdown-it&#39;)() 

return function (markdown, callback) {
    var html = md.render(markdown);
    callback(null, html);
}&quot;</span>);
  
<span style="color:#0000FF;">async</span> Task&lt;<span style="color:#0000FF;">string</span>&gt; MarkdownItAsync(<span style="color:#0000FF;">string</span> markdown)
{
    <span style="color:#0000FF;">return</span> (<span style="color:#0000FF;">string</span>)<span style="color:#0000FF;">await</span> _markdownItFunc(markdown);
}
</pre></div>
<p>To make it easier to use from the rest of my C# code, I wrapped the Edge.js delegate
with a statically typed C# function. This handles type checking and casting as well as
provides intellisense for the rest of my app.</p>
<p>The only remotely negative thing I can say about Edge.js is that it
<a href="https://github.com/tjanczuk/edge/issues/279">doesn't support</a>
<a href="http://dotnet.github.io/core/">.NET Core</a> yet. I had to build my markdown rendering
tool as a &quot;traditional&quot; C# console app instead of a
<a href="http://jameschambers.com/2015/08/writing-custom-commands-for-dnx-with-asp-net-5-0/">DNX Custom Command</a>
like the rest of Hawk's command line utilities.
However, <a href="https://github.com/lstratman">Luke Stratman</a>
is <a href="https://github.com/medicomp/edge">working on</a> .NET Core support for Edge.js. So maybe I'll be able to migrate my
markdown rendering tool to DNX sooner rather than later.</p>
<p>Rarely have I ever discovered such an elegant solution to a problem I was having. Edge.js
simply rocks. As I <a href="https://twitter.com/DevHawk/status/637359972091752448">said on Twitter</a>,
I owe Tomasz a beer or five. Drop me a line Tomasz and let me know when you want to collect.</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:1">
<p>I also investigated what it would take to update an existing .NET Markdown implementation
like <a href="https://github.com/Knagis/CommonMark.NET">CommonMark.NET</a> or
<a href="http://tpetricek.github.io/FSharp.Formatting/">F# Formatting</a> to support custom syntax extensions.
That would have been dramatically more code than simply biting the bullet and rewriting the post upload
tool in JavaScript.<a href="#fnref:1" class="footnote-back-ref">&#8617;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Go Ahead, Call It a Comeback</title>
      <link>http://devhawk.net/blog/2015/8/31/go-ahead-call-it-a-comeback</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Mon, 31 Aug 2015 20:55:03 GMT</pubDate>
      <guid>http://devhawk.net/blog/2015/8/31/go-ahead-call-it-a-comeback</guid>
      <category domain="urn:devhawk-net:category">General Geekery</category>
      <category domain="urn:devhawk-net:tag">Blogging</category>
      <category domain="urn:devhawk-net:tag">Working at MSFT</category>
      <description><![CDATA[<p>It's been a looooong time, but I finally got around to geting DevHawk
back online. It's hard to believe that it's been over a year since
<a href="/blog/2014/4/26/yet-more-change-for-the-capitals">my last post</a>.
Lots has happened in that time!</p>
<p>First off, I've changed jobs (again). Last year, I made the switch
<a href="/blog/2014/2/14/putting-the-dev-back-in-devhawk">from program manager to dev</a>.
Unfortunately, the project I was working on was cancelled. After several months in limbo,
I was reorganized into the <a href="http://dotnet.github.io/core/">.NET Core framework team</a>
back over in DevDiv. I've got lots of friends in DevDiv and love
<a href="https://github.com/dotnet/corefx">the open source work they are doing</a>.
But I really missed being in Windows. Earlier this year, I joined the team that builds the
platform plumbing for <a href="http://www.xbox.com/smartglass">SmartGlass</a>.
Not much to talk about publicly right now, but that will change sometime soon.</p>
<p>In addition to my day job in SmartGlass, I'm also pitching in to help the <a href="http://www.microsoft.com/about/corporatecitizenship/en-us/serving-communities/disaster-and-humanitarian-response/">Microsoft Services Disaster
Response team</a>.
I knew Microsoft has a long history of corporate giving. However, I was unaware
of the work we do helping communities affected by natural disasters until recently.
My good friend <a href="https://www.linkedin.com/in/lewiscurtis">Lewis Curtis</a> took over as
Director of Microsoft Services Disaster Response last year.
I'm currently helping out on some of the missions for Nepal in response to the
<a href="https://en.wikipedia.org/wiki/April_2015_Nepal_earthquake">devestating earthquake</a> that hit there earlier this year.</p>
<p>Finally, I decided that I was tired of running Other Peoples Code<sup>tm</sup> on <em>my</em> website.
So I built out a new blog engine called Hawk.
It's written in <a href="https://msdn.microsoft.com/en-us/library/vstudio/kx37x362.aspx">C#</a>
(plus about 30 lines of JavaScript), uses <a href="https://github.com/aspnet/home/">ASP.NET 5</a> and runs on <a href="http://azure.microsoft.com/">Azure</a>.
It's specifically designed for my needs - for example, it automatically
redirects old DasBlog style links like <a href="/2005/10/05/code+is+model.aspx">http://devhawk.net/2005/10/05/code+is+model.aspx</a>.
But I'm happy to let other people use it and would welcome contributions.
When I get a chance, I'll push the code up to GitHub.</p>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>It's been a looooong time, but I finally got around to geting DevHawk
back online. It's hard to believe that it's been over a year since
<a href="/blog/2014/4/26/yet-more-change-for-the-capitals">my last post</a>.
Lots has happened in that time!</p>
<p>First off, I've changed jobs (again). Last year, I made the switch
<a href="/blog/2014/2/14/putting-the-dev-back-in-devhawk">from program manager to dev</a>.
Unfortunately, the project I was working on was cancelled. After several months in limbo,
I was reorganized into the <a href="http://dotnet.github.io/core/">.NET Core framework team</a>
back over in DevDiv. I've got lots of friends in DevDiv and love
<a href="https://github.com/dotnet/corefx">the open source work they are doing</a>.
But I really missed being in Windows. Earlier this year, I joined the team that builds the
platform plumbing for <a href="http://www.xbox.com/smartglass">SmartGlass</a>.
Not much to talk about publicly right now, but that will change sometime soon.</p>
<p>In addition to my day job in SmartGlass, I'm also pitching in to help the <a href="http://www.microsoft.com/about/corporatecitizenship/en-us/serving-communities/disaster-and-humanitarian-response/">Microsoft Services Disaster
Response team</a>.
I knew Microsoft has a long history of corporate giving. However, I was unaware
of the work we do helping communities affected by natural disasters until recently.
My good friend <a href="https://www.linkedin.com/in/lewiscurtis">Lewis Curtis</a> took over as
Director of Microsoft Services Disaster Response last year.
I'm currently helping out on some of the missions for Nepal in response to the
<a href="https://en.wikipedia.org/wiki/April_2015_Nepal_earthquake">devestating earthquake</a> that hit there earlier this year.</p>
<p>Finally, I decided that I was tired of running Other Peoples Code<sup>tm</sup> on <em>my</em> website.
So I built out a new blog engine called Hawk.
It's written in <a href="https://msdn.microsoft.com/en-us/library/vstudio/kx37x362.aspx">C#</a>
(plus about 30 lines of JavaScript), uses <a href="https://github.com/aspnet/home/">ASP.NET 5</a> and runs on <a href="http://azure.microsoft.com/">Azure</a>.
It's specifically designed for my needs - for example, it automatically
redirects old DasBlog style links like <a href="/2005/10/05/code+is+model.aspx">http://devhawk.net/2005/10/05/code+is+model.aspx</a>.
But I'm happy to let other people use it and would welcome contributions.
When I get a chance, I'll push the code up to GitHub.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Yet More Change for the Capitals</title>
      <link>http://devhawk.net/blog/2014/4/26/yet-more-change-for-the-capitals</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Sat, 26 Apr 2014 20:13:29 GMT</pubDate>
      <guid>http://devhawk.net/blog/2014/4/26/yet-more-change-for-the-capitals</guid>
      <category domain="urn:devhawk-net:category">Sports</category>
      <category domain="urn:devhawk-net:tag">Hockey</category>
      <category domain="urn:devhawk-net:tag">Washington Capitals</category>
      <description><![CDATA[<p>Six years ago, I was pretty excited about the future for the Washington
Capitals. They had just lost their first round match up with the Flyers
– which was a bummer – but they had made the playoffs for the first time
in 3 seasons. <a href="http://devhawk.net/2008/04/22/caps-season-ends/">I wrote at the
time</a>:</p>
<blockquote>
<p>Furthermore, even though they lost, these playoffs are a promise of
future success. I tell my kids all the time that the only way to get
good at something is to work hard while you’re bad at it. Playoff
hockey is no different. Most of the Caps had little or no playoff
experience going into this series and it really showed thru the first
three games. But they kept at it and played much better over the last
four games of the series. They went 2-2 in those games, but the two
losses went to overtime. A little more luck (or better officiating)
and the Caps are headed to Pittsburgh instead of the golf course.</p>
</blockquote>
<p>What a difference <a href="https://twitter.com/JapersRink/status/458585591207038976/photo/1">six seasons
makes</a>.
Sure, they won the President’s Trophy in 2010. But the promise of future
playoff success has been broken, badly. The Caps have been on a pretty
steep decline after getting beat by the eighth seed Canadians in the
first round of the playoffs in 2010. Since then, they’ve switched
systems three times and head coaches twice. This year, they missed the
playoffs entirely even with Alex Ovechkin racking up a league-leading 51
goals.</p>
<p>Today, the word came down that <a href="http://capitalstoday.monumentalnetwork.com/2014/04/26/capitals-announce-changes-to-front-office-and-coaching-staff">both the coach and general
manager</a>
have been let go. As a Caps fan, I’m really torn about this. I mean, I
totally agree that the coach and GM had to go – frankly, I was surprised
it didn’t happen 7-10 days earlier. But now what do you do? The draft is
two months and one day away, free agency starts two days after that. The
search for a GM is going to have to be fast. Then the GM will have to
make some really important decisions about players at the draft, free
agency and compliance buyouts with limited knowledge of the players in
our system. Plus, he’ll need to hire a new head coach – preferably
before the draft as well.</p>
<p>The one positive note is that the salary cap for the Capitals <a href="http://www.capgeek.com/capitals">looks
pretty good</a> for next year. The
Capitals currently have the second largest amount of cap space / open
roster slot in the league. (The Islanders are first with $14.5 million
/ open roster slot. The Caps have just over $7 million / open roster
slot.) They have only a handful of unrestricted free agents to resign –
with arguably only one “must sign” (<a href="http://capitals.nhl.com/club/player.htm?id=8471362">Mikhail
Grabovski</a>) in the
bunch. Of course, this could also be a bug rather than a feature –
having that many players under contract may make it harder for the new
GM to shape the team in his image.</p>
<p>Who every the Capitals hire to be GM and coach, I’m not expecting a
promising start. It feels like the next season is already a wash, and
we’re not even finished with the first round of this year’s playoffs
yet.</p>
<p>I guess it could be worse.</p>
<p>I could be a Toronto Leafs fan.</p>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Six years ago, I was pretty excited about the future for the Washington
Capitals. They had just lost their first round match up with the Flyers
– which was a bummer – but they had made the playoffs for the first time
in 3 seasons. <a href="http://devhawk.net/2008/04/22/caps-season-ends/">I wrote at the
time</a>:</p>
<blockquote>
<p>Furthermore, even though they lost, these playoffs are a promise of
future success. I tell my kids all the time that the only way to get
good at something is to work hard while you’re bad at it. Playoff
hockey is no different. Most of the Caps had little or no playoff
experience going into this series and it really showed thru the first
three games. But they kept at it and played much better over the last
four games of the series. They went 2-2 in those games, but the two
losses went to overtime. A little more luck (or better officiating)
and the Caps are headed to Pittsburgh instead of the golf course.</p>
</blockquote>
<p>What a difference <a href="https://twitter.com/JapersRink/status/458585591207038976/photo/1">six seasons
makes</a>.
Sure, they won the President’s Trophy in 2010. But the promise of future
playoff success has been broken, badly. The Caps have been on a pretty
steep decline after getting beat by the eighth seed Canadians in the
first round of the playoffs in 2010. Since then, they’ve switched
systems three times and head coaches twice. This year, they missed the
playoffs entirely even with Alex Ovechkin racking up a league-leading 51
goals.</p>
<p>Today, the word came down that <a href="http://capitalstoday.monumentalnetwork.com/2014/04/26/capitals-announce-changes-to-front-office-and-coaching-staff">both the coach and general
manager</a>
have been let go. As a Caps fan, I’m really torn about this. I mean, I
totally agree that the coach and GM had to go – frankly, I was surprised
it didn’t happen 7-10 days earlier. But now what do you do? The draft is
two months and one day away, free agency starts two days after that. The
search for a GM is going to have to be fast. Then the GM will have to
make some really important decisions about players at the draft, free
agency and compliance buyouts with limited knowledge of the players in
our system. Plus, he’ll need to hire a new head coach – preferably
before the draft as well.</p>
<p>The one positive note is that the salary cap for the Capitals <a href="http://www.capgeek.com/capitals">looks
pretty good</a> for next year. The
Capitals currently have the second largest amount of cap space / open
roster slot in the league. (The Islanders are first with $14.5 million
/ open roster slot. The Caps have just over $7 million / open roster
slot.) They have only a handful of unrestricted free agents to resign –
with arguably only one “must sign” (<a href="http://capitals.nhl.com/club/player.htm?id=8471362">Mikhail
Grabovski</a>) in the
bunch. Of course, this could also be a bug rather than a feature –
having that many players under contract may make it harder for the new
GM to shape the team in his image.</p>
<p>Who every the Capitals hire to be GM and coach, I’m not expecting a
promising start. It feels like the next season is already a wash, and
we’re not even finished with the first round of this year’s playoffs
yet.</p>
<p>I guess it could be worse.</p>
<p>I could be a Toronto Leafs fan.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Brokered WinRT Components Step Three</title>
      <link>http://devhawk.net/blog/2014/4/25/brokered-winrt-components-step-three</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Fri, 25 Apr 2014 15:45:36 GMT</pubDate>
      <guid>http://devhawk.net/blog/2014/4/25/brokered-winrt-components-step-three</guid>
      <category domain="urn:devhawk-net:category">Development</category>
      <category domain="urn:devhawk-net:category">Windows</category>
      <category domain="urn:devhawk-net:category">Windows Runtime</category>
      <category domain="urn:devhawk-net:tag">brokered components</category>
      <category domain="urn:devhawk-net:tag">sideload</category>
      <category domain="urn:devhawk-net:tag">tutorial</category>
      <description><![CDATA[<p>So far, we’ve created two projects, written all of about two lines of
code and we have both our <a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-one">brokered
component</a> and
its
<a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-two">proxy/stub</a>
ready to go. Now it’s time to build the Windows Runtime app that uses
the component. So far, things have been pretty easy – the only really
tricky and/or manual step so far has been registering the proxy/stub,
and that’s only tricky if you don’t want to run VS as admin.
Unfortunately, tying this all together in the app requires a few more
manual steps.</p>
<p>But before we get to the manual steps, let’s create the WinRT client
app. Again, we’re going to create a new project but this time we’re
going to select “Blank App (Windows)” from the Visual C# -&gt; Store
Apps -&gt; Windows App node of the Add New Project dialog. Note, I’m not
using “Blank App (Universal)” or “Blank App (Windows Phone)” because the
brokered WinRT component feature is not support on Windows Phone. Call
the client app project whatever you like, I’m calling mine
“HelloWorldBRT.Client”.</p>
<p>Before we start writing code, we need to reference the brokered
component. We can’t reference the brokered component directly or it will
load in the sandboxed app process. Instead, the app need to reference a
reference assembly version of the .winmd that gets generated
automatically by the proxy/stub project. Remember in the <a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-two">last
step</a> when
I said Kieran Mockford is an MSBuild wizard? The proxy/stub template
project includes a custom target that automatically publishes the
reference assembly winmd file used by the client app. When he showed me
that, I was stunned – as I said, the man is a wizard. This means all
<em>you</em> need to do is right click on the References node of the WinRT
Client app project and select Add Reference. In the Reference Manager
dialog, add a reference to the proxy/stub project you created in step
two.</p>
<p>Now I can add the following code to the top of my App.OnLaunched
function. Since this is a simple Hello World walkthru, I’m not going to
bother to build any UI. I’m just going to inspect variables in the
debugger. Believe me, the less UI I write, the better for everyone
involved. Note, I’ve also added the P/Invoke signatures for
GetCurrentProcess/ThreadID and to the client app like I did in the
brokered component in <a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-one">step
one</a>.
This way, I can get the process and thread IDs for both the app and
broker process and compare them.</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#0000FF;">var</span> pid = GetCurrentProcessId();
<span style="color:#0000FF;">var</span> tid = GetCurrentThreadId();

<span style="color:#0000FF;">var</span> c = <span style="color:#0000FF;">new</span> HelloWorldBRT.Class();
<span style="color:#0000FF;">var</span> bpid = c.CurrentProcessId;
<span style="color:#0000FF;">var</span> btid = c.CurrentThreadId;
</pre></div>
<p>At this point the app will compile, but if I run it the app will throw a
TypeLoadException when it tries to create an instance of
HelloWorldBRT.Class. The type can’t be loaded because the we’re using
the reference assembly .winmd published by the proxy/stub project – it
has no implementation details, so it can’t load. In order to be able to
load the type, we need to declare the HelloWorldBRT.Class as a brokered
component in the app’s pacakge.appxmanifest file. For non-brokered
components, Visual Studio does this for you automatically. For brokered
components we have to do it manually unfortunately. Every activatable
class (i.e. class you can construct via “new”) needs to be registered in
the appx manifest this way.</p>
<p>To register HelloWorldBRT.Class, right click the Package.appxmanifest
file in the client project, select “Open With” from the context menu and
then select “XML (Text) editor” from the Open With dialog. Then you need
to insert <a href="http://msdn.microsoft.com/en-us/library/windows/apps/br211443.aspx">inProcessServer
extension</a>
that includes an <a href="http://msdn.microsoft.com/en-us/library/windows/apps/br211413.aspx">ActivatableClass
element</a>
for each class you can activate (aka has a public constructor). Each
ActivatableClass element contains an ActivatableClassAttribute element
that contains a pointer to the folder where the brokered component is
installed. Here’s what I added to Package.appxmainfest of my
HelloWorldBRT.Client app.</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">Extensions</span><span style="color:#0000FF;">&gt;</span>
  <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">Extension</span> <span style="color:#FF0000;">Category</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">windows.activatableClass.inProcessServer</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">&gt;</span>
    <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">InProcessServer</span><span style="color:#0000FF;">&gt;</span>
      <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">Path</span><span style="color:#0000FF;">&gt;</span>clrhost.dll<span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">Path</span><span style="color:#0000FF;">&gt;</span>
      <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">ActivatableClass</span> <span style="color:#FF0000;">ActivatableClassId</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">HelloWorldBRT.Class</span><span style="color:#000000;">&quot;</span>
                        <span style="color:#FF0000;">ThreadingModel</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">both</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">&gt;</span>
        <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">ActivatableClassAttribute</span>
             <span style="color:#FF0000;">Name</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">DesktopApplicationPath</span><span style="color:#000000;">&quot;</span>
             <span style="color:#FF0000;">Type</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">string</span><span style="color:#000000;">&quot;</span>
             <span style="color:#FF0000;">Value</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">D:\dev\HelloWorldBRT\Debug\HelloWorldBRT.PS</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">/&gt;</span>
      <span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">ActivatableClass</span><span style="color:#0000FF;">&gt;</span>
    <span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">InProcessServer</span><span style="color:#0000FF;">&gt;</span>
  <span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">Extension</span><span style="color:#0000FF;">&gt;</span>
<span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">Extensions</span><span style="color:#0000FF;">&gt;</span>
</pre></div>
<p>The key thing here is the addition of the DesktopApplicationPath
ActivatableClassAttribute. This tells the WinRT activation logic that
HelloWorldBRT.Class is a brokered component and where the managed .winmd
file with the implementation details is located on the device. Note, you
can use multiple brokered components in your side loaded app, but they
all have the same DesktopApplicationPath.</p>
<p>Speaking of DesktopApplicationPath, the path I’m using here is path the
final location of the proxy/stub components generated by the compiler.
Frankly, this isn’t an good choice to use in a production deployment.
But for the purposes of this walk thru, it’ll be fine.</p>
<p><a href="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-three/ClientWatchWindow.png"><img src="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-three/ClientWatchWindow-300x94.png" alt="ClientWatchWindow" /></a></p>
<p>Now when we run the app, we can load a HelloWorldBRT.Class instance and
access the properties. re definitely seeing a different app process IDs
when comparing the result of calling GetCurrentProcessId directly in
App.OnLoaded vs. the result of calling GetCurrentProcessId in the
brokered component. Of course, each run of the app will have different
ID values, but this proves that we are loading our brokered component
into a different process from where our app code is running.</p>
<p>Now you’re ready to go build your own brokered components! Here’s hoping
you’ll find more interesting uses for them than comparing the process
IDs of the app and broker processes in the debugger!
😄</p>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>So far, we’ve created two projects, written all of about two lines of
code and we have both our <a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-one">brokered
component</a> and
its
<a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-two">proxy/stub</a>
ready to go. Now it’s time to build the Windows Runtime app that uses
the component. So far, things have been pretty easy – the only really
tricky and/or manual step so far has been registering the proxy/stub,
and that’s only tricky if you don’t want to run VS as admin.
Unfortunately, tying this all together in the app requires a few more
manual steps.</p>
<p>But before we get to the manual steps, let’s create the WinRT client
app. Again, we’re going to create a new project but this time we’re
going to select “Blank App (Windows)” from the Visual C# -&gt; Store
Apps -&gt; Windows App node of the Add New Project dialog. Note, I’m not
using “Blank App (Universal)” or “Blank App (Windows Phone)” because the
brokered WinRT component feature is not support on Windows Phone. Call
the client app project whatever you like, I’m calling mine
“HelloWorldBRT.Client”.</p>
<p>Before we start writing code, we need to reference the brokered
component. We can’t reference the brokered component directly or it will
load in the sandboxed app process. Instead, the app need to reference a
reference assembly version of the .winmd that gets generated
automatically by the proxy/stub project. Remember in the <a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-two">last
step</a> when
I said Kieran Mockford is an MSBuild wizard? The proxy/stub template
project includes a custom target that automatically publishes the
reference assembly winmd file used by the client app. When he showed me
that, I was stunned – as I said, the man is a wizard. This means all
<em>you</em> need to do is right click on the References node of the WinRT
Client app project and select Add Reference. In the Reference Manager
dialog, add a reference to the proxy/stub project you created in step
two.</p>
<p>Now I can add the following code to the top of my App.OnLaunched
function. Since this is a simple Hello World walkthru, I’m not going to
bother to build any UI. I’m just going to inspect variables in the
debugger. Believe me, the less UI I write, the better for everyone
involved. Note, I’ve also added the P/Invoke signatures for
GetCurrentProcess/ThreadID and to the client app like I did in the
brokered component in <a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-one">step
one</a>.
This way, I can get the process and thread IDs for both the app and
broker process and compare them.</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#0000FF;">var</span> pid = GetCurrentProcessId();
<span style="color:#0000FF;">var</span> tid = GetCurrentThreadId();

<span style="color:#0000FF;">var</span> c = <span style="color:#0000FF;">new</span> HelloWorldBRT.Class();
<span style="color:#0000FF;">var</span> bpid = c.CurrentProcessId;
<span style="color:#0000FF;">var</span> btid = c.CurrentThreadId;
</pre></div>
<p>At this point the app will compile, but if I run it the app will throw a
TypeLoadException when it tries to create an instance of
HelloWorldBRT.Class. The type can’t be loaded because the we’re using
the reference assembly .winmd published by the proxy/stub project – it
has no implementation details, so it can’t load. In order to be able to
load the type, we need to declare the HelloWorldBRT.Class as a brokered
component in the app’s pacakge.appxmanifest file. For non-brokered
components, Visual Studio does this for you automatically. For brokered
components we have to do it manually unfortunately. Every activatable
class (i.e. class you can construct via “new”) needs to be registered in
the appx manifest this way.</p>
<p>To register HelloWorldBRT.Class, right click the Package.appxmanifest
file in the client project, select “Open With” from the context menu and
then select “XML (Text) editor” from the Open With dialog. Then you need
to insert <a href="http://msdn.microsoft.com/en-us/library/windows/apps/br211443.aspx">inProcessServer
extension</a>
that includes an <a href="http://msdn.microsoft.com/en-us/library/windows/apps/br211413.aspx">ActivatableClass
element</a>
for each class you can activate (aka has a public constructor). Each
ActivatableClass element contains an ActivatableClassAttribute element
that contains a pointer to the folder where the brokered component is
installed. Here’s what I added to Package.appxmainfest of my
HelloWorldBRT.Client app.</p>
<div style="color:#000000;background-color:#FFFFFF;"><pre>
<span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">Extensions</span><span style="color:#0000FF;">&gt;</span>
  <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">Extension</span> <span style="color:#FF0000;">Category</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">windows.activatableClass.inProcessServer</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">&gt;</span>
    <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">InProcessServer</span><span style="color:#0000FF;">&gt;</span>
      <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">Path</span><span style="color:#0000FF;">&gt;</span>clrhost.dll<span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">Path</span><span style="color:#0000FF;">&gt;</span>
      <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">ActivatableClass</span> <span style="color:#FF0000;">ActivatableClassId</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">HelloWorldBRT.Class</span><span style="color:#000000;">&quot;</span>
                        <span style="color:#FF0000;">ThreadingModel</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">both</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">&gt;</span>
        <span style="color:#0000FF;">&lt;</span><span style="color:#A31515;">ActivatableClassAttribute</span>
             <span style="color:#FF0000;">Name</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">DesktopApplicationPath</span><span style="color:#000000;">&quot;</span>
             <span style="color:#FF0000;">Type</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">string</span><span style="color:#000000;">&quot;</span>
             <span style="color:#FF0000;">Value</span><span style="color:#0000FF;">=</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">D:\dev\HelloWorldBRT\Debug\HelloWorldBRT.PS</span><span style="color:#000000;">&quot;</span><span style="color:#0000FF;">/&gt;</span>
      <span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">ActivatableClass</span><span style="color:#0000FF;">&gt;</span>
    <span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">InProcessServer</span><span style="color:#0000FF;">&gt;</span>
  <span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">Extension</span><span style="color:#0000FF;">&gt;</span>
<span style="color:#0000FF;">&lt;/</span><span style="color:#A31515;">Extensions</span><span style="color:#0000FF;">&gt;</span>
</pre></div>
<p>The key thing here is the addition of the DesktopApplicationPath
ActivatableClassAttribute. This tells the WinRT activation logic that
HelloWorldBRT.Class is a brokered component and where the managed .winmd
file with the implementation details is located on the device. Note, you
can use multiple brokered components in your side loaded app, but they
all have the same DesktopApplicationPath.</p>
<p>Speaking of DesktopApplicationPath, the path I’m using here is path the
final location of the proxy/stub components generated by the compiler.
Frankly, this isn’t an good choice to use in a production deployment.
But for the purposes of this walk thru, it’ll be fine.</p>
<p><a href="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-three/ClientWatchWindow.png"><img src="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-three/ClientWatchWindow-300x94.png" alt="ClientWatchWindow" /></a></p>
<p>Now when we run the app, we can load a HelloWorldBRT.Class instance and
access the properties. re definitely seeing a different app process IDs
when comparing the result of calling GetCurrentProcessId directly in
App.OnLoaded vs. the result of calling GetCurrentProcessId in the
brokered component. Of course, each run of the app will have different
ID values, but this proves that we are loading our brokered component
into a different process from where our app code is running.</p>
<p>Now you’re ready to go build your own brokered components! Here’s hoping
you’ll find more interesting uses for them than comparing the process
IDs of the app and broker processes in the debugger!
😄</p>
]]></content:encoded>
    </item>
    <item>
      <title>Brokered WinRT Components Step Two</title>
      <link>http://devhawk.net/blog/2014/4/25/brokered-winrt-components-step-two</link>
      <author>devhawk@outlook.com (DevHawk)</author>
      <pubDate>Fri, 25 Apr 2014 15:43:35 GMT</pubDate>
      <guid>http://devhawk.net/blog/2014/4/25/brokered-winrt-components-step-two</guid>
      <category domain="urn:devhawk-net:category">Development</category>
      <category domain="urn:devhawk-net:category">Windows</category>
      <category domain="urn:devhawk-net:category">Windows Runtime</category>
      <category domain="urn:devhawk-net:tag">brokered components</category>
      <category domain="urn:devhawk-net:tag">sideload</category>
      <category domain="urn:devhawk-net:tag">tutorial</category>
      <description><![CDATA[<p>Now that we have built the brokered component , we have to build a
proxy/stub for it. Proxies and stubs are how WinRT method calls are
marshalled across process boundaries. If you want to know more – or you
have insomnia – feel free to read <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms692621(v=vs.85).aspx">all the gory details up on
MSDN</a>.</p>
<p>Proxies and stubs look like they might be scary, but they’re actually
trivial (at least in the brokered component scenario) because 100% of
the code is generated for you. It couldn’t be much easier.</p>
<p>Right click the solution node and select Add -&gt; New Project.
Alternatively, you can select File -&gt; New -&gt; Project in the Visual
Studio main menu, but if you do that make sure you change the default
solution from “Create new Solution” to “Add to Solution”. Regardless of
how you launch the new project wizard, search for “broker” again, but
this time select the “Brokered Windows Runtime ProxyStub” template. Give
the project a name – I chose “HelloWorldBRT.PS”.</p>
<div class="image-left"><p><a href="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-two/ProxyStubAddReference.png"><img src="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-two/ProxyStubAddReference-300x174.png" alt="ProxyStubAddReference" /></a></p>
</div>
<p>Once you’ve created the proxy/stub project, you need to set a reference to
the brokered component you created in step 1. Since proxies and stubs
are native, this is a VC++ project. Adding a reference in a VC++ is not
as straightforward as it is in C# projects. Right click the proxy/stub
project, select “Properties” and then select Common Properties -&gt;
References from the tree on the left. Press the “Add New Reference…”
button to bring up the same Add Reference dialog you’ve seen in managed
code projects. Select the brokered component project and press OK.</p>
<p>Remember when I said that 100% of the code for the proxy/stub is
generated? I wasn’t kidding – creating the template and setting
referencing the brokered component project is literally all you need to
do. Want proof? Go ahead and build now. If you watch the output windows,
you’ll see a bunch of output go by referencing IDL files and MIDLRT
among other stuff. This proxy/stub template has some custom MSBuild
tasks that generates the proxy/stub code using winmdidl and midlrt. The
process is similar to what is <a href="http://msdn.microsoft.com/en-us/library/dn481253.aspx">described
here</a>. BTW, if
you get a chance, check out the proxy/stub project file – it is a work
of art. Major props to <a href="http://www.linkedin.com/pub/kieran-mockford/4/77/110">Kieran
Mockford</a> for his
msbuild wizardry.</p>
<div class="image-left"><p><a href="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-two/ProxyStubRegisterOutput.png"><img src="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-two/ProxyStubRegisterOutput-300x174.png" alt="ProxyStubRegisterOutput" /></a></p>
</div>
<p>Unfortunately, it’s not enough just to build the proxy/stub – you also have to register
it. The brokered component proxy/stub needs to be registered globally on
the machine, which means you have to be running as an admin to do it. VS
can register the proxy/stub for you automatically, but that means you
have to run VS as an administrator. That always makes me nervous, but if
you’re OK with running as admin you can enable proxy/stub registration
by right clicking the proxy/stub project file, selecting Properties,
navigating to Configuration properties -&gt; Linker -&gt; General in the
tree of the project properties page, and then changing Register Output
to “Yes”.</p>
<p>If you don’t like running VS as admin, you can manually register the
proxy/stub by running <code>regsvr32 &lt;proxystub dll&gt;</code> from an elevated
command prompt. Note, you do have to re-register every time the public
surface area of your brokered component changes so letting VS handle
registration admin is definitely the easier route to go.</p>
<p>In the <a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-three">third and final
step</a>,
we’ll build a client app that accesses our brokered component.</p>
]]></description>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Now that we have built the brokered component , we have to build a
proxy/stub for it. Proxies and stubs are how WinRT method calls are
marshalled across process boundaries. If you want to know more – or you
have insomnia – feel free to read <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms692621(v=vs.85).aspx">all the gory details up on
MSDN</a>.</p>
<p>Proxies and stubs look like they might be scary, but they’re actually
trivial (at least in the brokered component scenario) because 100% of
the code is generated for you. It couldn’t be much easier.</p>
<p>Right click the solution node and select Add -&gt; New Project.
Alternatively, you can select File -&gt; New -&gt; Project in the Visual
Studio main menu, but if you do that make sure you change the default
solution from “Create new Solution” to “Add to Solution”. Regardless of
how you launch the new project wizard, search for “broker” again, but
this time select the “Brokered Windows Runtime ProxyStub” template. Give
the project a name – I chose “HelloWorldBRT.PS”.</p>
<div class="image-left"><p><a href="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-two/ProxyStubAddReference.png"><img src="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-two/ProxyStubAddReference-300x174.png" alt="ProxyStubAddReference" /></a></p>
</div>
<p>Once you’ve created the proxy/stub project, you need to set a reference to
the brokered component you created in step 1. Since proxies and stubs
are native, this is a VC++ project. Adding a reference in a VC++ is not
as straightforward as it is in C# projects. Right click the proxy/stub
project, select “Properties” and then select Common Properties -&gt;
References from the tree on the left. Press the “Add New Reference…”
button to bring up the same Add Reference dialog you’ve seen in managed
code projects. Select the brokered component project and press OK.</p>
<p>Remember when I said that 100% of the code for the proxy/stub is
generated? I wasn’t kidding – creating the template and setting
referencing the brokered component project is literally all you need to
do. Want proof? Go ahead and build now. If you watch the output windows,
you’ll see a bunch of output go by referencing IDL files and MIDLRT
among other stuff. This proxy/stub template has some custom MSBuild
tasks that generates the proxy/stub code using winmdidl and midlrt. The
process is similar to what is <a href="http://msdn.microsoft.com/en-us/library/dn481253.aspx">described
here</a>. BTW, if
you get a chance, check out the proxy/stub project file – it is a work
of art. Major props to <a href="http://www.linkedin.com/pub/kieran-mockford/4/77/110">Kieran
Mockford</a> for his
msbuild wizardry.</p>
<div class="image-left"><p><a href="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-two/ProxyStubRegisterOutput.png"><img src="http://image.devhawk.net/blog-content/20140425-brokered-winrt-components-step-two/ProxyStubRegisterOutput-300x174.png" alt="ProxyStubRegisterOutput" /></a></p>
</div>
<p>Unfortunately, it’s not enough just to build the proxy/stub – you also have to register
it. The brokered component proxy/stub needs to be registered globally on
the machine, which means you have to be running as an admin to do it. VS
can register the proxy/stub for you automatically, but that means you
have to run VS as an administrator. That always makes me nervous, but if
you’re OK with running as admin you can enable proxy/stub registration
by right clicking the proxy/stub project file, selecting Properties,
navigating to Configuration properties -&gt; Linker -&gt; General in the
tree of the project properties page, and then changing Register Output
to “Yes”.</p>
<p>If you don’t like running VS as admin, you can manually register the
proxy/stub by running <code>regsvr32 &lt;proxystub dll&gt;</code> from an elevated
command prompt. Note, you do have to re-register every time the public
surface area of your brokered component changes so letting VS handle
registration admin is definitely the easier route to go.</p>
<p>In the <a href="http://devhawk.net/2014/04/25/brokered-winrt-components-step-three">third and final
step</a>,
we’ll build a client app that accesses our brokered component.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>