<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Khalid Abuhakmeh</title>
    <description>The latest articles on DEV Community by Khalid Abuhakmeh (@buhakmeh).</description>
    <link>https://dev.to/buhakmeh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F7285%2Fdafe10bd-56ef-48f7-b249-9bb78e8edfb5.jpg</url>
      <title>DEV Community: Khalid Abuhakmeh</title>
      <link>https://dev.to/buhakmeh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/buhakmeh"/>
    <language>en</language>
    <item>
      <title>Save Your C# Keystrokes With Tuples</title>
      <dc:creator>Khalid Abuhakmeh</dc:creator>
      <pubDate>Tue, 11 Feb 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/buhakmeh/save-your-c-keystrokes-with-tuples-71p</link>
      <guid>https://dev.to/buhakmeh/save-your-c-keystrokes-with-tuples-71p</guid>
      <description>&lt;p&gt;In the year 2000, Microsoft released C# to the masses, and since then, it has evolved with many new features. One of those features includes Tuples. Only recently have tuples become more useful with the addition deconstruction in C# 8. In this post, I’ll show you how to save your keystrokes by working with Tuples. We’ll look at two identical code snippets with as much readability, but significantly fewer characters used.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is A Tuple
&lt;/h2&gt;

&lt;p&gt;A Tuple is a newer data structure introduced in later versions of the .NET Framework. Microsoft’s documentation describes a Tuple as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A tuple is a data structure that has a specific number and sequence of elements.&lt;cite&gt;–&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.tuple?view=netframework-4.8"&gt;Microsoft&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s likely easier to understand what a Tuple is by looking at an example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Microsoft Documentation Example&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;primes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;19&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Prime numbers less than 20: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; 
    &lt;span class="s"&gt;"{0}, {1}, {2}, {3}, {4}, {5}, {6}, and {7}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Item1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Item2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Item3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Item4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Item5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Item6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Item7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Item1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// The example displays the following output: &lt;/span&gt;
&lt;span class="c1"&gt;// Prime numbers less than 20: 2, 3, 5, 7, 11, 13, 17, and 19&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tuples are limited to a structure containing seven items. That said, if you’re using Tuples with this many items, you may want to use a &lt;code&gt;class&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deconstruction To Save Keystrokes
&lt;/h2&gt;

&lt;p&gt;Let’s take a look at an example using an anonymous &lt;code&gt;friend&lt;/code&gt; object collection. Each friend has a &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;nickname&lt;/code&gt;, and a set of &lt;code&gt;hobbies&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;friends&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bruce Wayne"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;nickname&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Batman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;hobbies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"dressing up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"crime-fighting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"parkour"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Natalia Romanova"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;nickname&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Black Widow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;hobbies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"martial arts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"spying"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"guns"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Arthur Curry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;nickname&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Aquaman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;hobbies&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"surfing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"conversations"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"fish"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;friend&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;friends&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;friend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;friend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nickname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;) likes &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;friend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hobbies&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we execute the code, we get the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Bruce Wayne (Batman) likes dressing up, crime-fighting, parkour.
Natalia Romanova (Black Widow) likes martial arts, spying, guns.
Arthur Curry (Aquaman) likes surfing, conversations, fish.

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The character count of the previous code is &lt;strong&gt;606&lt;/strong&gt; characters.&lt;/p&gt;

&lt;p&gt;Let’s take a look at how we can use Tuple deconstruction to shorten that code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;friends&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Bruce Wayne"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Batman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"dressing up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"crime-fighting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"parkour"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Natalia Romanova"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Black Widow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"martial arts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"spying"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"guns"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Arthur Curry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Aquaman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"surfing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"conversations"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"fish"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nickname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hobbies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;friends&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nickname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;) likes &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hobbies&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executing the tuple deconstruction code, we get the following output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Bruce Wayne (Batman) likes dressing up, crime-fighting, parkour.
Natalia Romanova (Black Widow) likes martial arts, spying, guns.
Arthur Curry (Aquaman) likes surfing, conversations, fish.

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No surprise, it is identical to the first code execution. The difference being that this codebase has a character count of &lt;strong&gt;497&lt;/strong&gt;. That’s an &lt;strong&gt;18%&lt;/strong&gt; reduction in keystrokes. The savings come from not having to define property names, and the use of &lt;code&gt;.&lt;/code&gt; notation to access those same properties.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By using Tuples we reduced our character count by 18%!&lt;cite&gt;–Khalid&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Should you switch your entire codebase to use tuples? You should not. I think the advantage of tuples presents itself in tightly scoped situations. These situations can include scripts, unit tests, and code samples. In my opinion, tuples break down once you begin to pass them to external consumers. The items comprising my tuples are clear in the sample code, but if I were to return the tuple to an ignorant consumer, the intention of the data structure would be lost. &lt;strong&gt;Like all new things, take the time to absorb the idea, evaluate its value, and use it accordingly.&lt;/strong&gt; I hope you found this blog post educational. Thank you for reading.&lt;/p&gt;

</description>
      <category>dotnet</category>
    </item>
    <item>
      <title>.NET Core 3.0 AllowSynchronousIO Workaround</title>
      <dc:creator>Khalid Abuhakmeh</dc:creator>
      <pubDate>Tue, 28 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/buhakmeh/net-core-3-0-allowsynchronousio-workaround-3bhk</link>
      <guid>https://dev.to/buhakmeh/net-core-3-0-allowsynchronousio-workaround-3bhk</guid>
      <description>&lt;p&gt;Over the last year I’ve been dabbling in the dark arts of &lt;a href="https://graphql.org/"&gt;GraphQL&lt;/a&gt;. As a web api interface, its easy to consume and utilize, but I consider myself a &lt;strong&gt;back end developer&lt;/strong&gt; first and for most. I have been spending my time learning how to build a GraphQL server implementation utilizing .NET Core with &lt;a href="https://github.com/graphql-dotnet/graphql-dotnet"&gt;GraphQL.NET&lt;/a&gt;. I’ve pulled down the project’s recent code, launched the harness project, and was immediately met with an ASP.NET Core error.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;System.InvalidOperationException: Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.StreamReader.ReadBuffer(Span`1 userBuffer, Boolean&amp;amp; readToUserBuffer)
   at System.IO.StreamReader.ReadSpan(Span`1 buffer)
   at System.IO.StreamReader.Read(Char[] buffer, Int32 index, Int32 count)
   at Newtonsoft.Json.JsonTextReader.ReadData(Boolean append, Int32 charsRequired)
   at Newtonsoft.Json.JsonTextReader.ParseValue()
   at Newtonsoft.Json.JsonReader.ReadAndMoveToContent()
   at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)
   at Example.GraphQLMiddleware.Deserialize[T](Stream s) in /Users/khalidabuhakmeh/Projects/dotnet/graphql-dotnet/src/GraphQL.Harness/GraphQLMiddleware.cs:line 93
   at Example.GraphQLMiddleware.ExecuteAsync(HttpContext context, ISchema schema) in /Users/khalidabuhakmeh/Projects/dotnet/graphql-dotnet/src/GraphQL.Harness/GraphQLMiddleware.cs:line 54
   at Example.GraphQLMiddleware.Invoke(HttpContext context, ISchema schema) in /Users/khalidabuhakmeh/Projects/dotnet/graphql-dotnet/src/GraphQL.Harness/GraphQLMiddleware.cs:line 41
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turns out, starting in .NET Core 3.0, all synchronous operations on the request are turned off by default.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AllowSynchronousIO is a option in each server that enables or disables sync IO APIs like HttpReqeuest.Body.Read, HttpResponse.Body.Write, Stream.Flush, etc.. These APIs have long been a source of thread starvation and application hangs. Starting in 3.0.0-preview3 these are disabled by default. &lt;cite&gt;&lt;a href="https://github.com/dotnet/aspnetcore/issues/7644"&gt;–Chris Ross&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you are seeing this error after upgrading your project to .NET Core 3.0, it is likely you are running on these .NET server implementations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kestrel&lt;/li&gt;
&lt;li&gt;HttpSys&lt;/li&gt;
&lt;li&gt;IIS in-process&lt;/li&gt;
&lt;li&gt;TestServer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Errors can revolve around &lt;code&gt;ReadAsync&lt;/code&gt;, &lt;code&gt;WriteAsync&lt;/code&gt;, and &lt;code&gt;FlushAsync&lt;/code&gt; with outputs similar to what is listed below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.

Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.

