<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>asp.net-core on Marcin Zabłocki blog</title>
    <link>https://zablo.net/tags/asp.net-core/</link>
    <description>Recent content in asp.net-core on Marcin Zabłocki blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <managingEditor>Marcin Zabłocki</managingEditor>
    <webMaster>Marcin Zabłocki</webMaster>
    <copyright>2026 Marcin Zabłocki</copyright>
    <lastBuildDate>Tue, 24 May 2016 22:00:00 +0000</lastBuildDate>
    <atom:link href="https://zablo.net/tags/asp.net-core/index.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>Setup ASP.NET Core 1.0 debugging on Ubuntu 16.04</title>
      <link>https://zablo.net/blog/post/run-and-debug-asp-net-core-rc2-ubuntu-16-04/</link>
      <pubDate>Tue, 24 May 2016 22:00:00 +0000</pubDate>
      <author>Marcin Zabłocki</author>
      <guid>https://zablo.net/blog/post/run-and-debug-asp-net-core-rc2-ubuntu-16-04/</guid>
      <category>asp.net-core</category>
      <category>linux</category>
      <category>ubuntu</category>
      <category>.net-core</category>
      <category>debugging</category>
      <category>console</category>
      <category>vscode</category>
      <description>&lt;p&gt;There has been a lot of excitement about running ASP.NET Core 1.0 applications on Linux. Since RC2, Microsoft provided official support for running .NET Core on Ubuntu, however up to the date of writing this post, .NET Core is officially working only on Ubuntu 14.04. What about newest version of this OS? You can easily get it work (&lt;strong&gt;with debugging!&lt;/strong&gt;). Here&amp;rsquo;s the tutorial, &lt;strong&gt;how to run and debug ASP.NET Core 1.0 RC2 on Ubuntu 16.04&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;prerequsites&#34;&gt;Prerequsites&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Ubuntu 16.04 installed (can be a VM)&lt;/li&gt;&#xA;&lt;li&gt;Visual Studio Code with latest updates installed&lt;/li&gt;&#xA;&lt;li&gt;good will&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;installing-net-core-on-ubuntu-1604-dotnet&#34;&gt;Installing .NET Core on Ubuntu 16.04 (dotnet)&lt;/h2&gt;&#xA;&lt;p&gt;Run the following commands to add the following repository package sources to your system (taken from the official Microsoft&amp;rsquo;s &lt;a href=&#34;http://dot.net&#34; target=&#34;_blank&#34;&gt;&lt;a href=&#34;http://dot.net&#34;&gt;http://dot.net&lt;/a&gt;&lt;/a&gt; site, from Linux/Ubuntu section):&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sudo&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sh&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-c&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;echo &amp;#34;deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet/ trusty main&amp;#34; &amp;gt; /etc/apt/sources.list.d/dotnetdev.list&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sudo&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;apt-key&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;adv&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-keyserver&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;apt-mo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;trafficmanager&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;net&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-recv-keys&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;417A0893&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sudo&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;apt-get&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;update&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;Now, the original steps requires to run:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sudo&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;apt-get&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;install&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dotnet-dev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-preview1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;002702&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;But&amp;hellip; &lt;strong&gt;there will be an error&lt;/strong&gt;:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;The&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;following&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;have&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;unmet&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dependencies&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &lt;span class=&#34;nb&#34;&gt;dotnet-dev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-preview1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;002702&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Depends&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dotnet-sharedframework&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-microsoft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;netcore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-rc2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3002702&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;but&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;it&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;going&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;be&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;installed&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;E:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Unable&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;correct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;problems&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;you&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;have&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;held&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;broken&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;So, let&amp;rsquo;s fix it! Trying to install the dependant package &lt;em&gt;dotnet-sharedframework-microsoft.netcore.app&lt;/em&gt; will get you next error, saying that this package &lt;em&gt;depends on libicu52 but it is not installable&lt;/em&gt;. Really? Head to:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;packages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;ubuntu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;com&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;trusty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;amd64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;libicu52&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;download&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;and download .deb package. Now, go to the download location and install the package by running:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sudo&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dpkg&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-i&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;libicu52_52&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;3ubuntu0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;4_amd64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;deb&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;Now, you will be able to run the following commands:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sudo&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;apt-get&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;install&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dotnet-sharedframework&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-microsoft&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;netcore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-rc2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3002702&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sudo&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;apt-get&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;install&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dotnet-dev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-preview1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;002702&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;div class=&#34;mfp-play-wrapper&#34;&gt;&#xA;    &lt;a class=&#34;video-hover mfp-gif&#34; href=&#34;https://zablo.net/resources/822ec9a4-fb51-4544-8c39-a5a6b56f8861.png&#34; title=&#34;Install .NET Core on Ubuntu 16.04&#34;&gt;&#xA;        &lt;div&gt;&#xA;            &lt;img class=&#34;grayscale&#34; src=&#34;https://zablo.net/resources/822ec9a4-fb51-4544-8c39-a5a6b56f8861.png&#34; alt=&#34;Install .NET Core on Ubuntu 16.04&#34;&gt;&#xA;&#x9;&#x9;&#x9;&lt;div class=&#34;mfp-btn-play&#34;&gt;&lt;i class=&#34;fa fa-search-plus&#34;&gt;&lt;/i&gt;&lt;/div&gt;&#xA;        &lt;/div&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;   &#xA;&lt;p&gt;A few moments and&amp;hellip;&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;dotnet&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-version&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;&amp;hellip;yay! It&amp;rsquo;s installed.&lt;/p&gt;&#xA;&lt;div class=&#34;row&#34;&gt;&#xA;   &lt;div class=&#34;column twelve&#34;&gt;&#xA;        &lt;img src=&#34;https://zablo.net/resources/4847d069-f492-4bd2-8dd7-e686cacddddf.gif&#34; alt=&#34;.NET Core running on Ubuntu 16.04&#34; title=&#34;.NET Core running on Ubuntu 16.04&#34;&gt; &#xA;   &lt;/div&gt;&#xA;&lt;/div&gt;   &#xA;&lt;h2 id=&#34;visual-studio-code-aspnet-core-debugging-on-ubuntu-1604&#34;&gt;Visual Studio Code ASP.NET Core Debugging on Ubuntu 16.04&lt;/h2&gt;&#xA;&lt;p&gt;Now, when you have &lt;em&gt;dotnet&lt;/em&gt; installed, it&amp;rsquo;s time to setup the debugger. If already have a project to debug, that&amp;rsquo;s great. If not - download official samples from ASP.NET github repository (&lt;a href=&#34;https://github.com/aspnet/cli-samples&#34; target=&#34;_blank&#34;&gt;&lt;a href=&#34;https://github.com/aspnet/cli-samples&#34;&gt;https://github.com/aspnet/cli-samples&lt;/a&gt;&lt;/a&gt; - remember to run &lt;em&gt;dotnet restore&lt;/em&gt; in the project directory afterwards). After setting this up, just open project directory in VS Code.&lt;/p&gt;&#xA;&lt;p&gt;First of all, you need Visual Studio Code C# extension. To install it, just press &lt;strong&gt;Ctrl+E&lt;/strong&gt; inside VS Code and type:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ext&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;install&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;C&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;#&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;After sucessful installation, editor will prompt you to restart. And now&amp;hellip; another error!&#xA;It says, that Ubuntu 16.04 is not supported by .NET Core Debugger. Or is it? ;]&lt;/p&gt;&#xA;&lt;div class=&#34;mfp-play-wrapper&#34;&gt;&#xA;    &lt;a class=&#34;video-hover mfp-gif&#34; href=&#34;https://zablo.net/resources/de71bde9-e5fb-4dc2-a906-a3b3ae35eaf9.png&#34; title=&#34;Debug .NET Core on Ubuntu 16.04&#34;&gt;&#xA;        &lt;div&gt;&#xA;            &lt;img class=&#34;grayscale&#34; src=&#34;https://zablo.net/resources/6de8f74f-5e78-41d7-9c53-5ac8e98bd04a.jpg&#34; alt=&#34;Debug .NET Core on Ubuntu 16.04&#34;&gt;&#xA;&#x9;&#x9;&#x9;&lt;div class=&#34;mfp-btn-play&#34;&gt;&lt;i class=&#34;fa fa-search-plus&#34;&gt;&lt;/i&gt;&lt;/div&gt;&#xA;        &lt;/div&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;  &#xA;&lt;p&gt;To HACK this issue, go back to the terminal, and head to&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;etc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;In this directory, there is a lot of files&amp;hellip; And here comes the greatness of &amp;ldquo;everything-is-a-file&amp;rdquo; Linux philosophy: the &lt;em&gt;/etc/&lt;/em&gt; directory contains the following files:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;os-release&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;lsb-release&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;Which as you might have guessed - store the information about Ubuntu version.&#xA;&lt;strong&gt;Let&amp;rsquo;s change all of the 16.04 to 14.04 and see what happens!&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;powershell&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sudo&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nano&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;os-release&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;edit&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;the&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;press&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Ctrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;O&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;ENTER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;save&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Ctrl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;repeat&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;the&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;same&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;procedure&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;the&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;next&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;sudo&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nano&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;lsb-release&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;I provide you my files if you are uncertain how they should look:&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;/etc/lsb-release&lt;/em&gt;&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;html&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DISTRIB_ID=Ubuntu&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DISTRIB_RELEASE=14.04&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DISTRIB_CODENAME=xenial&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DISTRIB_DESCRIPTION=&amp;#34;Ubuntu 14.04 LTS&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;&lt;em&gt;/etc/os-release&lt;/em&gt;&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;html&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;NAME=&amp;#34;Ubuntu&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VERSION=&amp;#34;14.04 LTS (Xenial Xerus)&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ID=ubuntu&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ID_LIKE=debian&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PRETTY_NAME=&amp;#34;Ubuntu 14.04 LTS&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;VERSION_ID=&amp;#34;14.04&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;HOME_URL=&amp;#34;http://www.ubuntu.com/&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SUPPORT_URL=&amp;#34;http://help.ubuntu.com/&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;BUG_REPORT_URL=&amp;#34;http://bugs.launchpad.net/ubuntu/&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;UBUNTU_CODENAME=xenial&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;Go back to Visual Studio Code. Oh my goodness! .NET Core Debugger have installed!&#xA;VS Code will also prompt you to add debug configuration file, click &lt;em&gt;yes&lt;/em&gt; to generate it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;debugging-aspnet-core-10-on-ubuntu-1604&#34;&gt;Debugging ASP.NET Core 1.0 on Ubuntu 16.04&lt;/h2&gt;&#xA;&lt;p&gt;The final step. Open debug view in Code and make sure that you have &lt;strong&gt;.NET Core Launch (console)&lt;/strong&gt; selected as debug target.&lt;/p&gt;&#xA;&lt;div class=&#34;row&#34;&gt;&#xA;   &lt;div class=&#34;column twelve&#34;&gt;&#xA;        &lt;img src=&#34;https://zablo.net/resources/e3ea0fd0-6360-418f-8714-5c881a276b65.gif&#34; alt=&#34;Launch ASP.NET Core debugger Ubuntu 16.04&#34; title=&#34;Launch ASP.NET Core debugger on Ubuntu 16.04&#34;&gt; &#xA;   &lt;/div&gt;&#xA;&lt;/div&gt;   &#xA;&lt;p&gt;Start debugging by pressing F5. Go back to your code, and mark breakpoint somewhere.&#xA;&lt;strong&gt;The ultimate test&lt;/strong&gt; - open web browser and hit &lt;em&gt;localhost:5000&lt;/em&gt; (or any other port if you have changed it)&amp;hellip; drumroll please&amp;hellip;&#xA;Isn&amp;rsquo;t it awesome?&lt;/p&gt;&#xA;&lt;div class=&#34;mfp-play-wrapper&#34;&gt;&#xA;    &lt;a class=&#34;video-hover mfp-gif&#34; href=&#34;https://zablo.net/resources/41d0c70b-c65f-4767-a5b7-8c6c01b82616.png&#34; title=&#34;Debuging .NET Core on Ubuntu 16.04&#34;&gt;&#xA;        &lt;div&gt;&#xA;            &lt;img class=&#34;grayscale&#34; src=&#34;https://zablo.net/resources/6226951b-b47c-4dc0-9800-eab8cdb1ba99.jpg&#34; alt=&#34;Debuging .NET Core on Ubuntu 16.04&#34;&gt;&#xA;&#x9;&#x9;&#x9;&lt;div class=&#34;mfp-btn-play&#34;&gt;&lt;i class=&#34;fa fa-search-plus&#34;&gt;&lt;/i&gt;&lt;/div&gt;&#xA;        &lt;/div&gt;&#xA;    &lt;/a&gt;&#xA;&lt;/div&gt;  &#xA;&lt;p&gt;I hope this post helped you to fully setup ASP.NET Core debugging on Ubuntu 16.04. Happy C# coding&amp;hellip; on Linux!&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Modular ASP.NET Core 1.0 project structure</title>
      <link>https://zablo.net/blog/post/modular-asp-net-core-project-structure/</link>
      <pubDate>Mon, 21 Mar 2016 23:00:00 +0000</pubDate>
      <author>Marcin Zabłocki</author>
      <guid>https://zablo.net/blog/post/modular-asp-net-core-project-structure/</guid>
      <category>asp.net-core</category>
      <category>asp.net-5</category>
      <category>components</category>
      <category>project</category>
      <category>areas</category>
      <description>&lt;p&gt;ASP.NET Core 1.0 (formely ASP.NET 5) introduced some new framework concepts as well as cut loose the project structure, giving the developers ability to fully customize it. In example, we are no more bound to the Areas folder structure, which in my opinion unnecessarily duplicated Controllers/Models/Views folder structure in each of them.&lt;/p&gt;&#xA;&lt;p&gt;Moreover, new version of the framework added a feature called View Components, which finally resolved issue of having additional controllers returning only partial views. From now on, we can make true components in ASP.NET without any workarounds.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve already written a few projects in ASP.NET Core 1.0 and here is how I worked my way into creating elastic project structure.&lt;/p&gt;&#xA;&lt;h2 id=&#34;well-structured-areas&#34;&gt;Well structured areas&lt;/h2&gt;&#xA;&lt;p&gt;First of all - the areas. They are in ASP.NET MVC for quite a while and they are really useful. Personally, I&amp;rsquo;ve used them every time when I had to write application with both &lt;strong&gt;admin panel&lt;/strong&gt; and &lt;strong&gt;client facing pages&lt;/strong&gt;. The bigger part usually landed inside main project structure and the smaller one inside the &lt;em&gt;Areas folder&lt;/em&gt;. And&amp;hellip; I hated that. I wanted &lt;strong&gt;Controllers inside the &lt;em&gt;Controllers folder&lt;/em&gt;&lt;/strong&gt;, Views inside Views folder and Models inside Models folder. Finally - I can do that really easily.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s say we have three areas: Main (client facing), Administrator and Content Authors. The output of the following configuration will look like this.&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;html&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;projectroot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└───Controllers&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───Admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───Authors&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───HomeController.cs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───(...) other client controllers&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└───Views&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───Admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───Authors&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───Shared&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───Home&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └───Index.cshtml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └───(...) other client views&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└───Models&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───Admin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───Authors&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───(...)HomePageViewModel.cs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;As you can see, Admin and Author controllers are placed inside Controllers folder - it is where you would start looking for any controller in somebody else&amp;rsquo;s project, don&amp;rsquo;t you?&#xA;The same rule applies for the Views and Models (actually - View Models) folders.&lt;/p&gt;&#xA;&lt;p&gt;To make this structure work, the only thing we need to do is to &lt;strong&gt;extend Razor View Engine&lt;/strong&gt;, so it will know &lt;strong&gt;how to find Views for particular Area&lt;/strong&gt;. This can be done by implementing &lt;em&gt;IViewLocationExpander&lt;/em&gt; interface:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;csharp&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;ViewLocationExpander&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IViewLocationExpander&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PopulateValues&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ViewLocationExpanderContext&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// nothing here&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IEnumerable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ExpandViewLocations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ViewLocationExpanderContext&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IEnumerable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;viewLocations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;area&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ActionContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ActionDescriptor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RouteConstraints&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FirstOrDefault&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rc&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RouteKey&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;area&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kt&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;additionalLocations&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LinkedList&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;area&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;additionalLocations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AddLast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;$&amp;#34;/Views/{area.RouteValue}&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;{1}/{0}.cshtml&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;viewLocations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Concat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;additionalLocations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;Now we need to attach this class to Razor engine. Head to &lt;em&gt;Startup.cs&lt;/em&gt; and find the line in which you add MVC to application services:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;csharp&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;services&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AddMvc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;and extend this line in order to add &lt;strong&gt;Razor View Engine Options&lt;/strong&gt;:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;csharp&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;services&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AddMvc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AddRazorOptions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;razorOptions&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;razorOptions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ViewLocationExpanders&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ViewLocationExpander&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;());&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;From now on, for every controller marked with  &lt;strong&gt;&lt;em&gt;[Area]&lt;/em&gt;&lt;/strong&gt; atrribute, the framework will search for it&amp;rsquo;s views inside proper folder located under projects Views folder. Of course, this solution requires to have &lt;strong&gt;exactly the same name in the folder structure as in the attribute parameter&lt;/strong&gt;. If you want to have different area name and different folder names, just add some &lt;em&gt;if/switch&lt;/em&gt; inside of the &lt;em&gt;ExpandViewLocations&lt;/em&gt; method and you will be good to go.&lt;/p&gt;&#xA;&lt;h2 id=&#34;reusable--isolated-components&#34;&gt;Reusable &amp;amp; isolated components&lt;/h2&gt;&#xA;&lt;p&gt;Some time ago, somebody asked on Stackoverflow, where the JavaScript files for the View Components should be placed in ASP.NET Core 1.0 projects. I&amp;rsquo;ve responed for that question, and here is my point of view (link to the answer bellow the post).&lt;/p&gt;&#xA;&lt;p&gt;Isolation of components should not only consider JavaScript files, but also backing code (&lt;em&gt;ViewComponent class&lt;/em&gt;) and the component&amp;rsquo;s view razor file. In my projects, I tend to make this kind of structure for View Components:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;markdown&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;projectroot&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└───Components&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───AwesomeComponent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └───Awesome.cshtml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └───AwesomeComponent.cs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └───AwesomeComponentModel.cs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └───CommentsComponent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └───Comments.cshtml&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └───CommentsComponent.cs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        └───CommentsComponentModel.cs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;I treat every component as totally isolated entity. It is concise and it only contains necessary files. I can easily cut the component from my project and put it into another. For example, the Comments Component (actually used on this blog to show Discuss) just renders the required HTML with some dynamically rendered parameters passed to it&amp;rsquo;s view via CommentsComponentModel (which is the View Model).&lt;/p&gt;&#xA;&lt;p&gt;View, Backend code and Model are all in one place, so when you move around the component&amp;rsquo;s folder, you are sure that you move whole component. Moreover, when you are modyfying them, you have quick access to all of their parts.&lt;/p&gt;&#xA;&lt;p&gt;It will be convinient to put JavaScript and/or CSS files which are highly coupled with a component also in such structure. You can do this by simply creating the file under the component&amp;rsquo;s folder, and then writing a &lt;strong&gt;GULP TASK&lt;/strong&gt; that will copy JS/CSS files to &lt;strong&gt;wwwroot&lt;/strong&gt;. From that point, you will be able to link that JavaScript code on component&amp;rsquo;s .cshtml using standard syntax:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;html&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;~/Components/awesomecomponent.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;After such setup, in order to render View Component with it&amp;rsquo;s parameters, use the following syntax:&lt;/p&gt;&#xA;&lt;figure class=&#34;codeblock on-ink&#34;&gt;&#xA;  &lt;figcaption class=&#34;codeblock__caption&#34;&gt;&#xA;    &lt;span class=&#34;codeblock__lang&#34;&gt;csharp&lt;/span&gt;&#xA;    &lt;span class=&#34;codeblock__caption-right&#34;&gt;&#xA;      &lt;button type=&#34;button&#34; class=&#34;codeblock__copy&#34; aria-label=&#34;Copy code to clipboard&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/span&gt;&#xA;  &lt;/figcaption&gt;&#xA;  &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;@await&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Component&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;InvokeAsync&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;AwesomeComponent&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AwesomeComponentModel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;&lt;/figure&gt;&#xA;&lt;p&gt;And remember to put &lt;strong&gt;&lt;em&gt;[ViewComponent(Name = &amp;ldquo;Awesome&amp;rdquo;)]&lt;/em&gt;&lt;/strong&gt; annotation on the top of component&amp;rsquo;s backing class if you want to avoid adding full &lt;em&gt;(Name)ViewComponent&lt;/em&gt; convention and just have &lt;em&gt;(Name)Component&lt;/em&gt; classes.&lt;/p&gt;&#xA;&lt;h3 id=&#34;additional-links&#34;&gt;Additional links&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;My Stackoverflow anwser for &lt;em&gt;&amp;ldquo;Where should my Javascript go for MVC 6 view components?&amp;rdquo;&lt;/em&gt; &lt;a href=&#34;http://stackoverflow.com/questions/34932699/where-should-my-javascript-go-for-mvc-6-view-components/34933221#34933221&#34; target=&#34;_blank&#34;&gt;&lt;a href=&#34;http://stackoverflow.com/questions/34932699/where-should-my-javascript-go-for-mvc-6-view-components/34933221#34933221&#34;&gt;http://stackoverflow.com/questions/34932699/where-should-my-javascript-go-for-mvc-6-view-components/34933221#34933221&lt;/a&gt;&lt;/a&gt;&lt;/projectroot&gt;&lt;/string&gt;&lt;/string&gt;&lt;/string&gt;&lt;/projectroot&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>ASP.NET Core Redis HTML Cache</title>
      <link>https://zablo.net/blog/post/asp-net-core-redis-html-cache/</link>
      <pubDate>Tue, 08 Mar 2016 22:51:42 +0000</pubDate>
      <author>Marcin Zabłocki</author>
      <guid>https://zablo.net/blog/post/asp-net-core-redis-html-cache/</guid>
      <category>asp.net-5</category>
      <category>asp.net-core</category>
      <category>html-cache</category>
      <category>redis</category>
      <category>cache</category>
      <description>&lt;div&gt;&#xA;    &lt;p&gt;Previous versions of ASP.NET MVC framework had out-of-the-box &lt;strong&gt;OutputCache&lt;/strong&gt;&#xA;        attribute, which could be used to improve MVC aplications performance by - as the name describes&#xA;        - caching the output of actions to which the attribute was added.&#xA;    &lt;/p&gt;&#xA;    &lt;p&gt;&#xA;        In ASP.NET Core 1.0 (formerly ASP.NET 5) the attribute no longer exists. The ASP.NET team&#xA;        provided &lt;em&gt;ResponseCache&lt;/em&gt; attribute, however it&#39;s purpose is only to set HTTP response headers, so&#xA;        the proxy servers behind which the web application could be running, could cache the response.&#xA;        What about local caching? So far, I didn&#39;t found out-of-the-box solution in the edge version of&#xA;        the framework (which is as of writing this post in RC1 state).&#xA;    &lt;/p&gt;&#xA;    &lt;p&gt;So... the need for that functionality became the code in my Visual Studio. I will show you how&#xA;        I&#39;ve implemented &lt;strong&gt;full HTML cache for ASP.NET Core 1.0 using REDIS&lt;/strong&gt; cache (and&#xA;        also in-proc memory), and I&#39;ll be glad to read comments about my solution and also discuss about&#xA;        it. Here it goes!&#xA;    &lt;/p&gt;&#xA;    &lt;h2&gt;Implementing ASP.NET Core HTML cache&lt;/h2&gt;&#xA;    &lt;h3&gt;Prerequisites:&lt;/h3&gt;&#xA;    &lt;ul&gt;&#xA;        &lt;li&gt;ASP.NET 5 (ASP.NET Core 1.0) RC1 installed&lt;/li&gt;&#xA;        &lt;li&gt;Visual Studio 2015&lt;/li&gt;&#xA;        &lt;li&gt;access to any Redis server*&lt;/li&gt;&#xA;        &lt;li&gt;ASP.NET dnx451 targeted project (there is no .NET Core support for Redis Cache yet)&lt;/li&gt;&#xA;    &lt;/ul&gt;&#xA;    &lt;p&gt;&#xA;        *Redis is obviously optional when you use memory cache&#xA;    &lt;/p&gt;&#xA;    &lt;h3&gt;Preparation&lt;/h3&gt;&#xA;    &lt;p&gt;&#xA;        My cache solution will be a tandem of ASP.NET Middleware and C# Attribute usage.&#xA;        Let&#39;s start with creating new Web Application project. You will also need some additional&#xA;        packages, so open project.json and add those:&#xA;        &lt;br&gt;&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-markup&#34;&gt;&lt;code&gt;&#34;Microsoft.Extensions.Caching.Memory&#34;: &#34;1.0.0-rc1-final&#34;,&#xA;&#34;Microsoft.Extensions.Caching.Redis&#34;: &#34;1.0.0-rc1-final&#34;&lt;/code&gt;&lt;/pre&gt;&#xA;    If Visual Studio fails to restore packages, make sure that you have proper package sources. Those&#xA;    are mine:&#xA;    (Nuget.config)&#xA;    &lt;pre&gt;&lt;code class=&#34;language-markup&#34;&gt;&amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&amp;gt;&#xA;&amp;lt;configuration&amp;gt;&#xA;    &amp;lt;packageSources&amp;gt;&#xA;        &amp;lt;add key=&#34;api.nuget.org&#34; value=&#34;https://api.nuget.org/v3/index.json&#34; /&amp;gt;&#xA;        &amp;lt;add key=&#34;AspNetVNext&#34; value=&#34;https://www.myget.org/F/aspnetvnext/api/v2/&#34;&#xA;        /&amp;gt;&#xA;        &amp;lt;add key=&#34;nuget.org&#34; value=&#34;https://www.nuget.org/api/v2/&#34; /&amp;gt;&#xA;        &amp;lt;add key=&#34;Roslyn&#34; value=&#34;https://www.myget.org/F/roslyn-nightly/&#34; /&amp;gt;&#xA;        &amp;lt;add key=&#34;DotNet&#34; value=&#34;https://www.myget.org/F/dotnet-corefx/&#34; /&amp;gt;&#xA;    &amp;lt;/packageSources&amp;gt;&#xA;&amp;lt;/configuration&amp;gt;&lt;/code&gt;&#xA;                    &lt;/pre&gt;&#xA;    &lt;h3&gt;How it will work&lt;/h3&gt;&#xA;    &lt;p&gt;&#xA;        Before writing the code, here is a description how my solution will work:&#xA;    &lt;/p&gt;&#xA;    &lt;ol&gt;&#xA;        &lt;li&gt;Adding custom created &lt;strong&gt;Cache attribute&lt;/strong&gt; adds action filter to marked action&lt;/li&gt;&#xA;        &lt;li&gt;Action filter handles those events:&#xA;            &lt;ol&gt;&#xA;                &lt;li&gt;&#xA;                    &lt;b&gt;OnActionExecuting&lt;/b&gt; - to prevent action executing if cached response exists, and to write&#xA;                    cached response into current request result&#xA;                &lt;/li&gt;&#xA;                &lt;li&gt;&#xA;                    &lt;b&gt;OnResultExecuting&lt;/b&gt; - to finish request handling, when cache is hit&#xA;                &lt;/li&gt;&#xA;                &lt;li&gt;&#xA;                    &lt;b&gt;OnResultExecuted&lt;/b&gt; - when there was a cache miss, to save response into cache&#xA;                &lt;/li&gt;&#xA;            &lt;/ol&gt;&#xA;        &lt;/li&gt;&#xA;        &lt;li&gt;&#xA;            Custom middleware to intercept response stream and provide own MemoryStream to which custom code will be&#xA;            able to write and read.w&#xA;        &lt;/li&gt;&#xA;    &lt;/ol&gt;&#xA;    &lt;h3&gt;Implementation - abstract layer&lt;/h3&gt;&#xA;    &lt;p&gt;&#xA;        After restoring packages and setting target framework - add new folder to your project, call it Cache - all of&#xA;        cache related code will land there.&#xA;    &lt;/p&gt;&#xA;    &lt;p&gt;&#xA;        In order to have some abstraction and avoid hard dependencies, I&#39;ve created &lt;em&gt;ICacheService&lt;/em&gt; interface,&#xA;        which exposes general purpose cache methods:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;public interface ICacheService&#xA;{&#xA;    void Store(string key, object content);&#xA;&#xA;    void Store(string key, object content, int duration);&#xA;&#xA;    T Get&lt;t&gt;(string key) where T : class;&#xA;}&lt;/t&gt;&lt;/code&gt;&#xA;                &lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        Implementation of this service will be described later in this post.&lt;br&gt;&#xA;        Next - let&#39;s add &lt;em&gt;CacheAttribute&lt;/em&gt; class, which will implement &lt;em&gt;IActionFilter&lt;/em&gt; and inherit from&#xA;        &lt;em&gt;ResultFilterAttribute&lt;/em&gt;.&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;public class CacheAttribute : ResultFilterAttribute, IActionFilter&#xA;{&#xA;//...&#xA;}&lt;/code&gt;&#xA;                &lt;/pre&gt;&#xA;    &lt;h3&gt;Custom middleware for accessing response stream&lt;/h3&gt;&#xA;    &lt;p&gt;&#xA;        Before writing the implementation of this attribute, we will need access to the response stream (which is&#xA;        somehow locked to write/read by default). In order to obtain this functionality, add the middleware class&#xA;        CacheMiddleware.cs. Every middleware class requires non-interfaced method with the signature as follows:&#xA;        &lt;br&gt;&#xA;        &lt;code class=&#34;language-csharp&#34;&gt;public async Task Invoke(HttpContext httpContext)&lt;/code&gt;&#xA;    &lt;/p&gt;&#xA;    &lt;p&gt;&#xA;        By desing, every middleware must invoke further registered middlewares, there is no exception for this one.&#xA;        Easiest way to do this is to add &lt;em&gt;RequestDelegate&lt;/em&gt; dependency in constructor, so build-in ASP.NET DI&#xA;        container will inject this object into our middleware.&#xA;    &lt;/p&gt;&#xA;    &lt;p&gt;&#xA;        Purpose of &lt;strong&gt;&lt;em&gt;CacheMiddleware&lt;/em&gt;&lt;/strong&gt; is to intercept request, and provide custom stream to which&#xA;        further middlewares could write (and read). When the middleware invocation process will return to&#xA;        &lt;em&gt;CacheMiddleware&lt;/em&gt;, this stream&#39;s content will be copied to original response stream. Full implementation&#xA;        of this class:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;public class CacheMiddleware&#xA;{&#xA;&#x9;protected RequestDelegate NextMiddleware;&#xA;&#xA;&#x9;public CacheMiddleware(RequestDelegate nextMiddleware)&#xA;&#x9;{&#xA;&#x9;&#x9;NextMiddleware = nextMiddleware;&#xA;&#x9;}&#xA;&#xA;&#x9;public async Task Invoke(HttpContext httpContext)&#xA;&#x9;{&#xA;&#x9;&#x9;using (var responseStream = new MemoryStream())&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;var fullResponse = httpContext.Response.Body;&#xA;&#x9;&#x9;&#x9;httpContext.Response.Body = responseStream;&#xA;&#x9;&#x9;&#x9;await NextMiddleware.Invoke(httpContext);&#xA;&#x9;&#x9;&#x9;responseStream.Seek(0, SeekOrigin.Begin);&#xA;&#x9;&#x9;&#x9;await responseStream.CopyToAsync(fullResponse);&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        To make use of this class, we need to add it to the request pipeline. In &lt;em&gt;Startup.cs&lt;/em&gt; file, in Configure&#xA;        method, just before &lt;em&gt;app.UseMvc()&lt;/em&gt;, add:&#xA;        &lt;br&gt;&#xA;        &lt;code class=&#34;language-csharp&#34;&gt;app.UseMiddleware&amp;lt;CacheMiddleware&amp;gt;();&lt;/code&gt;&#xA;    &lt;/p&gt;&#xA;    &lt;h3&gt;Cache attribute&lt;/h3&gt;&#xA;    &lt;p&gt;&#xA;        We are now set to write CacheAttribute implementation. First, add those properties to the&#xA;        &lt;em&gt;CacheAttribute.cs&lt;/em&gt; class:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;protected ICacheService CacheService { set; get; }&#xA;&#xA;public int Duration { set; get; }&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        Duration will be handy if there is any need for adjustment of cache time. Usage of CacheService property will be&#xA;        described shortly.&#xA;    &lt;/p&gt;&#xA;    &lt;p&gt;&#xA;        Let&#39;s move along with caching output in &lt;em&gt;OnResultExecuted&lt;/em&gt; method:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;public override void OnResultExecuted(ResultExecutedContext context)&#xA;{&#xA;&#x9;GetServices(context);&#xA;&#xA;&#x9;var cacheKey = context.HttpContext.Request.GetEncodedUrl().ToMd5();&#xA;&#x9;var httpResponse = context.HttpContext.Response;&#xA;&#x9;var responseStream = httpResponse.Body;&#xA;&#xA;&#x9;responseStream.Seek(0, SeekOrigin.Begin);&#xA;&#xA;&#x9;using (var streamReader = new StreamReader(responseStream, Encoding.UTF8, true, 512, true))&#xA;&#x9;{&#xA;&#x9;&#x9;var toCache = streamReader.ReadToEnd();&#xA;&#x9;&#x9;var contentType = httpResponse.ContentType;&#xA;&#x9;&#x9;var statusCode = httpResponse.StatusCode.ToString();&#xA;&#x9;&#x9;Task.Factory.StartNew(() =&amp;gt;&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;CacheService.Store(cacheKey + &#34;_contentType&#34;, contentType, Duration);&#xA;&#x9;&#x9;&#x9;CacheService.Store(cacheKey + &#34;_statusCode&#34;, statusCode, Duration);&#xA;&#x9;&#x9;&#x9;CacheService.Store(cacheKey, toCache, Duration);&#xA;&#x9;&#x9;});&#xA;&#xA;&#x9;}&#xA;&#x9;base.OnResultExecuted(context);&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        &lt;b&gt;What it does?&lt;/b&gt; First - it uses &lt;em&gt;Service Locator Pattern&lt;/em&gt; (which you could obviously replace with&#xA;        proper DI-way, it was used here for the quick implementation purposes) to get access to &lt;em&gt;CacheService&lt;/em&gt;.&#xA;        Then, it takes the response stream (which was provided by our custom middleware) and reads the whole of it (with&#xA;        leaving the stream open, thus the monstrous StreamReader constructor usage). After all of this, method stores&#xA;        &lt;strong&gt;response, response type and status code&lt;/strong&gt; in the Cache - this process is run in the background,&#xA;        so the request could process further without any blocking operations. At last, the &lt;em&gt;OnResultExecuted&lt;/em&gt;&#xA;        method invokes base method, so any remaining filters can execute.&#xA;    &lt;/p&gt;&#xA;    &lt;p&gt;&#xA;        Now, when we have response cached, we need a way to intercept request and write it to the response. There goes&#xA;        the implementation of &lt;em&gt;OnActionExecuting&lt;/em&gt; method:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;public void OnActionExecuting(ActionExecutingContext context)&#xA;{&#xA;&#x9;GetServices(context);&#xA;&#x9;var requestUrl = context.HttpContext.Request.GetEncodedUrl();&#xA;&#x9;var cacheKey = requestUrl.ToMd5();&#xA;&#x9;var cachedResult = CacheService.Get&amp;lt;string&amp;gt;(cacheKey);&#xA;&#x9;var contentType = CacheService.Get&amp;lt;string&amp;gt;(cacheKey + &#34;_contentType&#34;);&#xA;&#x9;var statusCode = CacheService.Get&amp;lt;string&amp;gt;(cacheKey + &#34;_statusCode&#34;);&#xA;&#x9;if (!string.IsNullOrEmpty(cachedResult) &amp;amp;&amp;amp; !string.IsNullOrEmpty(contentType) &amp;amp;&amp;amp;&#xA;&#x9;&#x9;!string.IsNullOrEmpty(statusCode))&#xA;&#x9;{&#xA;&#x9;&#x9;//cache hit&#xA;&#x9;&#x9;var httpResponse = context.HttpContext.Response;&#xA;&#x9;&#x9;httpResponse.ContentType = contentType;&#xA;&#x9;&#x9;httpResponse.StatusCode = Convert.ToInt32(statusCode);&#xA;&#xA;&#x9;&#x9;var responseStream = httpResponse.Body;&#xA;&#x9;&#x9;responseStream.Seek(0, SeekOrigin.Begin);&#xA;&#x9;&#x9;if (responseStream.Length &amp;lt;= cachedResult.Length)&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;responseStream.SetLength((long)cachedResult.Length &amp;lt;&amp;lt; 1);&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;using (var writer = new StreamWriter(responseStream, Encoding.UTF8, 4096, true))&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;writer.Write(cachedResult);&#xA;&#x9;&#x9;&#x9;writer.Flush();&#xA;&#x9;&#x9;&#x9;responseStream.Flush();&#xA;&#x9;&#x9;&#x9;context.Result = new ContentResult { Content = cachedResult };&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;else&#xA;&#x9;{&#xA;&#x9;&#x9;//cache miss&#xA;&#x9;}&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        As you can see, again - I take &lt;strong&gt;CacheService&lt;/strong&gt;. This time, the code searches for the same cache&#xA;        keys used to store response. If all keys are found (cache hit). From this point, we set response Content Type,&#xA;        Status Code and finally - we &lt;strong&gt;write cached HTML&lt;/strong&gt; into response stream. As you can see, there is a&#xA;        part of code which extends stream&#39;s length. I&#39;ve encountered an issue in which I could not write to the stream&#xA;        (because of the length issues), so I&#39;ve just extended the length of it.&#xA;        The line which sets &lt;strong&gt;context.Result&lt;/strong&gt; is very important, as the implementation of next method -&#xA;        &lt;em&gt;OnResultExecuting&lt;/em&gt; - relays on it:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;public override void OnResultExecuting(ResultExecutingContext context)&#xA;{&#xA;&#x9;if (context.Result is ContentResult)&#xA;&#x9;{&#xA;&#x9;&#x9;context.Cancel = true;&#xA;&#x9;}&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        This code cancels the request pipeline, if there was a Cache Hit. Of course, you can create more sophisticated&#xA;        condition here - I&#39;m sure that it will not work in some cases, but this post is about general idea of HTML&#xA;        cache, not &lt;i&gt;perfect-error-resistant-uber-implemntation.&lt;/i&gt;&#xA;    &lt;/p&gt;&#xA;    &lt;p&gt;&lt;em&gt;OnResultExecuted&lt;/em&gt; method will be left blank.&lt;/p&gt;&#xA;    &lt;h3&gt;Implementing Cache Service&lt;/h3&gt;&#xA;    &lt;p&gt;&#xA;        We are almost done. The only missing part is the actual &lt;strong&gt;CacheService&lt;/strong&gt;. As promised in the title&#xA;        of this post - &lt;strong&gt;Redis cache&lt;/strong&gt; will be used. I will also provide my implementation of&#xA;        &lt;strong&gt;MemoryCache&lt;/strong&gt;, so you can test HTML cache without Redis server.&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;public class RedisCacheService : ICacheService&#xA;{&#xA;&#x9;protected IDistributedCache Cache;&#xA;&#x9;private static int DefaultCacheDuration =&amp;gt; 60;&#xA;&#xA;&#x9;public RedisCacheService(IDistributedCache cache)&#xA;&#x9;{&#xA;&#x9;&#x9;Cache = cache;&#xA;&#x9;}&#xA;&#xA;&#x9;public void Store(string key, object content)&#xA;&#x9;{&#xA;&#x9;&#x9;Store(key, content, DefaultCacheDuration);&#xA;&#x9;}&#xA;&#xA;&#x9;public void Store(string key, object content, int duration)&#xA;&#x9;{&#xA;&#x9;&#x9;string toStore;&#xA;&#x9;&#x9;if (content is string)&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;toStore = (string)content;&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;else&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;toStore = JsonConvert.SerializeObject(content);&#xA;&#x9;&#x9;}&#xA;&#xA;&#x9;&#x9;duration = duration &amp;lt;= 0 ? DefaultCacheDuration : duration;&#xA;&#x9;&#x9;Cache.Set(key, Encoding.UTF8.GetBytes(toStore), new DistributedCacheEntryOptions()&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;AbsoluteExpiration = DateTime.Now + TimeSpan.FromSeconds(duration)&#xA;&#x9;&#x9;});&#xA;&#x9;}&#xA;&#xA;&#x9;public T Get&amp;lt;T&amp;gt;(string key) where T : class&#xA;&#x9;{&#xA;&#x9;&#x9;var fromCache = Cache.Get(key);&#xA;&#x9;&#x9;if (fromCache == null)&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;return null;&#xA;&#x9;&#x9;}&#xA;&#xA;&#x9;&#x9;var str = Encoding.UTF8.GetString(fromCache);&#xA;&#x9;&#x9;if (typeof(T) == typeof(string))&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;return str as T;&#xA;&#x9;&#x9;}&#xA;&#xA;&#x9;&#x9;return JsonConvert.DeserializeObject&amp;lt;T&amp;gt;(str);&#xA;&#x9;}&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        Implementation depends on &lt;em&gt;IDistributedCache&lt;/em&gt; - interface provided by the ASP.NET Core 1.0 framework&#xA;        itself. To use it, we need to configure it. Head to the &lt;em&gt;Startup.cs&lt;/em&gt; file again, but this time, go to&#xA;        &lt;em&gt;ConfigureServices&lt;/em&gt; method and add this code:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;services.AddCaching();&#xA;string redisConnection = Configuration[&#34;Redis:ConnectionString&#34;],&#xA;&#x9;   redisInstance = Configuration[&#34;Redis:InstanceName&#34;];&#xA;&#xA;services.AddSingleton&amp;lt;IDistributedCache&amp;gt;(factory =&amp;gt;&#xA;{&#xA;&#x9;var cache = new RedisCache(new RedisCacheOptions&#xA;&#x9;{&#xA;&#x9;&#x9;Configuration = redisConnection,&#xA;&#x9;&#x9;InstanceName = redisInstance&#xA;&#x9;});&#xA;&#xA;&#x9;return cache;&#xA;});&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        You can see that this code uses some configuration data. By default, ASP.NET Core 1.0 configuration is stored in&#xA;        &lt;em&gt;appsettings.json&lt;/em&gt; file. Open it and configure your Redis instance connection strings:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-markup&#34;&gt;&lt;code&gt;&#34;Redis&#34;: {&#xA;    &#34;ConnectionString&#34;: &#34;redis-server:7331,password=correcthorsebatterystaple&#34;,&#xA;    &#34;InstanceName&#34;: &#34;redis&#34;&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        Last thing to do is to add implemented &lt;em&gt;CacheAttribute&lt;/em&gt; and &lt;em&gt;RedisCacheService&lt;/em&gt; to the&#xA;        application. Just add those lines bellow the previous Redis-related ones in &lt;em&gt;Startup.cs&lt;/em&gt;:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;services.AddSingleton&amp;lt;ICacheService, RedisCacheService&amp;gt;();&#xA;services.AddTransient&amp;lt;CacheAttribute&amp;gt;();&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;h3&gt;Testing the solution&lt;/h3&gt;&#xA;    &lt;p&gt;&#xA;        OK, &lt;b&gt;let&#39;s test it!&lt;/b&gt; I&#39;ve replaced original &lt;em&gt;Home/Index.cshtml&lt;/em&gt; with this code:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-markup&#34;&gt;&lt;code&gt;@model dynamic&#xA;@DateTime.Now&#xA;&amp;lt;script type=&#34;text/javascript&#34;&amp;gt;&#xA;    document.write(&#34;&amp;lt;p&amp;gt;&#34; + new Date().toLocaleString() + &#34;&amp;lt;/p&amp;gt;&#34;);&#xA;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        and then I&#39;ve added &lt;strong&gt;CacheAttribute&lt;/strong&gt; to &lt;em&gt;HomeController&lt;/em&gt; Index method:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;[Cache(Duration = 30)]&#xA;public IActionResult Index()&#xA;{&#xA;&#x9;return View();&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;p&gt;&#xA;        Now - let&#39;s start the application using &lt;em&gt;dnx web&lt;/em&gt; (or &lt;em&gt;dnx-watch web&lt;/em&gt;) command and open&#xA;        &lt;em&gt;http://localhost:5000&lt;/em&gt; (default URL). First request processes along the whole pipeline, but the second&#xA;        one responds from cache, as you can see in the screenshots bellow.&#xA;    &lt;/p&gt;&#xA;    &lt;div class=&#34;row&#34;&gt;&#xA;        &lt;div class=&#34;column six&#34;&gt;&#xA;            &lt;h3&gt;Full request&lt;/h3&gt;&#xA;            &lt;img src=&#34;https://zablo.net/resources/d58c4af9-c712-4e60-8ef4-0e17beeecd33.png&#34; alt=&#34;ASP.NET Core 1.0 Redis Cached HTML&#34;&gt;&#xA;        &lt;/div&gt;&#xA;        &lt;div class=&#34;column six&#34;&gt;&#xA;            &lt;h3&gt;Cached request&lt;/h3&gt;&#xA;            &lt;img src=&#34;https://zablo.net/resources/ea52f328-dadd-4a3d-831e-fb2e4d63d96f.png&#34; alt=&#34;ASP.NET Core 1.0 Redis Cached HTML&#34;&gt;&#xA;        &lt;/div&gt;&#xA;        &lt;div class=&#34;column twelve&#34;&gt;&#xA;            &lt;h3&gt;Redis server view&lt;/h3&gt;&#xA;            &lt;img src=&#34;https://zablo.net/resources/73d5b618-443a-454f-90d2-89a9d2776f3d.png&#34; alt=&#34;ASP.NET Core 1.0 Redis Cached HTML&#34;&gt;&#xA;        &lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;    &lt;h2&gt;Using memory to cache HTML instead of Redis&lt;/h2&gt;&#xA;    &lt;p&gt;&#xA;        As my implementation is interface-only dependant, the &lt;em&gt;RedisCacheService&lt;/em&gt; could be easily replaced by&#xA;        In-memory Cache. Here is the implementation:&#xA;    &lt;/p&gt;&#xA;    &lt;pre class=&#34;language-csharp&#34;&gt;&lt;code&gt;public class MemoryCacheService : ICacheService&#xA;{&#xA;&#x9;protected IMemoryCache Cache;&#xA;&#xA;&#x9;public MemoryCacheService(IMemoryCache cache)&#xA;&#x9;{&#xA;&#x9;&#x9;Cache = cache;&#xA;&#x9;}&#xA;&#xA;&#x9;public void Store(string key, object content)&#xA;&#x9;{&#xA;&#x9;&#x9;Store(key, content, DefaultCacheDuration);&#xA;&#x9;}&#xA;&#xA;&#x9;public void Store(string key, object content, int duration)&#xA;&#x9;{&#xA;&#x9;&#x9;object cached;&#xA;&#x9;&#x9;if (Cache.TryGetValue(key, out cached))&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;Cache.Remove(key);&#xA;&#x9;&#x9;}&#xA;&#xA;&#x9;&#x9;Cache.Set(key, content,&#xA;&#x9;&#x9;&#x9;new MemoryCacheEntryOptions&#xA;&#x9;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;&#x9;AbsoluteExpiration = DateTime.Now + TimeSpan.FromSeconds(duration),&#xA;&#x9;&#x9;&#x9;&#x9;Priority = CacheItemPriority.Low&#xA;&#x9;&#x9;&#x9;});&#xA;&#x9;}&#xA;&#xA;&#xA;&#x9;private static int DefaultCacheDuration =&amp;gt; 60;&#xA;&#xA;&#x9;public T Get&amp;lt;T&amp;gt;(string key) where T : class&#xA;&#x9;{&#xA;&#x9;&#x9;object result;&#xA;&#x9;&#x9;if (Cache.TryGetValue(key, out result))&#xA;&#x9;&#x9;{&#xA;&#x9;&#x9;&#x9;return result as T;&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;return null;&#xA;&#x9;}&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;h2&gt;Wrap up&lt;/h2&gt;&#xA;    &lt;p&gt;And that&#39;s it. I hope you like my post, please share or/and leave a comment!&#xA;        Of course, the whole source code can be found on github: &lt;a&#xA;            href=&#34;https://github.com/marrrcin/aspnet-core-redis-html-cache&#34; target=&#34;_blank&#34;&#xA;            title=&#34;ASP.NET Core 1.0 Redis HTML Cache&#34;&gt;https://github.com/marrrcin/aspnet-core-redis-html-cache&lt;/a&gt;&#xA;        &lt;br&gt;&#xA;        &lt;strong&gt;Please comment and share if you like it!&lt;/strong&gt;&#xA;    &lt;/p&gt;&#xA;&lt;/div&gt;</description>
    </item>
  </channel>
</rss>