Synchronous operations are disallowed. Call FlushAsync or set AllowSynchronousIO to true instead.

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a temporary workaround, you can set the value of &lt;code&gt;AllowSynchronousIO&lt;/code&gt; in your &lt;code&gt;ConfigureServices&lt;/code&gt; method found in your &lt;code&gt;Startup&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;KestrelServerOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowSynchronousIO&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// If using IIS:&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IISServerOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowSynchronousIO&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// other services&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It isn’t a great workaround, but it will keep you moving forward. The better solution is to upgrade your libraries and perform all your actions asynchronously. I hope this helped!&lt;/p&gt;

</description>
      <category>dotnet</category>
    </item>
    <item>
      <title>Using Environment Variables In Your .NET Core Builds</title>
      <dc:creator>Khalid Abuhakmeh</dc:creator>
      <pubDate>Sat, 25 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/buhakmeh/using-environment-variables-in-your-net-core-builds-2n8m</link>
      <guid>https://dev.to/buhakmeh/using-environment-variables-in-your-net-core-builds-2n8m</guid>
      <description>&lt;p&gt;MSBuild is the glue that holds the .NET ecosystem together. As a powerful build system, it can do anything and everything to compose your applications. The tool has been around since the inception of .NET, but with .NET Core enhancements to the &lt;code&gt;csproj&lt;/code&gt; files, it has become less scary to dive in and make modifications to your build process. In this post, I’ll show you the one trick that should make your .NET build pipeline easier, primarily if you use continuous integrations (CI) providers like &lt;a href="https://www.appveyor.com/docs/environment-variables/"&gt;AppVeyor&lt;/a&gt;, &lt;a href="https://github.com/projectkudu/kudu/wiki/Azure-runtime-environment"&gt;Windows Azure Kudu&lt;/a&gt;, or &lt;a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/using-environment-variables"&gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;We have a project file for each .NET Core project we start. Let’s look at an original file for a console application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Project&lt;/span&gt; &lt;span class="na"&gt;Sdk=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.NET.Sdk"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;OutputType&amp;gt;&lt;/span&gt;Exe&lt;span class="nt"&gt;&amp;lt;/OutputType&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;netcoreapp3.0&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the file is quite understandable. We want our artifact to be an executable program, and that we are targeting .NET Core 3.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Access To All Environment Variables
&lt;/h2&gt;

&lt;p&gt;When working within this file, you may see variables accessed via the &lt;code&gt;$()&lt;/code&gt; syntax. MSBuild gives you access to &lt;strong&gt;all environment variables&lt;/strong&gt; during your build. We can utilize environment variables to execute targets conditionally. Let’s modify our &lt;code&gt;csproj&lt;/code&gt; file with some targets and conditions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Project&lt;/span&gt; &lt;span class="na"&gt;Sdk=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.NET.Sdk"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;OutputType&amp;gt;&lt;/span&gt;Exe&lt;span class="nt"&gt;&amp;lt;/OutputType&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;netcoreapp3.0&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;Target&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;"Production"&lt;/span&gt; &lt;span class="na"&gt;Condition=&lt;/span&gt;&lt;span class="s"&gt;"$(Game) == 'Pong'"&lt;/span&gt; &lt;span class="na"&gt;BeforeTargets=&lt;/span&gt;&lt;span class="s"&gt;"Build"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Message&lt;/span&gt; &lt;span class="na"&gt;Importance=&lt;/span&gt;&lt;span class="s"&gt;"high"&lt;/span&gt; &lt;span class="na"&gt;Text=&lt;/span&gt;&lt;span class="s"&gt;"Ping!"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;Target&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;"Development"&lt;/span&gt; &lt;span class="na"&gt;Condition=&lt;/span&gt;&lt;span class="s"&gt;"$(Game) == 'Ping'"&lt;/span&gt; &lt;span class="na"&gt;BeforeTargets=&lt;/span&gt;&lt;span class="s"&gt;"Build"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Message&lt;/span&gt; &lt;span class="na"&gt;Importance=&lt;/span&gt;&lt;span class="s"&gt;"high"&lt;/span&gt; &lt;span class="na"&gt;Text=&lt;/span&gt;&lt;span class="s"&gt;"Pong!"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the environment variable of &lt;code&gt;Game&lt;/code&gt; is &lt;code&gt;Pong&lt;/code&gt;, then our build output should have a message of &lt;code&gt;Ping!&lt;/code&gt;. If &lt;code&gt;Game&lt;/code&gt; is &lt;code&gt;Ping&lt;/code&gt;, then we should have an output message of &lt;code&gt;Pong!&lt;/code&gt;. Let’s try it out. In a command-line window, we can pass in the environment variable for &lt;code&gt;Game&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;➜ ConsoleApp1 Game=Ping dotnet build
Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 28.26 ms for /Users/khalidabuhakmeh/Projects/dotnet/ConsoleApp1/ConsoleApp1/ConsoleApp1.csproj.
&lt;/span&gt;&lt;span class="gp"&gt;  ConsoleApp1 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/Users/khalidabuhakmeh/Projects/dotnet/ConsoleApp1/ConsoleApp1/bin/Debug/netcoreapp3.0/ConsoleApp1.dll
&lt;span class="go"&gt;  Pong!

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.06

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, for &lt;code&gt;Pong&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;➜ ConsoleApp1 Game=Pong dotnet build
Microsoft (R) Build Engine version 16.4.0+e901037fe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 29.22 ms for /Users/khalidabuhakmeh/Projects/dotnet/ConsoleApp1/ConsoleApp1/ConsoleApp1.csproj.
&lt;/span&gt;&lt;span class="gp"&gt;  ConsoleApp1 -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/Users/khalidabuhakmeh/Projects/dotnet/ConsoleApp1/ConsoleApp1/bin/Debug/netcoreapp3.0/ConsoleApp1.dll
&lt;span class="go"&gt;  Ping!

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.05

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see with the two outputs above, we were able to execute build targets based on environment variables selectively. There is an array of options in &lt;a href="https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-conditions?view=vs-2019"&gt;MSBuild conditions&lt;/a&gt; and is viewable at &lt;a href="https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-conditions?view=vs-2019"&gt;Microsoft’s documentation site&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment Variables Everywhere!
&lt;/h2&gt;

&lt;p&gt;In a previous blog post, &lt;a href="https://dev.to/kick-ass-with-aspnet-core-vue-components-and-parcel"&gt;I talked about running NPM scripts via MSBuild targets&lt;/a&gt;, and you should check it out. Building on that post, we can utilize environment variables in our build environment, to selectively run commands to build for different target environments. AppVeyor, a continuous integration service, injects &lt;a href="https://www.appveyor.com/docs/environment-variables/"&gt;many environment variables&lt;/a&gt; for your use. Windows Azure injects all app settings in the portal into your &lt;a href="https://github.com/projectkudu/kudu/wiki/Azure-runtime-environment"&gt;Kudu build environment&lt;/a&gt;, and so does &lt;a href="https://help.github.com/en/actions/automating-your-workflow-with-github-actions/using-environment-variables"&gt;GitHub actions&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Microsoft’s simplification of the &lt;code&gt;csproj&lt;/code&gt; file makes it easier to reason and modify your .NET Core build process. Utilizing environment variables and &lt;a href="https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-conditions?view=vs-2019"&gt;MSBuild conditions&lt;/a&gt; means we can tailor our build artifacts for our destination environments. Most, if not all, CI services inject many variables that MSBuild can take advantage of, and it is quite simple to build complex conditions on these exposed variables.&lt;/p&gt;

</description>
      <category>dotnet</category>
    </item>
    <item>
      <title>Watching More Files With Dotnet Watch For Static Sites</title>
      <dc:creator>Khalid Abuhakmeh</dc:creator>
      <pubDate>Wed, 22 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/buhakmeh/watching-more-files-with-dotnet-watch-for-static-sites-3ab6</link>
      <guid>https://dev.to/buhakmeh/watching-more-files-with-dotnet-watch-for-static-sites-3ab6</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k5RHjleD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1518717328608-59c0379cb82f%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D960%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k5RHjleD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1518717328608-59c0379cb82f%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D960%26q%3D80" alt="Neon wall clock"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The marriage of .NET Core and static site generators is a beautiful thing. There are many great static site generator options out there like &lt;a href="https://www.11ty.dev/"&gt;&lt;code&gt;11ty&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://jekyllrb.com/"&gt;&lt;code&gt;Jekyll&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://gohugo.io/"&gt;&lt;code&gt;Hugo&lt;/code&gt;&lt;/a&gt;, and many more. While you can accomplish amazing feats at build time, a dynamic backend can allow your application features that are just not possible at build time. The combination of .NET Core and the static site generator of your choice is a powerful one-two punch. In this post, I’ll show you how to set up an ASP.NET Core application hosting a static site generator, with the added ability to watch all files within your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project and Static Site Setup
&lt;/h2&gt;

&lt;p&gt;In this post, I’ll be using 11ty as my static site generator. This post could be adapted to any other static site framework. To get started with 11ty, check out the &lt;a href="https://www.11ty.dev/"&gt;documentation site&lt;/a&gt;. The first step is to create a new ASP.NET Core application. From a command line, let’s create a new app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;mkdir &lt;/span&gt;staticz
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;staticz
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; dotnet new web
&lt;span class="go"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run this, we should have an empty ASP.NET Core applications.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;dotnet new web&lt;/code&gt; will create an empty ASP.NET Core web application. Next, let’s run the commands to install &lt;code&gt;11ty&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; npm init
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt; @11ty/eleventy &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be able to run &lt;code&gt;11ty&lt;/code&gt; from the &lt;code&gt;node_modules&lt;/code&gt; folder, we need to add an NPM script in packages.json.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"staticz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eleventy --input=. --output=wwwroot"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@11ty/eleventy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.10.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are passing some default arguments to &lt;code&gt;11ty&lt;/code&gt;. First, the directory to build, and secondly, the output directory of &lt;code&gt;wwwroot&lt;/code&gt;. The output directory is the default content directory ASP.NET Core looks for in web projects. Before we run the script, let’s add a &lt;code&gt;index.html&lt;/code&gt; file to the root of our project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello, World!&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Hi&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s make sure our script works by running &lt;code&gt;npm run build&lt;/code&gt; in the command line. You should see some build output, and a brand new &lt;code&gt;wwwroot&lt;/code&gt; folder. Awesome! Let’s get to the ASP.NET Core part now.&lt;/p&gt;

&lt;h2&gt;
  
  
  ASP.NET Core Configuration
&lt;/h2&gt;

&lt;p&gt;The ASP.NET Core application has three parts: Add some static file middleware, modify our &lt;code&gt;csproj&lt;/code&gt; file, and add a new build target. I’ve mentioned one of the approaches in a &lt;a href="https://dev.to/kick-ass-with-aspnet-core-vue-components-and-parcel"&gt;previous blog post about kicking some butt with Parcel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s first look at our changes to the &lt;code&gt;Startup&lt;/code&gt; class. We need to register a few middleware components, specifically the &lt;code&gt;DefaultFile&lt;/code&gt; middleware and the &lt;code&gt;StaticFile&lt;/code&gt; middleware.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.Builder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.Hosting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.DependencyInjection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Hosting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;staticz&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Startup&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// This method gets called by the runtime. Use this method to add services to the container.&lt;/span&gt;
        &lt;span class="c1"&gt;// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IApplicationBuilder&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IWebHostEnvironment&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseDeveloperExceptionPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHttpsRedirection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseDefaultFiles&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseStaticFiles&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is important that the &lt;code&gt;UseDefaultFiles&lt;/code&gt; registration is called before the &lt;code&gt;UseStaticFiles&lt;/code&gt; call. I also threw in the call to &lt;code&gt;UseHttpsRedirection&lt;/code&gt; for good-practices reasons. The next step is to tell our application to run the &lt;code&gt;npm run build&lt;/code&gt; command we have in &lt;code&gt;packages.json&lt;/code&gt;. We do this by modifying our &lt;code&gt;.csproj&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Project&lt;/span&gt; &lt;span class="na"&gt;Sdk=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.NET.Sdk.Web"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;netcoreapp3.1&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;Target&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;"Static"&lt;/span&gt; &lt;span class="na"&gt;BeforeTargets=&lt;/span&gt;&lt;span class="s"&gt;"Build"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class="na"&gt;Command=&lt;/span&gt;&lt;span class="s"&gt;"npm run build"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- extends watching group to include *.js files --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Watch&lt;/span&gt; 
      &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;" **\*.cs;** \*.js; **\*.json;** \*.html;**.*.md"&lt;/span&gt;
      &lt;span class="na"&gt;Exclude=&lt;/span&gt;&lt;span class="s"&gt;"node_modules\ **\*;wwwroot\** \*;"&lt;/span&gt; 
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two important elements to this project that you should take note of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The build target of &lt;code&gt;Static&lt;/code&gt;. It will run our NPM script.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Watch&lt;/code&gt; element tells the &lt;code&gt;dotnet-watch&lt;/code&gt; command to observe specific files. You can also exclude certain directories as well.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cool! Now we have all the pieces, only one thing left to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dotnet Watch All The Things
&lt;/h3&gt;

&lt;p&gt;In the command line, type the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; dotnet watch run
&lt;span class="go"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will use your current project and the configuration options we have in our project file. Here is my command output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RBE-A55a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/static-watch/dotnet-watch-run-1-800-969319.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RBE-A55a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/static-watch/dotnet-watch-run-1-800-969319.png" alt="dotnet watch run first time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! When we visit &lt;code&gt;https://localhost:5001&lt;/code&gt;, we see the output of our &lt;code&gt;index.html&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xIrxXlwE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/static-watch/dotnet-localhost-1-753-343e17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xIrxXlwE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/static-watch/dotnet-localhost-1-753-343e17.png" alt="dotnet watch run web result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s modify our &lt;code&gt;index.html&lt;/code&gt; file from saying &lt;code&gt;Hi&lt;/code&gt; to a hipper &lt;code&gt;Yo!&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--520Spcqe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/static-watch/dotnet-watch-run-2-800-2bd388.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--520Spcqe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/static-watch/dotnet-watch-run-2-800-2bd388.png" alt="dotnet watch run first time"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As soon as the change occurs, our process is shut down and restarted. Since we modified the project to execute our NPM script, we also build our web assets. Going back to &lt;code&gt;https://localhost:5001&lt;/code&gt; we see the results of our hard work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3lJAZ7FS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/static-watch/dotnet-localhost-2-658-c5a085.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3lJAZ7FS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/static-watch/dotnet-localhost-2-658-c5a085.png" alt="dotnet watch run web result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes! Now we have a quick feedback loop that includes our ASP.NET Core work and our static site work. If you want to configure &lt;code&gt;dotnet-watch&lt;/code&gt; more granularly, I recommend reading the &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/dotnet-watch?view=aspnetcore-3.1#customize-files-list-to-watch"&gt;Microsoft Documentation&lt;/a&gt; site for more detailed information around configuring your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have many tools at our disposal, and I think the combination of static site generators and ASP.NET Core are a winning combination. If you work within a multi-disciplinary team, this approach also allows everyone to participate in building your web application. Copywriters can focus on writing content, and developers can focus on optimizing the application using C# and .NET. Remember, this approach can be modified to work with your favorite static site generators, so branch out and experiment. All in all, this is a winning recipe in my book.&lt;/p&gt;

</description>
      <category>dotnet</category>
    </item>
    <item>
      <title>Using LINQ to Build A World Travel Itinerary</title>
      <dc:creator>Khalid Abuhakmeh</dc:creator>
      <pubDate>Thu, 16 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/buhakmeh/using-linq-to-build-a-world-travel-itinerary-21k1</link>
      <guid>https://dev.to/buhakmeh/using-linq-to-build-a-world-travel-itinerary-21k1</guid>
      <description>&lt;p&gt;I enjoy traveling, having new experiences, and making new friends. With so many locations to get to, it is challenging to keep all of them straight. In this post, I’ll show you how to use Language Integrated Query, or LINQ, to take a list of world locations and link them together into travel legs. This technique is powerful and is useful for other scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Imagine you have a list of locations from around the world. You want to fly to each location and map each leg of your travel. Let’s first look at the sites.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;destinations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"Harrisburg, Pennsylvania, USA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"London, England"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Amsterdam, Netherlands"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Paris, France"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Rome, Italy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Shanghai, China"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Tokyo, Japan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Sydney, Australia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Maui, Hawaii, USA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"Los Angeles, California, USA"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to generate a list of travel legs from one location to the other. For example, you could start at &lt;strong&gt;Harrisburg, Pennsylvania, USA&lt;/strong&gt; and fly to the next immediate location. In our case, that would be &lt;strong&gt;London, England.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;legNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Harrisburg, Pennsylvania, USA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;London, England&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;legNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;start&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;London, England&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Amsterdam, Netherlands&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our final destination should bring us back home to the first site. How do we accomplish this in C#?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Shift and Zip To The Rescue
&lt;/h2&gt;

&lt;p&gt;The first step to solving our problem is realizing that we need essentially two lists. We can visualize the problem easier if we start with a more straightforward numeric dataset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Given we have the values of 1,2, and 3, we want the following result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get to our result, we need two lists with identical values, but with the first list &lt;em&gt;shifted&lt;/em&gt; by one value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can accomplish this by using a &lt;code&gt;Shift&lt;/code&gt; extension method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// https://stackoverflow.com/a/18181243&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShiftList&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Shift&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have two lists, we can use LINQ’s &lt;code&gt;Zip&lt;/code&gt; method to pair the two list values together into one enumerable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;shifted&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;legs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;destinations&lt;/span&gt;
        &lt;span class="c1"&gt;// using ZIP to pair the first and second lists here&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shifted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;leg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;legNumber&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;leg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;leg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s look at our results!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;1.) Harrisburg, Pennsylvania, USA -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;London, England
&lt;span class="gp"&gt;2.) London, England -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Amsterdam, Netherlands
&lt;span class="gp"&gt;3.) Amsterdam, Netherlands -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Paris, France
&lt;span class="gp"&gt;4.) Paris, France -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Rome, Italy
&lt;span class="gp"&gt;5.) Rome, Italy -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Shanghai, China
&lt;span class="gp"&gt;6.) Shanghai, China -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Tokyo, Japan
&lt;span class="gp"&gt;7.) Tokyo, Japan -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Sydney, Australia
&lt;span class="gp"&gt;8.) Sydney, Australia -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Maui, Hawaii, USA
&lt;span class="gp"&gt;9.) Maui, Hawaii, USA -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Los Angeles, California, USA
&lt;span class="gp"&gt;10.) Los Angeles, California, USA -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Harrisburg, Pennsylvania, USA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is the full program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Linq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;ConsoleApp1&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;destinations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"Harrisburg, Pennsylvania, USA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"London, England"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Amsterdam, Netherlands"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Paris, France"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Rome, Italy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Shanghai, China"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Tokyo, Japan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Sydney, Australia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Maui, Hawaii, USA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"Los Angeles, California, USA"&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;shifted&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;destinations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;legs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
                &lt;span class="n"&gt;destinations&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shifted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;leg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;legNumber&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;leg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;leg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;
                    &lt;span class="p"&gt;})&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;leg&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;legs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;leg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;legNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.) &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;leg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;leg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// https://stackoverflow.com/a/18181243&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShiftList&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Shift&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;shiftBy&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You can use LINQ’s &lt;code&gt;Zip&lt;/code&gt; method to tie to lists together into something new. In our case, we wanted to travel from one item to the other in a connected fashion. This technique is robust for different use cases as well. Recently, I used this technique to get the distance between two headers in a command-line output. I hope you found this post a fun exploration into LINQ and playing with collections.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>tips</category>
    </item>
    <item>
      <title>Endpoint Debugging in ASP.NET Core 3 Applications</title>
      <dc:creator>Khalid Abuhakmeh</dc:creator>
      <pubDate>Sun, 12 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/buhakmeh/endpoint-debugging-in-asp-net-core-3-applications-2b45</link>
      <guid>https://dev.to/buhakmeh/endpoint-debugging-in-asp-net-core-3-applications-2b45</guid>
      <description>&lt;p&gt;Nothing can be more frustrating than going into a situation &lt;em&gt;“thinking”&lt;/em&gt; you know how a framework works, only to spend the next several hours pulling your hair out and stewing in a pot of unhealthy feelings. I like to consider myself an ASP.NET routing expert with my experience dating back to MVC 1.0. Recently, I’ve started using ASP.NET Core Razor Pages mixed in with MVC and API approaches. I find the combination of all this technology to be a winning one, but it can also add complexity when building views. In this post, &lt;strong&gt;I’ll show you a simple one page Razor Page that can help diagnose route resolution issues quickly.&lt;/strong&gt; Quickly see what your ASP.NET Core application sees and what it requires to resolve routes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Endpoint Routing
&lt;/h2&gt;

&lt;p&gt;With .NET Core 3, the responsibility of routing is on the shoulders of the &lt;code&gt;EndpointMiddlware&lt;/code&gt; component. Registrations of the approaches described above, MVC, Razor Pages, and API occur in the &lt;code&gt;Configure&lt;/code&gt; method of the &lt;code&gt;Startup&lt;/code&gt; class. Below, you’ll see the registration of all Razor Pages endpoints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.UseEndpoints(endpoints =&amp;gt; { endpoints.MapRazorPages(); });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method scans the project for all Razor Pages and registers them as individual endpoints. Cool right?&lt;/p&gt;

&lt;p&gt;What you may not realize is that each registration goes into a global bank of endpoints. This data source of endpoints is called the &lt;code&gt;EndpointDataSource&lt;/code&gt;. Luckily, this data source is also registered (on the down-low) with your dependency injection container. The endpoint data source will be critical for our solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;When generating links within your application, you’ll end up using helper methods from &lt;code&gt;Url&lt;/code&gt; and &lt;code&gt;Html&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;a class="dropdown-item" href="@Url.Page("/Admin/Conferences/Index")"&amp;gt;Conferences&amp;lt;/a&amp;gt;
&amp;lt;!-- or --&amp;gt;
&amp;lt;a href="@Url.Page("/Admin/Conferences/Edit", new { @conference.Id })" role="button"&amp;gt;
    Edit
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re like me, you may forget to add a critical route value, which causes ASP.NET Core to give up on route generation. I’ve found the best way to debug these situations, is to see &lt;em&gt;what&lt;/em&gt; routes are registered. To do that, I’ve built a Razor page that you can drop into your project right now and get more information. I named my page &lt;code&gt;_routes.cshtml&lt;/code&gt;, and the code-behind is unnecessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@page
@using Microsoft.AspNetCore.Mvc.ApplicationModels
@using Microsoft.AspNetCore.Mvc.RazorPages
@using Microsoft.AspNetCore.Routing
@inject EndpointDataSource EndpointsDataSource

@{
    var endpoints = EndpointsDataSource.Endpoints.ToList();
}

&amp;lt;table class="table"&amp;gt;
    &amp;lt;thead class="thead-dark"&amp;gt;
    &amp;lt;tr&amp;gt;
        &amp;lt;th scope="col"&amp;gt;Order&amp;lt;/th&amp;gt;
        &amp;lt;th scope="col"&amp;gt;Display Name&amp;lt;/th&amp;gt;
        &amp;lt;th scope="col"&amp;gt;Route Pattern&amp;lt;/th&amp;gt;
        &amp;lt;th scope="col"&amp;gt;Metadata&amp;lt;/th&amp;gt;
    &amp;lt;/tr&amp;gt;
    &amp;lt;/thead&amp;gt;
    &amp;lt;tbody&amp;gt;
    @foreach (var endpoint in endpoints)
    {
        var routeEndpoint = endpoint as RouteEndpoint;
        &amp;lt;tr&amp;gt;
            &amp;lt;td&amp;gt;@routeEndpoint?.Order&amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;@endpoint.DisplayName&amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;@routeEndpoint?.RoutePattern.RawText&amp;lt;/td&amp;gt;
            &amp;lt;td&amp;gt;
                &amp;lt;ul&amp;gt;
                    @foreach (var md in endpoint.Metadata)
                    {
                        switch (md)
                        {
                            case PageRouteMetadata prm:
                                &amp;lt;li&amp;gt;
                                    &amp;lt;p&amp;gt;@nameof(PageRouteMetadata)&amp;lt;/p&amp;gt;
                                    &amp;lt;ul&amp;gt;
                                        &amp;lt;li&amp;gt;Page Route: @prm.PageRoute&amp;lt;/li&amp;gt;
                                        &amp;lt;li&amp;gt;Route Template: @prm.RouteTemplate&amp;lt;/li&amp;gt;
                                    &amp;lt;/ul&amp;gt;
                                &amp;lt;/li&amp;gt;
                                break;
                            case PageActionDescriptor pad:
                                &amp;lt;li&amp;gt;
                                    &amp;lt;p&amp;gt;@nameof(PageActionDescriptor)&amp;lt;/p&amp;gt;
                                    &amp;lt;ul&amp;gt;
                                        &amp;lt;li&amp;gt;Id: @pad.Id&amp;lt;/li&amp;gt;
                                        &amp;lt;li&amp;gt;Area: @pad.AreaName&amp;lt;/li&amp;gt;
                                        &amp;lt;li&amp;gt;Display Name: @pad.DisplayName&amp;lt;/li&amp;gt;
                                        &amp;lt;li&amp;gt;View Engine Path: @pad.ViewEnginePath&amp;lt;/li&amp;gt;
                                        &amp;lt;li&amp;gt;Relative Path: @pad.RelativePath&amp;lt;/li&amp;gt;
                                    &amp;lt;/ul&amp;gt;
                                &amp;lt;/li&amp;gt;
                                break;
                            case RouteNameMetadata rnm:
                                &amp;lt;li&amp;gt;
                                    Route Name Metadata: @rnm.RouteName
                                &amp;lt;/li&amp;gt;
                                break;
                            case SuppressLinkGenerationMetadata slg:
                                &amp;lt;li&amp;gt;
                                    suppress link: @slg.SuppressLinkGeneration;
                                &amp;lt;/li&amp;gt;
                                break;
                            default:
                                &amp;lt;li&amp;gt;@md.ToString()&amp;lt;/li&amp;gt;
                                break;
                        }
                    }
                &amp;lt;/ul&amp;gt;
            &amp;lt;/td&amp;gt;
        &amp;lt;/tr&amp;gt;
    }
    &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is what it looks like when you visit the page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ADKxmEtm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/routes/debugger-800-121f65.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ADKxmEtm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/routes/debugger-800-121f65.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome right?!&lt;/p&gt;

&lt;h2&gt;
  
  
  More Endpoint Information
&lt;/h2&gt;

&lt;p&gt;The exciting part of debugging endpoints is that there is a treasure trove of information for each route. You can see what required parameters exist for each route, the expected name for resolution, the view engine path, and much more. The debugger in this post was written to diagnose Razor Page issues, but will also work with any library that registers an endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;ASP.NET Core routing is powerful but can be a bit of a black box. Understanding where routes are registered and how you can debug them can save you hours of frustration. Understanding that all endpoints are registered globally and can be accessed via an &lt;code&gt;EndpointDataSource&lt;/code&gt; makes the task of debugging much more straightforward. I hope this post has helped, and please feel free to leave a comment.&lt;/p&gt;

</description>
      <category>dotnet</category>
    </item>
    <item>
      <title>Battling Spam In Your ASP.NET Core Applications with Akismet</title>
      <dc:creator>Khalid Abuhakmeh</dc:creator>
      <pubDate>Sat, 04 Jan 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/buhakmeh/battling-spam-in-your-asp-net-core-applications-with-akismet-275d</link>
      <guid>https://dev.to/buhakmeh/battling-spam-in-your-asp-net-core-applications-with-akismet-275d</guid>
      <description>&lt;p&gt;You’ve spent the better part of a year building your site with hopes of positive community interaction. You deploy your application feeling you’ve accomplished something great. Days later, you realize that your community site has become flooded with horrible advertisements for the latest diet fads, get rich quick schemes, and links to the more sordid parts of the internet.&lt;/p&gt;

&lt;p&gt;In this post, I’ll show you how to combat spam in your ASP.NET Core applications using the Akismet API and ideas for implementing necessary components you will need to keep your application data free of unwanted users and their content.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Spam
&lt;/h2&gt;

&lt;p&gt;No, we are not talking about any kind of canned meat. &lt;strong&gt;Spam is any unsolicited or undesirable message from a third party.&lt;/strong&gt; As internet folks, we deal with unwanted email spam every day. You can also find spam in user groups, search engine results, blog comments, and text messages. If a communication medium exists, it likely has a spam problem. Why would anyone want to spam your application?&lt;/p&gt;

&lt;p&gt;As stated on Wikipedia:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Spamming remains economically viable because advertisers have no operating costs beyond the management of their mailing lists, servers, infrastructures, IP ranges, and domain names, and it is difficult to hold senders accountable for their mass mailings. &lt;cite&gt;–&lt;a href="https://en.wikipedia.org/wiki/Spamming"&gt;Wikipedia&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fun fact: The term &lt;a href="https://en.wikipedia.org/wiki/Spamming"&gt;&lt;em&gt;spam&lt;/em&gt;&lt;/a&gt; can be traced back to &lt;a href="http://www.montypython.com/"&gt;Monty Python’s Flying Circus&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Akismet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://akismet.com"&gt;Akismet&lt;/a&gt; is an API service provided by Wordpress. It is a database with known spam instances that can help identify comments as spam. The service works by crowd-sourcing identification to users of the API and comes bundled with every Wordpress instance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Used by millions of websites, Akismet filters out hundreds of millions of spam comments from the Web every day. &lt;cite&gt;–Akismet&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As of writing this post, Akismet claims to have blocked close to 500 million spam comments.&lt;/p&gt;

&lt;p&gt;The Akismet API has four functional endpoints:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Key Verification&lt;/strong&gt; : Clients can use this endpoint to verify API keys. Mainly used by services that allow users to add their keys to the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comment Check&lt;/strong&gt; : Clients can send comments (or any message) to Akismet for spam validation. The check endpoint is the most used endpoint on the service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Submit Spam&lt;/strong&gt; : This allows applications to submit verified spam to Akismet, thus enhancing the database of known spam.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Submit Ham&lt;/strong&gt; : Allows clients to provide false positives (real comments marked as spam), giving Akismet an idea of what factors may have caused the mistake in the first place.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I really recommend reading the &lt;a href="https://akismet.com/development/api/"&gt;Akismet documentation&lt;/a&gt;, as it gives detailed advice when testing your implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before Getting Started With Akismet
&lt;/h3&gt;

&lt;p&gt;Before using Akismet in your application, you must take into account a few factors.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Akismet is &lt;strong&gt;not&lt;/strong&gt; free, but is reasonably priced. For commercial use, plans start at $5 a month. You can create a free account for local development.&lt;/li&gt;
&lt;li&gt;Akismet is &lt;strong&gt;not&lt;/strong&gt; perfect. It relies on users to actively mark incoming messages as spam, and also mark false-positives as ham. Thus plan for building mechanisms in your application to manage any avenue protected by Akismet.&lt;/li&gt;
&lt;li&gt;Akismet is a web API, so performing any spam protection will incur a network request over the internet. If you have sensitive information or require an offline solution, this is not something I would recommend.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If all those caveats look reasonable to you, you can continue to the &lt;a href="https://akismet.com/development/"&gt;Akismet developer portal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before continuing to the implementation, you will need an API key from Akismet.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ASP.NET Core Implementation
&lt;/h2&gt;

&lt;p&gt;Now that you understand what Akismet it, you can imagine how you may use it to increase the quality of user interaction in your application. The implementation is quite simple, given Akismet is a web API.&lt;/p&gt;

&lt;p&gt;The first step is to install the Akismet client in your ASP.NET Core application. I use a library called &lt;a href="https://www.nuget.org/packages/Akismet/"&gt;&lt;code&gt;Akismet&lt;/code&gt; from NuGet&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; Install-Package Akismet -Version 0.7.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second step will involve us registering our AkismetClient with ASP.NET Core’s dependency injection. To initialize the client, you will need an API key, the URI of your application, the name of your app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddSingleton(
        new AkismetClient(
        "&amp;lt;Your API Key Here&amp;gt;",
        new Uri(Configuration["blogUrl"]),
        "spam-killer")
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I chose to register the client as a &lt;code&gt;singleton&lt;/code&gt; because the &lt;code&gt;AkismetClient&lt;/code&gt; has an internal &lt;code&gt;HttpClient&lt;/code&gt; and is otherwise stateless. Feel free to register the client for your specific needs. You may have to use a transient registration if you allow users to supply personal API keys.&lt;/p&gt;

&lt;p&gt;The next step is to use it in our application. In this example, I am using Razor Pages with a simple form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Contact : PageModel
{
    private readonly IConfiguration configuration;
    private AkismetClient Akismet { get; }

    public Contact(AkismetClient akismet, IConfiguration configuration)
    {
        this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
        Akismet = akismet ?? throw new ArgumentNullException(nameof(akismet));
    }

    [BindProperty]
    public string Comment { get; set; }

    [BindProperty]
    public string Author { get; set; }

    public bool? IsSpam { get; set; }

    public async Task OnPost()
    {
        var comment = new AkismetComment
        {
            Blog = new Uri(configuration["blogUrl"]),
            CommentAuthorEmail = Author,
            CommentContent = Comment,
        };

        IsSpam = await Akismet.IsSpam(comment);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see, we are using the &lt;code&gt;AkismetClient&lt;/code&gt; to call the &lt;code&gt;IsSpam&lt;/code&gt; endpoint with an &lt;code&gt;AkismetComment&lt;/code&gt;. A comment has the following properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public Uri Blog { get; set; }
public string UserIp { get; set; }
public string UserAgent { get; set; }
public string Referrer { get; set; }
public string Permalink { get; set; }
public string CommentType { get; set; }
public string CommentAuthor { get; set; }
public string CommentAuthorEmail { get; set; }
public string CommentAuthorUrl { get; set; }
public string CommentContent { get; set; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don’t have to set &lt;em&gt;all&lt;/em&gt; the properties, but the more information you can provide Akismet, the more likely they are to flag an incoming comment as spam.&lt;/p&gt;

&lt;p&gt;The Razor page has the following implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@page
@model SpamKiller.Pages.Contact
@{
    ViewData["Title"] = "Contact";
}

@if (Model.IsSpam.HasValue)
{
    &amp;lt;div class="row"&amp;gt;
        &amp;lt;div class="col-md-12"&amp;gt;
            &amp;lt;div class="alert alert-@(Model.IsSpam.Value ? "warning" : "success")" role="alert"&amp;gt;
                &amp;lt;h4 class="alert-heading"&amp;gt;The Results Are In!&amp;lt;/h4&amp;gt;
                @if (Model.IsSpam.Value)
                {
                    &amp;lt;p&amp;gt;Boo his, you're trying to submit SPAM to my application. You should be ashamed of your nefarious activity.&amp;lt;/p&amp;gt;
                }
                else
                {
                    &amp;lt;p&amp;gt;Aww yeah, you successfully submitted some quality stuff here. We'll get back to you as soon as we can.&amp;lt;/p&amp;gt;
                }
                &amp;lt;hr&amp;gt;
                &amp;lt;p class="mb-0"&amp;gt;Calling Akismet insures we filter out as much SPAM as possible.&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
}

&amp;lt;div class="row"&amp;gt;
    &amp;lt;div class="col-md-12"&amp;gt;
        &amp;lt;div class="text-center"&amp;gt;
            &amp;lt;form asp-page="Contact" method="post" name="contact"&amp;gt;
                &amp;lt;div class="form-group"&amp;gt;
                    &amp;lt;label for="email"&amp;gt;Email address&amp;lt;/label&amp;gt;
                    &amp;lt;input type="email" class="form-control" id="email" aria-describedby="emailHelp" placeholder="Enter email" asp-for="Author"&amp;gt;
                    &amp;lt;small id="emailHelp" class="form-text text-muted"&amp;gt;We'll never share your email with anyone else.&amp;lt;/small&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div class="form-group"&amp;gt;
                    &amp;lt;label for="comment"&amp;gt;Example textarea&amp;lt;/label&amp;gt;
                    &amp;lt;textarea class="form-control" id="comment" rows="3" asp-for="Comment"&amp;gt;&amp;lt;/textarea&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;button type="submit" class="btn btn-primary"&amp;gt;Submit&amp;lt;/button&amp;gt;
            &amp;lt;/form&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Akismet is easy to test, as they give you inputs that can trigger spam detection immediately. If the user’s email address is &lt;code&gt;akismet-guaranteed-spam@example.com&lt;/code&gt;, it will immediately be marked as spam. Here are two examples: one is welcome, and the other marked immediately as spam.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;“good result”&lt;/em&gt; we expected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fm_CMbyv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/akismet/not_spam_result-800-c3fc95.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fm_CMbyv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/akismet/not_spam_result-800-c3fc95.png" alt="not spam result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;“bad”&lt;/em&gt; result we expected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IJqCrBZZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/akismet/spam_result-800-da2dc0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IJqCrBZZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/akismet/spam_result-800-da2dc0.png" alt="spam result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we log into our Akismet account, it will also show us analytics around our application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F1oaarZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/akismet/akismet_dashboard-800-909f09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F1oaarZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/akismet/akismet_dashboard-800-909f09.png" alt="Akismet dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to play around with the sample application, you can clone the &lt;a href="https://github.com/khalidabuhakmeh/SpamKiller"&gt;repository from GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building interactive applications are challenging, especially when the internet has nefarious parties waiting to exploit any open form. Luckily, spam isn’t a new problem, and by using Akismet, &lt;strong&gt;&lt;em&gt;even a single developer can take on an army of spammers&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Remember the following before using Akismet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Akismet is free for personal use but has paid tiers for commercial use.&lt;/li&gt;
&lt;li&gt;The service is not perfect, so build mechanisms into your application to manage spam and ham (false-positives). Maybe a dashboard or notification system via email/text message.&lt;/li&gt;
&lt;li&gt;You will be transmitting the data over the internet, so take into account the latency and sensitivity of the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The actual implementation in code is pretty simple, and anyone can do it. I hope I’ve inspired you to battle spam and ultimately help everyone else. Good luck, and please let me know if this post has helped in any way.&lt;/p&gt;

</description>
      <category>dotnet</category>
    </item>
    <item>
      <title>Running NPM Scripts From A .NET Core Process</title>
      <dc:creator>Khalid Abuhakmeh</dc:creator>
      <pubDate>Sat, 30 Nov 2019 00:00:00 +0000</pubDate>
      <link>https://dev.to/buhakmeh/running-npm-scripts-from-a-net-core-process-3j7j</link>
      <guid>https://dev.to/buhakmeh/running-npm-scripts-from-a-net-core-process-3j7j</guid>
      <description>&lt;p&gt;It’s 2019, and no one can argue that to be a successful developer, you need a couple of tools in your toolbox. For ASP.NET developers, they can build web applications and run Kestrel as a web server. For front end developers, many UI frameworks have their own hot-reload capable web servers. In this post, I’ll show you .NET developers how to start a front end web server from their .NET Core process and use that in their C# application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Download the project at &lt;a href="https://github.com/khalidabuhakmeh/ChildProcesses"&gt;GitHub&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Run NPM Scripts From .NET Core
&lt;/h2&gt;

&lt;p&gt;Like I mentioned above, many web frameworks come with their web servers. By using these internal webservers, developers get access to many features they wouldn’t otherwise. Some highlights include hot-reloading when development files change and extra debugging capabilities. Running these servers from .NET Core allows us to read the output and create variables for our .NET Core application to use (as you’ll see later).&lt;/p&gt;

&lt;p&gt;Before we get started, we’ll need NodeJs, NPM, and .NET Core.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the Script
&lt;/h2&gt;

&lt;p&gt;In a new .NET Core application, we’ll need to set up a &lt;code&gt;packages.json&lt;/code&gt; file. This file will have our development dependency and UI framework of our choice. In this example, I am using &lt;a href="https://parceljs.org/"&gt;Parcel&lt;/a&gt; to bundle and minify my assets. And as it stands today, it also has [an internal webserver][parcel-sever]. We’ll use the server to serve those assets to our C# application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ChildProcesses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dependencies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;devDependencies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parcel&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^1.12.4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parcel ./src/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parcel build ./src/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;watch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parcel watch ./src/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parcel has three commands that are of interest to us.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;build&lt;/code&gt;: creates our assets for production&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;watch&lt;/code&gt;: creates our assets for development and rebuilds them when they change.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dev&lt;/code&gt;: like &lt;code&gt;watch&lt;/code&gt; but with a web server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We could run any of the scripts from our .NET Core application, but likely to run &lt;code&gt;dev&lt;/code&gt; or &lt;code&gt;watch&lt;/code&gt; during our development process. If you want to run &lt;code&gt;build&lt;/code&gt;, I suggest &lt;a href="https://dev.to/buhakmeh/kick-ass-with-asp-net-core-vue-components-and-parcel-3eja-temp-slug-4656362"&gt;my previous post, which shows how you can run NPM scripts during the build process&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The .NET Core Application
&lt;/h2&gt;

&lt;p&gt;Let’s look at the final product of running the NPM script in our .NET Core application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;ChildProcesses&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;parcel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NpmScript&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;parcel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parcel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasServer&lt;/span&gt;
                &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s"&gt;$"From ASP.NET Core. Parcel is started (&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;parcel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasServer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;) @ &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;parcel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; at process: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;parcel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProcessId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Script has executed."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code, we create a new &lt;code&gt;NpmScript&lt;/code&gt; class, and then run the process. The &lt;code&gt;NpmScript&lt;/code&gt; class does a few things that I think folks will appreciate.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It will wait for the Parcel process to complete running.&lt;/li&gt;
&lt;li&gt;It will parse the output for the webserver&lt;/li&gt;
&lt;li&gt;In the off chance we are not running the webserver, it will timeout and succeed&lt;/li&gt;
&lt;li&gt;We can write the console output of our NPM script to an &lt;code&gt;Action&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It will throw if the process fails to start.&lt;/li&gt;
&lt;li&gt;The node process is a child process of our .NET Core application. When our app stops, so will all child processes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After we run it, we get the following results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q2uwHGnt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/netcore_npm/running_process-710-b7abb3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q2uwHGnt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/netcore_npm/running_process-710-b7abb3.png" alt="running the process"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the Node process running in activity monitor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0xG6hlNa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/netcore_npm/running_process_activity-800-425e68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0xG6hlNa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/netcore_npm/running_process_activity-800-425e68.png" alt="running the process with activity monitor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we close out the .NET Core application, we no longer see the node child processes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mKN10htX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/netcore_npm/running_process_activity_done-800-011609.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mKN10htX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://khalidabuhakmeh.com/assets/images/generated/netcore_npm/running_process_activity_done-800-011609.png" alt="running the process with activity monitor empty"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The NpmScript Class
&lt;/h2&gt;

&lt;p&gt;The following is the implementation of &lt;code&gt;NpmScript&lt;/code&gt;, which uses a &lt;code&gt;Process&lt;/code&gt; class to execute our NPM scripts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NpmScript&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;scriptName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Regex&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\'\\/\\\\\\+&amp;amp;%\\$#_]*)?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;RegexOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IgnoreCase&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;RegexOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Compiled&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Url&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;HasServer&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ProcessId&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;TaskCompletionSource&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;TaskCompletionSource&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// Will execute a script name with default value of "dev"&lt;/span&gt;
    &lt;span class="c1"&gt;/// i.e. npm run [script name]&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;param name="scriptName"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;NpmScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;scriptName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scriptName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scriptName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// Will wait for npm to start up and retrieve the first url from the output.&lt;/span&gt;
    &lt;span class="c1"&gt;/// **Only use this to run the development server.**&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;param name="output"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;param name="timeout"&amp;gt;In milliseconds&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ProcessStartInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"npm"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;RedirectStandardOutput&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;RedirectStandardError&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Arguments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"run &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;scriptName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;UseShellExecute&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;};&lt;/span&gt;

                &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EnableRaisingEvents&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BeginOutputReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BeginErrorReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                &lt;span class="c1"&gt;// Process the NPM output and attempt&lt;/span&gt;
                &lt;span class="c1"&gt;// to find a URL. This will stop processing&lt;/span&gt;
                &lt;span class="c1"&gt;// when it finds the first URL&lt;/span&gt;
                &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OutputDataReceived&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eventArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                        &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="n"&gt;Url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;First&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                            &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;};&lt;/span&gt;

                &lt;span class="c1"&gt;// Terrible things have happened&lt;/span&gt;
                &lt;span class="c1"&gt;// so we can stop waiting for the success&lt;/span&gt;
                &lt;span class="c1"&gt;// event to occur, because it ain't happening&lt;/span&gt;
                &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrorDataReceived&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsCompleted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"npm web server failed to start"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;};&lt;/span&gt;

                &lt;span class="c1"&gt;// set a timeout to wait for the process&lt;/span&gt;
                &lt;span class="c1"&gt;// to finish starting and find the Url. If it doesn't then we&lt;/span&gt;
                &lt;span class="c1"&gt;// assume that the user just ran a script&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cancellationTokenSource&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;cancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsCompleted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                    &lt;span class="c1"&gt;// we don't want to wait for a url anymore&lt;/span&gt;
                    &lt;span class="n"&gt;Url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; 

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While you could run your frontend web server and .NET Core application as two separate processes, I believe this approach has some benefits that you should consider. First, NPM scripts run as a child process of your .NET Core application. More importantly, you can parse the output of your NPM scripts to create variables to use in your .NET Core applications (think ASP.NET Core). Finally, you can programmatically know whether the NPM scripts succeeded or failed, which can save you hours of debugging. If you’re a .NET Core developer, but still want to use the latest UI frameworks that the JavaScript community has to offer, I hope you consider using this approach. Also, feel free to modify the &lt;code&gt;NpmScript&lt;/code&gt; class to meet your needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Download the project at &lt;a href="https://github.com/khalidabuhakmeh/ChildProcesses"&gt;GitHub&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
    </item>
    <item>
      <title>Hi, I'm Khalid Abuhakmeh</title>
      <dc:creator>Khalid Abuhakmeh</dc:creator>
      <pubDate>Fri, 23 Jun 2017 12:16:28 +0000</pubDate>
      <link>https://dev.to/buhakmeh/hi-im-khalid-abuhakmeh</link>
      <guid>https://dev.to/buhakmeh/hi-im-khalid-abuhakmeh</guid>
      <description>&lt;p&gt;I have been coding for 10 years.&lt;/p&gt;

&lt;p&gt;You can find me on Twitter as &lt;a href="https://twitter.com/buhakmeh" rel="noopener noreferrer"&gt;@buhakmeh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in New Cumberland, PA which is close to the capital of Harrisburg.&lt;/p&gt;

&lt;p&gt;I work currently work for &lt;a href="https://rimdev.io" rel="noopener noreferrer"&gt;Ritter Insurance Marketing&lt;/a&gt;. I also blog at &lt;a href="https://www.khalidabuhakmeh.com" rel="noopener noreferrer"&gt;khalidabuhakmeh.com&lt;/a&gt; about my .NET adventures.&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: C# and JavaScript on the ASP.NET stack.&lt;/p&gt;

&lt;p&gt;I am currently learning more about Vue and Functional Programming.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
