<?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>Forem: elfalem</title>
    <description>The latest articles on Forem by elfalem (@elfalem).</description>
    <link>https://forem.com/elfalem</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%2F207528%2F80682818-8adf-4ad9-ae2f-2b615c66dd10.png</url>
      <title>Forem: elfalem</title>
      <link>https://forem.com/elfalem</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/elfalem"/>
    <language>en</language>
    <item>
      <title>Tale of .NET Core and the JSON SQLite Extension</title>
      <dc:creator>elfalem</dc:creator>
      <pubDate>Fri, 09 Apr 2021 16:59:05 +0000</pubDate>
      <link>https://forem.com/dealeron/tale-of-net-core-and-the-json-sqlite-extension-ddo</link>
      <guid>https://forem.com/dealeron/tale-of-net-core-and-the-json-sqlite-extension-ddo</guid>
      <description>&lt;p&gt;I was working on a .NET Core application and was getting to the stage where data needed to be persisted. I wanted to use SQLite because it's great as an &lt;a href="https://sqlite.org/appfileformat.html" rel="noopener noreferrer"&gt;application file format&lt;/a&gt;. Some of the data would be stored using JSON. Although SQLite doesn't have built-in functionality for working with JSON, it allows the use of &lt;a href="https://www.sqlite.org/loadext.html" rel="noopener noreferrer"&gt;extensions&lt;/a&gt;. This is a very powerful feature allowing anyone to customize SQLite to their needs. Things like JSON support (&lt;a href="https://www.sqlite.org/json1.html" rel="noopener noreferrer"&gt;JSON1&lt;/a&gt;) and full-text search (&lt;a href="https://sqlite.org/fts3.html" rel="noopener noreferrer"&gt;FTS3 and FTS4&lt;/a&gt;) are implemented in this way.&lt;/p&gt;

&lt;p&gt;Although loadable extensions can be statically linked at compile time, they can also be dynamically linked at run time. The latter is very beneficial because it means you don't have to re-compile your own version of SQLite to include an extension and ship it with your application. Instead, you can leverage an existing SQLite instance and load the necessary extensions at run time.&lt;/p&gt;

&lt;p&gt;In the case of .NET, there is the &lt;a href="https://www.nuget.org/packages/System.Data.SQLite.Core" rel="noopener noreferrer"&gt;System.Data.SQLite.Core&lt;/a&gt; NuGet package, the official database and ADO.NET provider. This instance of SQLite doesn't have JSON support enabled by default but I should be able to load the extension as mentioned above. However there were some unexpected challenges and thus began my journey into getting a SQLite extension to load in a .NET core application on a Linux machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initial Attempt
&lt;/h2&gt;

&lt;p&gt;I was working on a Linux Mint machine with .NET SDK version 2.2. After referencing the necessary packages, the first step was to create a connection to the database.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

dotnet new console
dotnet add package System.Data.SQLite.Core
dotnet add package Dapper


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

&lt;/div&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connection&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;SQLiteConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data Source=:memory:"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&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;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryFirst&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="s"&gt;"select SQLITE_VERSION() AS Version"&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;result&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;This part was straightforward. I was able to connect to an in-memory database and successfully execute a query through Dapper.&lt;/p&gt;

&lt;p&gt;The next step was loading the JSON1 extension. This is what the internet says to do to load an extension:&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connection&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;SQLiteConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data Source=:memory:"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SQLite.Interop.dll"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"sqlite3_json_init"&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;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryFirst&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="s"&gt;"select json(' { \"this\" : \"is\", \"a\": [ \"test\" ] } ')"&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;result&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;The above actually works on Windows (which I'll discuss at the end) but it fails on Linux. It shows an error indicating that the DLL is not found:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Unhandled Exception: System.Data.SQLite.SQLiteException: SQL logic error
The specified module could not be found.


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

&lt;/div&gt;

&lt;p&gt;Unfortunately I wasn't able to find a lot of information on the net to help with this issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure of the NuGet package and SQLite
&lt;/h2&gt;

&lt;p&gt;I started looking into how the NuGet package and SQLite work in hopes of uncovering something that resolves the issue. SQLite is written in C. The NuGet package allows us to interface with it by calling the C functions through C#. Since the C code is native, it's specific to different operating systems and architectures. The NuGet package contains the native SQLite code compiled to &lt;a href="https://docs.microsoft.com/en-us/nuget/create-packages/supporting-multiple-target-frameworks#architecture-specific-folders" rel="noopener noreferrer"&gt;different platforms&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Actually, if you directly download &lt;code&gt;System.Data.SQLite.Core&lt;/code&gt; from NuGet and extract it (.nupkg files are just archives), there isn't a lot of code. If you open up &lt;code&gt;System.Data.SQLite.Core.nuspec&lt;/code&gt; in a text editor you will find that it's a simple wrapper for other packages. It conditionally references various other packages based on the version of .NET framework encountered. For instance, the package &lt;code&gt;Stub.System.Data.SQLite.Core.NetStandard&lt;/code&gt; is referenced for .NET Core. This package has a much larger size (3.72 MB vs 11.44 KB for the wrapper) and is actually what contains the code.&lt;/p&gt;

&lt;p&gt;Downloading and extracting this package, you'll find a &lt;code&gt;lib/&lt;/code&gt; folder with the C# DLL as well as the &lt;code&gt;runtimes/&lt;/code&gt; folder with platform specific native code as mentioned above. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

runtimes/linux-x64/native/SQLite.Interop.dll
runtimes/win-x64/native/SQLite.Interop.dll
runtimes/osx-x64/native/SQLite.Interop.dll
runtimes/win-x86/native/SQLite.Interop.dll


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

&lt;/div&gt;

&lt;p&gt;You can inspect DLLs with &lt;a href="https://linux.die.net/man/1/nm" rel="noopener noreferrer"&gt;&lt;code&gt;nm&lt;/code&gt;&lt;/a&gt; on Linux. For example: &lt;code&gt;nm --dynamic runtimes/linux-x64/native/SQLite.Interop.dll&lt;/code&gt; shows all the symbols in the DLL. This is one way to examine what functions exist. A portion of the output for this command looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

0000000000017028 T sqlite3_hard_heap_limit64
0000000000114ea2 T sqlite3_index_column_info_interop
00000000000d3cc4 T sqlite3_initialize
00000000000d6240 T sqlite3_interrupt
0000000000142a7f T sqlite3Json1Init
0000000000142c9d T sqlite3_json_init
00000000000d2533 T sqlite3_keyword_check
00000000000d2528 T sqlite3_keyword_count
00000000000d24ba T sqlite3_keyword_name
00000000000d556d T sqlite3_last_insert_rowid
0000000000114679 T sqlite3_last_insert_rowid_interop
00000000000d3ca1 T sqlite3_libversion
00000000000d3cae T sqlite3_libversion_number
00000000000d764f T sqlite3_limit
0000000000095810 T sqlite3_load_extension
000000000001b695 T sqlite3_log
000000000001746c T sqlite3_malloc
00000000000174a4 T sqlite3_malloc64


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

&lt;/div&gt;

&lt;p&gt;In the above snippet, we find functions that are part of the core SQLite code such as &lt;code&gt;sqlite3_initialize&lt;/code&gt; and &lt;code&gt;sqlite3_load_extension&lt;/code&gt;. But we also find &lt;code&gt;sqlite3_json_init&lt;/code&gt; which is the entry point of the JSON1 loadable extension. It looks like the DLL is sourced from the &lt;a href="https://www.sqlite.org/amalgamation.html" rel="noopener noreferrer"&gt;SQLite Amalgamation&lt;/a&gt;. The SQLite Amalgamation is a single file containing all of SQLite proper as well as about half a dozen loadable extensions that are maintained by the SQLite team. Although the extensions are not enabled during compilation, having them bundled makes it easier to distribute and enable them at runtime.&lt;/p&gt;

&lt;p&gt;Putting all this together, the structure of the NuGet package is as follows:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdev6quqz92d5vubp2on.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdev6quqz92d5vubp2on.png" alt="SQLite package structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How SQLite Loads an Extension at Runtime
&lt;/h2&gt;

&lt;p&gt;Using a SQLite loadable extension at runtime entails dynamically linking to the extension code. Whether it's done through C# code (&lt;code&gt;connection.LoadExtension()&lt;/code&gt; in the above snippet), the command-line SQLite shell (&lt;code&gt;.load&lt;/code&gt;), or other means, ultimately the process involves searching for a DLL and loading it into memory.&lt;/p&gt;

&lt;p&gt;I came across a &lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/data/sqlite/extensions" rel="noopener noreferrer"&gt;Microsoft Docs page&lt;/a&gt; which indicates that SQLite doesn't leverage the .NET Core logic for finding native libraries. It directly calls the platform API to load the DLL. The way to influence this is to modify environment variables (&lt;code&gt;PATH&lt;/code&gt; on Windows, &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; or &lt;code&gt;DYLD_LIBRARY_PATH&lt;/code&gt; on Linux). There is &lt;a href="https://github.com/dotnet/docs/blob/main/samples/snippets/standard/data/sqlite/ExtensionsSample/Program.cs" rel="noopener noreferrer"&gt;sample code&lt;/a&gt; linked from the Doc that finds native libraries for the current runtime in a referenced NuGet package. The code notes that on Windows, &lt;code&gt;PATH&lt;/code&gt; could be modified with the path of found native libraries after the application starts. However for Linux, the environment variable must be modified before running the application which is cumbersome.&lt;/p&gt;

&lt;p&gt;Instead of changing environment variables to modify the DLL search locations, I wanted to see if we can somehow provide an absolute path for the DLL location. Looking at the &lt;a href="https://github.com/haf/System.Data.SQLite/blob/8d2e5027723654e97d2ad208b9a076da496eee79/System.Data.SQLite/SQLite3.cs#L2175" rel="noopener noreferrer"&gt;source for the NuGet package&lt;/a&gt; it's clear that, as the Microsoft Docs page noted, the C# code just invokes the native code (&lt;code&gt;sqlite3_load_extension()&lt;/code&gt;) directly. Therefore I looked at the &lt;a href="https://github.com/sqlite/sqlite/blob/4989a530a17e1caf4171d911bd42d8b7e5f34106/src/loadext.c#L646" rel="noopener noreferrer"&gt;SQLite source code&lt;/a&gt;. SQLite has the concept of &lt;a href="https://sqlite.org/vfs.html" rel="noopener noreferrer"&gt;VFS&lt;/a&gt; which is a portability layer at the bottom of the SQLite architecture. There are implementations of this abstraction for specific operating systems. Windows and Linux implementations are &lt;a href="https://github.com/sqlite/sqlite/blob/4989a530a17e1caf4171d911bd42d8b7e5f34106/src/os_win.c" rel="noopener noreferrer"&gt;os_win.c&lt;/a&gt; and &lt;a href="https://github.com/sqlite/sqlite/blob/4989a530a17e1caf4171d911bd42d8b7e5f34106/src/os_unix.c" rel="noopener noreferrer"&gt;os_unix.c&lt;/a&gt; respectively. The extension loading code eventually relies on VFS implementations to load DLLs. On Linux this is handled by &lt;a href="https://linux.die.net/man/3/dlopen" rel="noopener noreferrer"&gt;&lt;code&gt;dlopen&lt;/code&gt;&lt;/a&gt; and it's &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw" rel="noopener noreferrer"&gt;&lt;code&gt;LoadLibraryW&lt;/code&gt;&lt;/a&gt; on Windows. I later rediscovered this same information after reading the bottom (section 7) of a &lt;a href="https://www.sqlite.org/loadext.html#implementation_details" rel="noopener noreferrer"&gt;SQLite documentation page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Focusing on &lt;code&gt;dlopen()&lt;/code&gt;, the documentation shows that it accepts a full file path. This is great because I can obtain the location of the platform specific native library using the same approach as the Microsoft sample code from earlier. However instead of attempting to modify environment variables, I can provide the direct path to &lt;code&gt;connection.LoadExtension()&lt;/code&gt; and load the DLL. Since I'm on a Linux machine, I started by directly hard-coding the path to the native Linux library. If it works, I should be able to easily generalize it to work on other platforms.&lt;/p&gt;

&lt;p&gt;I changed the code to the following and ran &lt;code&gt;dotnet publish&lt;/code&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connection&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;SQLiteConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data Source=:memory:"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp2.2/publish/runtimes/linux-x64/native/SQLite.Interop.dll"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"sqlite3_json_init"&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;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryFirst&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="s"&gt;"select json(' { \"this\" : \"is\", \"a\": [ \"test\" ] } ')"&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;result&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;I then ran the published DLL from the &lt;code&gt;/bin/Debug/netcoreapp2.2/publish/&lt;/code&gt; folder and it worked. The query that includes the &lt;code&gt;json()&lt;/code&gt; function provided by the extension ran successfully and I got the expected result.&lt;/p&gt;

&lt;p&gt;I didn't realize it at the time but it becomes important that I ran the DLL from the &lt;code&gt;publish/&lt;/code&gt; folder and not the one that's one level up at &lt;code&gt;/bin/Debug/netcoreapp2.2/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confusing Observations
&lt;/h2&gt;

&lt;p&gt;At this point I thought I had a good solution for loading the DLL. I started making other unrelated changes to my program. But when I tried to run it with &lt;code&gt;dotnet run&lt;/code&gt;, it wouldn't work. The program abruptly exits when it reaches the line that loads the extension. I tried running the published DLL as before, and that works. But using &lt;code&gt;dotnet run&lt;/code&gt; does not. There are no exceptions or errors of any kind that's outputted. Even when debugging (with &lt;code&gt;justMyCode&lt;/code&gt; set to false in &lt;code&gt;.vscode/launch.json&lt;/code&gt;) there are no signs that anything is wrong. It even indicated an exit code of 0 (i.e. successful termination of program). Yet the program was quitting abruptly. I was very confused and posted a &lt;a href="https://stackoverflow.com/questions/66773573/dotnet-run-exits-unexpectedly-when-loading-sqlite-extension" rel="noopener noreferrer"&gt;question&lt;/a&gt; on Stack Overflow.&lt;/p&gt;

&lt;p&gt;Unfortunately I didn't get any answers. One thing I eventually tried was using newer versions of the .NET framework since I was on version 2.2. I changed the project target to 3.1 and tried &lt;code&gt;dotnet run&lt;/code&gt;. I got the same behavior of the program terminating without errors when it got to loading the extension. I executed the DLL (from the &lt;code&gt;/bin/Debug/netcoreapp3.1/&lt;/code&gt; folder) directly and this time it terminated in the same place but I got a &lt;code&gt;segmentation fault&lt;/code&gt; error. I was more confused because I expected this to work (it seemed like it was working when using version 2.2). I changed the target framework to 5.0 and tried again. I got the same results as 3.1. Then I changed it back to 2.2 and I started getting &lt;code&gt;segmentation fault&lt;/code&gt; there as well when executing the DLL directly. This was really puzzling because it was working earlier. We'll get to it later but this was because this time I was executing the DLL from &lt;code&gt;/bin/Debug/netcoreapp2.2/&lt;/code&gt; instead of &lt;code&gt;/bin/Debug/netcoreapp2.2/publish/&lt;/code&gt;. However, I didn't realize it at the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Segmentation Fault
&lt;/h2&gt;

&lt;p&gt;I turned my attention towards investigating the segmentation fault I was seeing. It means there is improper memory access occurring somewhere. However this can't happen in managed code so it was likely coming from the native C code for SQLite. I used &lt;code&gt;gdb&lt;/code&gt; to debug and find the offending line. The following is a snippet of the call stack after my program crashes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Thread 1 "dotnet" received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x00007fffec630c04 in sqlite3_mutex_enter (p=0x555555859f28) at ../core/sqlite3.c:25905
#2  0x00007fffec6f05c9 in createFunctionApi (db=0x5555559a43c8, zFunc=0x7fffec773d60 "json", nArg=1, enc=2099201, p=0x7fffec99a3cc &amp;lt;aFunc.54932+12&amp;gt;, xSFunc=0x7fffec75ae78 &amp;lt;jsonRemoveFunc&amp;gt;, 
    xStep=0x0, xFinal=0x0, xValue=0x0, xInverse=0x0, xDestroy=0x0) at ../core/sqlite3.c:162077
#3  0x00007fffec6f0708 in sqlite3_create_function (db=0x5555559a43c8, zFunc=0x7fffec773d60 "json", nArg=1, enc=2099201, p=0x7fffec99a3cc &amp;lt;aFunc.54932+12&amp;gt;, 
    xSFunc=0x7fffec75ae78 &amp;lt;jsonRemoveFunc&amp;gt;, xStep=0x0, xFinal=0x0) at ../core/sqlite3.c:162117
#4  0x00007fffec75cb33 in sqlite3Json1Init (db=0x5555559a43c8) at ../ext/json1.c:2591
#5  0x00007fffec75ccbd in sqlite3_json_init (db=0x5555559a43c8, pzErrMsg=0x7fffffffc670, pApi=0x7fffecd215c0 &amp;lt;sqlite3Apis&amp;gt;) at ../ext/json1.c:2623
#6  0x00007fffeca366ae in sqlite3LoadExtension (db=0x5555559a43c8, 
    zFile=0x7fff5807dd98 "/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp2.2/publish/runtimes/linux-x64/native/SQLite.Interop.dll", zProc=0x7fff5807de60 "sqlite3_json_init", 
    pzErrMsg=0x7fffffffc7c8) at ../core/sqlite3.c:124451
#7  0x00007fffeca36850 in sqlite3_load_extension (db=0x5555559a43c8, 
    zFile=0x7fff5807dd98 "/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp2.2/publish/runtimes/linux-x64/native/SQLite.Interop.dll", zProc=0x7fff5807de60 "sqlite3_json_init", 
    pzErrMsg=0x7fffffffc7c8) at ../core/sqlite3.c:124484
#8  0x00007fff7d01ca34 in ?? ()
#9  0x4164657a696c6169 in ?? ()
#10 0x0000000094cf77ea in ?? ()
#11 0x00007ffff66f6c38 in ?? () from /usr/share/dotnet/shared/Microsoft.NETCore.App/2.2.8/libcoreclr.so
#12 0x00007fffffffcbb8 in ?? ()


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

&lt;/div&gt;

&lt;p&gt;As expected the issue was in SQLite code. I tried looking at the &lt;a href="https://github.com/sqlite/sqlite/blob/4ad1a1c74caeee76124091e6e1771fae4afa1a33/src/mutex.c#L315" rel="noopener noreferrer"&gt;code&lt;/a&gt; where the problem was occurring but nothing stood out. Searching the web for segmentation faults related to SQLite I came across &lt;a href="https://sqlite.org/forum/forumpost/f7aaee5190" rel="noopener noreferrer"&gt;this forum post&lt;/a&gt;. The answer pointed to multiple instances of SQLite being the issue. Although the forum post was about a python application, I started wondering if there were multiple instances being created in my application as well. It seemed unlikely because I wasn't using threads or doing anything fancy. It was a simple console application. Perhaps something was lingering from earlier runs of my application? I tried restarting VS Code and the entire machine. I tried using an actual file instead of an in-memory database. I tried explicitly enabling extension loading (&lt;code&gt;connection.EnableExtensions(true)&lt;/code&gt;) even though it was already enabled. I looked at various compile and connection setup flags in SQLite. None of this helped.&lt;/p&gt;

&lt;p&gt;Looking up information about the function where the error is occurring (&lt;code&gt;sqlite3_mutex_enter&lt;/code&gt;), I came across a Stack Overflow question about access violation (i.e. segmentation fault) in python. The &lt;a href="https://stackoverflow.com/questions/24253406/access-violation-on-sqlite3-mutex-enter-why#24262103" rel="noopener noreferrer"&gt;accepted answer&lt;/a&gt; talks about multiple modules which apparently are DLLs on Windows. The solution in this case was invoking &lt;code&gt;sqlite3_initialize()&lt;/code&gt; in the SQLite code for the second module. Although it was a different language, it seemed like the same issue I was facing. And it seems to align with the eariler forum post about multiple instances of SQLite being the issue.&lt;/p&gt;

&lt;p&gt;Given the above information, I wanted to see if I can reach into the native library and invoke &lt;code&gt;sqlite3_initialize()&lt;/code&gt;. This was quite straightforward. I added the following method signature that corresponds to the C function I wanted to invoke and decorated it with &lt;code&gt;DllImport&lt;/code&gt; attribute specifying the full path to the DLL. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;DllImport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp2.2/publish/runtimes/linux-x64/native/SQLite.Interop.dll"&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;extern&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sqlite3_initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Then I added a call to this method before loading the extension.&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connection&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;SQLiteConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data Source=:memory:"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;sqlite3_initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp2.2/publish/runtimes/linux-x64/native/SQLite.Interop.dll"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"sqlite3_json_init"&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;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryFirst&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="s"&gt;"select json(' { \"this\" : \"is\", \"a\": [ \"test\" ] } ')"&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;result&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;After the above changes, the program did not terminate abruptly or lead to a segmentation fault. The JSON extension was loaded and the SQL query that made use of syntax provided by the extension executed successfully.&lt;/p&gt;

&lt;p&gt;It was working at this point. But the fix was a workaround. It was clear that there were two different DLLs being loaded. As we saw earlier &lt;code&gt;SQLite.Interop.dll&lt;/code&gt; is made from the SQLite Amalgamation. Therefore when the extension is loaded, a second full instance of SQLite was also being loaded. The first instance would be what is referenced directly by the NuGet package and used to establish the database connection and execute queries. I wanted to inspect the location of this first instance. To do so, I printed the location of the assembly that contains the &lt;code&gt;SQLiteConnection&lt;/code&gt; class.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&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="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SQLiteConnection&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;and got the output:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

/home/&amp;lt;my-user&amp;gt;/.nuget/packages/stub.system.data.sqlite.core.netstandard/1.0.113.2/lib/netstandard2.0/System.Data.SQLite.dll


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

&lt;/div&gt;

&lt;p&gt;This was surprising because I thought it would be referencing the package from the &lt;code&gt;publish/&lt;/code&gt; folder. I changed my code to refer to the same absolute path as above when loading the extension. I also removed the call to &lt;code&gt;sqlite3_initialize()&lt;/code&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="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connection&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;SQLiteConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Data Source=:memory:"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&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="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SQLiteConnection&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadExtension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/home/&amp;lt;my-user&amp;gt;/.nuget/packages/stub.system.data.sqlite.core.netstandard/1.0.113.2/runtimes/linux-x64/native/SQLite.Interop.dll"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"sqlite3_json_init"&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;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QueryFirst&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="s"&gt;"select json(' { \"this\" : \"is\", \"a\": [ \"test\" ] } ')"&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;result&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;The above worked. The same exact DLL was being referenced so there weren't multiple instances of SQLite.&lt;/p&gt;

&lt;p&gt;At this point, I remembered that publishing my program creates a DLL in the &lt;code&gt;publish/&lt;/code&gt; folder. Ever since I encountered the segmentation fault, I was executing the DLL that was one level up. When I executed the DLL inside the &lt;code&gt;publish/&lt;/code&gt; folder, I saw that the path of the assembly containing &lt;code&gt;SQLiteConnection&lt;/code&gt; was the following and the program was terminated with a segmentation fault error.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp2.2/publish/System.Data.SQLite.dll


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

&lt;/div&gt;

&lt;p&gt;It now made sense why the program worked when I initially hard-coded the full path of the DLL. I executed it from the &lt;code&gt;publish/&lt;/code&gt; folder. Therefore, the NuGet package and the &lt;code&gt;LoadExtension&lt;/code&gt; call were referencing the same native library. It meant only one instance of SQLite existed and hence there wasn't an issue. This observation raised a couple of questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions About .NET SDK
&lt;/h2&gt;

&lt;p&gt;The first question was why there are two seemingly identical DLLs created. Ever since I first worked with .NET Core I've noticed that when publishing a program &lt;code&gt;Foo&lt;/code&gt;, both &lt;code&gt;/bin/Debug/netcoreapp2.2/Foo.dll&lt;/code&gt; and &lt;code&gt;/bin/Debug/netcoreapp2.2/publish/Foo.dll&lt;/code&gt; get created but didn't figure out why. It was clear that the one in the &lt;code&gt;publish/&lt;/code&gt; folder is part of the end result of the publishing process. However, why does the same DLL exist one level up? There were quite a few Stack Overflow questions that asked about this (among other things) but frustratingly none of their answers addressed this particular question. I finally came across &lt;a href="https://stackoverflow.com/questions/49939630/why-does-dotnet-publish-create-2-copies-of-the-same-files" rel="noopener noreferrer"&gt;one question&lt;/a&gt; that directly answered it. I now understand that &lt;code&gt;/bin/Debug/netcoreapp2.2/&lt;/code&gt; is used as the output location when building. The files are then copied to &lt;code&gt;/bin/Debug/netcoreapp2.2/publish/&lt;/code&gt; when publishing. This would have been less confusing if Microsoft defaulted to a different folder as the output location of build artifacts, perhaps &lt;code&gt;/bin/Debug/netcoreapp2.2/build/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second question was why when executing the DLL from the build location, it looks for packages in &lt;code&gt;/home/&amp;lt;my-user&amp;gt;/.nuget/packages/&lt;/code&gt; (trivia: this is called a "probing directory". In this context, probing is the process of locating assemblies by the runtime). I was able to find the answer in the &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-build" rel="noopener noreferrer"&gt;documentation for &lt;code&gt;dotnet build&lt;/code&gt;&lt;/a&gt;. It states that:&lt;/p&gt;

&lt;blockquote&gt;For executable projects targeting versions earlier than .NET Core 3.0, library dependencies from NuGet are typically NOT copied to the output folder. They're resolved from the NuGet global packages folder at run time.&lt;/blockquote&gt;

&lt;p&gt;So this was a change in newer versions of the framework. I was able to confirm this by outputting the location of the assembly containing &lt;code&gt;SQLiteConnection&lt;/code&gt; for the different versions.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Build output DLL&lt;/th&gt;
&lt;th&gt;Publish output DLL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2.2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/home/&amp;lt;my-user&amp;gt;/.nuget/packages/stub.system.data.sqlite.core.netstandard/1.0.113.2/lib/netstandard2.0/System.Data.SQLite.dll&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp2.2/publish/System.Data.SQLite.dll&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3.1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp3.1/System.Data.SQLite.dll&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp3.1/publish/System.Data.SQLite.dll&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp5.0/System.Data.SQLite.dll&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/&amp;lt;my-project-path&amp;gt;/bin/Debug/netcoreapp5.0/publish/System.Data.SQLite.dll&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As can be seen above, newer versions of the framework load dependencies from a location relative to the executing program whether the program was built or published. This makes it easier to consistently locate a native library for my use case.&lt;/p&gt;

&lt;p&gt;Another unresolved item was why directly executing the DLL resulted a &lt;code&gt;segmentation fault&lt;/code&gt; error but using &lt;code&gt;dotnet run&lt;/code&gt; abruptly ends the program with no indication as to the cause. I was curious as to what actually prints the error on the terminal in the first case. In Linux, a segmentation fault is one of the many signals that can be sent from the kernel or between processes. According to &lt;a href="https://unix.stackexchange.com/questions/53289/does-segmentation-fault-message-come-under-stderr" rel="noopener noreferrer"&gt;this question&lt;/a&gt;, if the &lt;code&gt;SIGSEGV&lt;/code&gt; signal (i.e. a segmentation fault) is not handled by the program, the program is terminated and the the parent process (i.e. the shell) prints out the message to it's (not the program's, which is already terminated) standard error.&lt;/p&gt;

&lt;p&gt;So in the context of my program, it's the Linux shell that's telling me that there's a segmentation fault. I wanted to know how &lt;code&gt;dotnet run&lt;/code&gt; executes programs. Looking at the .NET SDK &lt;a href="https://github.com/dotnet/sdk/blob/ef99d3240a737fead9a731785fd7bc2d0ae157d6/src/Cli/Microsoft.DotNet.Cli.Utils/Command.cs#L37" rel="noopener noreferrer"&gt;source code&lt;/a&gt;, it starts a new process to execute the program. It also reads the standard output and standard error streams from the process it creates. However, I did not see logic dealing with handling signals such as &lt;code&gt;SIGSEGV&lt;/code&gt;. I've opened &lt;a href="https://github.com/dotnet/sdk/issues/16561" rel="noopener noreferrer"&gt;an issue&lt;/a&gt; for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Behavior on Windows
&lt;/h2&gt;

&lt;p&gt;To gain a broader understanding of items discussed above, I also looked at the behavior on a Windows machine. I used VS Code and not Visual Studio so that that doesn't become a factor. I looked into why simply specifying the DLL name without a path (e.g. &lt;code&gt;SQLite.Interop.dll&lt;/code&gt;) works on Windows. This is explained by the &lt;a href="https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#search-order-for-desktop-applications" rel="noopener noreferrer"&gt;search order&lt;/a&gt; used when loading DLLs. The first thing that the system checks is if the DLL with the same module name is already in memory. If so, then the already loaded DLL is used and the search stops. This seems to be what's happening in this case. When the application creates the database connection, it's using the native library (since it's an amalgamation containing the core SQLite code as well as the loadable extension). Therefore, the DLL is already loaded by the time we invoke &lt;code&gt;LoadExtension()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To test this further, I made a copy of the DLL in the same folder and renamed it to &lt;code&gt;SQLite.Interop_copy.dll&lt;/code&gt;. Then I modified the code to load this renamed DLL (again without specifying the path) and it was not able to find it. The search order is then to look for the DLL in various directories, and lastly in paths listed in the &lt;code&gt;PATH&lt;/code&gt; environment variable. The location of the renamed DLL doesn't match any of these and thus it's not found. If I modify the &lt;code&gt;PATH&lt;/code&gt; environment variable and add the location, then the renamed DLL is found. This made it possible to see the Windows DLL search heuristic in action.&lt;/p&gt;

&lt;p&gt;I also wanted to see if Windows will report a segmentation fault. Using the bash shell within VS Code, I got a &lt;code&gt;segementation fault&lt;/code&gt; while using &lt;code&gt;dotnet run&lt;/code&gt; as well as when directly executing the DLL. I then switched to using PowerShell in which case the program halted abruptly for both ways of executing it. So it looks like the behavior differs based on the shell I'm using when it comes to Windows.&lt;/p&gt;

&lt;p&gt;Lastly, I wanted to see how .NET handles segmentation faults within C# code. I didn't find a way to intentionally cause this with managed code so I had to switch to an unsafe context and write unmanaged code. I declared an integer variable and assign it's memory address to a pointer. I then shift the pointer by an arbitrary value and attempt to access that address as an integer.&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;unsafe&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;foo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pointer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;pointer&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;500000000&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="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)*&lt;/span&gt;&lt;span class="n"&gt;pointer&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;The above results in the exception: &lt;code&gt;Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.&lt;/code&gt; This indicates that there is a difference in how improper memory access is handled when it occurs in unmanaged code as opposed to a native library (which technically is still unmanaged code). If anyone has an explanation of why this is, I'd like to know.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;This journey was a diversion from the project I was working on but a lot of lessons were learned in the process. I learned more about the .NET build and publish steps and why there are duplicate DLL files in the output directory. I also learned about the the types of things that could be different between .NET SDK versions and the importance of ensuring installed versions are up-to-date. I have a better understanding of how DLLs are loaded in both Linux and Windows. I gained insight into the inner workings of SQLite and the NuGet packages that interface with it to allow it's usage in .NET. Diving into the source code of a very successful project and a complex one like that of a database seems daunting, but SQLite has excellent documentation and it was a rewarding experience.&lt;/p&gt;

&lt;p&gt;Furthermore, I got to use &lt;code&gt;gdb&lt;/code&gt; to debug a segmentation fault and also learned about how signals in general work in Linux. This was also a good experience at putting together information from various sources and different programming languages to solve a problem. It also demonstrated the effectiveness of using different phrases when searching for solutions. Searching for "segmentation fault" and "access violation" provided different pieces to the puzzle. Finally, this was a practice in perseverance. Not giving up easily when feeling lost is difficult. But at the same time, you gain a powerful sense of accomplishment when things make sense in the end. This image is an apt illustration:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FdzbQCj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FdzbQCj4.png" alt='The two states of every programmer: "I am a God" and "I have no idea what I'&gt;&lt;/a&gt;&lt;br&gt;
Image: &lt;a href="https://imgur.com/gallery/dzbQCj4" rel="noopener noreferrer"&gt;George Broussard&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>sqlite</category>
      <category>csharp</category>
      <category>database</category>
    </item>
    <item>
      <title>Alternative view engine for ASP.NET Core: Passing data from controller</title>
      <dc:creator>elfalem</dc:creator>
      <pubDate>Fri, 29 Jan 2021 17:21:40 +0000</pubDate>
      <link>https://forem.com/dealeron/alternative-view-engine-for-asp-net-core-passing-data-from-controller-2jbf</link>
      <guid>https://forem.com/dealeron/alternative-view-engine-for-asp-net-core-passing-data-from-controller-2jbf</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/dealeron/alternative-view-engine-for-asp-net-core-compiling-templates-2m2f"&gt;Part III&lt;/a&gt; in this series looked at how view templates are dynamically compiled including the processing of simple expressions (like &lt;code&gt;1 + 1&lt;/code&gt;) embedded in the templates. However, view templates are useful when we can pass values to them to be shown in the variable areas of the template. In this final post of the series, we'll demonstrate how values added to the &lt;code&gt;ViewData&lt;/code&gt; in the controller can be passed to the view template and rendered in the final output.&lt;/p&gt;

&lt;p&gt;In the Razor view engine, accessing a value from ViewData looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello @@ViewData["name"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our mustache syntax, we want a more readable syntax like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello {{name}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the above to work &lt;code&gt;name&lt;/code&gt; must exist as some sort of variable in the compiled template and have an assigned value.&lt;/p&gt;

&lt;p&gt;You can find the full contents of the source files discussed below on &lt;a href="https://gist.github.com/elfalem/c9e54f4eef8e400510c7509dd4920021"&gt;this GitHub gist&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Identify Replaceable Values
&lt;/h2&gt;

&lt;p&gt;The first step is knowing all the replaceable values in the view template. Since we allow expressions in our mustache syntax, we need a way to parse C# expressions and identify the variables. As we are already compiling the view template, we can use diagnostic messages from the compilation process to indirectly obtain the list of replaceable values.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;StacheTemplateCompiler.cs&lt;/code&gt;, add the following 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="k"&gt;private&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetMissingProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CSharpCompilation&lt;/span&gt; &lt;span class="n"&gt;compilation&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;missingProperties&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetDiagnostics&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&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="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CS0103"&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;d&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetMessage&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;Distinct&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;m&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The name '"&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"' does not exist in the current context"&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;missingProperties&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're using the Roslyn compiler for the heavy lifting. Any names it reports as not existing in the current context are replaceable values in the view template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adjust Compiled Template
&lt;/h2&gt;

&lt;p&gt;Once we know this list, we can create the class document a second time and declare the replaceable values as properties. In &lt;code&gt;StacheTemplateCompiler.cs&lt;/code&gt;, insert the following into the &lt;code&gt;Compile()&lt;/code&gt; method right before loading the assembly:&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;missingProperties&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetMissingProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;compilation&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;missingProperties&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;secondClassDocument&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateClassDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsedResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;templateClassName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;missingProperties&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;secondSyntaxTree&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CSharpSyntaxTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ParseText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secondClassDocument&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;compilation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReplaceSyntaxTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syntaxTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secondSyntaxTree&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;Additionally modify &lt;code&gt;CreateClassDocument()&lt;/code&gt; to accept a list of strings as the last paramater named &lt;code&gt;properties&lt;/code&gt; (optional, with default value of null). Insert the following code right after the creation of the &lt;code&gt;StringBuilder&lt;/code&gt; object.&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;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;properties&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="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;property&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;properties&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;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"public dynamic &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;property&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="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We declare each replaceable value as a dynamic property. Although we have been using strings in the examples, values sent through &lt;code&gt;ViewData&lt;/code&gt; from the controller could have other types. Therefore treating it as a dynamic property gives us the flexibility to accept all types.&lt;/p&gt;

&lt;p&gt;To use the &lt;code&gt;dynamic&lt;/code&gt; keyword, we need to include references to additional assemblies when creating the compilation. Update the beginning of the &lt;code&gt;CreateCompilation()&lt;/code&gt; method as follows:&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;assemblyLocations&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="c1"&gt;// system runtime assembly&lt;/span&gt;
    &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// the following are needed for dynamic keyword support&lt;/span&gt;
    &lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&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;AssemblyName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"System.Linq.Expressions"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&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;AssemblyName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.CSharp"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&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;AssemblyName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"System.Runtime"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&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;AssemblyName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"netstandard"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;Location&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;references&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assemblyLocations&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;location&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MetadataReference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateFromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pass Values to View Template
&lt;/h2&gt;

&lt;p&gt;At this point, we have code to successfully complile a view template while including C# properties for each replaceable value in the template. The last step is to set the properties with the the actual values provided from &lt;code&gt;ViewData&lt;/code&gt; when rendering the view template.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;StacheView.cs&lt;/code&gt;, update the &lt;code&gt;RenderAsync()&lt;/code&gt; method to set the properties using Reflection before invoking the &lt;code&gt;Execute()&lt;/code&gt; method on the compiled instance:&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;properties&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;GetRuntimeProperties&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;property&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;return&lt;/span&gt; &lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetIndexParameters&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Length&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;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMethod&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;&amp;amp;&amp;amp;&lt;/span&gt;
          &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsStatic&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;prop&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;properties&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContainsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prop&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;prop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;prop&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="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 test the changes, we will modify the &lt;code&gt;Bar&lt;/code&gt; action in &lt;code&gt;HomeController.cs&lt;/code&gt; we have been using to the following:&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="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Jonathan"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;View&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;And modify the view template &lt;code&gt;Bar.stache&lt;/code&gt; as follows:&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="n"&gt;Hello&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;your&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;has&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;Length&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="n"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you now run the application (&lt;code&gt;dotnet run&lt;/code&gt;) and navigate to &lt;code&gt;https://localhost:5001/home/bar&lt;/code&gt;, you should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Jonathan, your name has 8 characters.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have successfuly passed a value from the controller to the view template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this series, we created an alternative view engine with its own template syntax. We parsed the template, created a compilation, and used it to render values supplied by the controller. Hopefully this illustrated the modular nature of ASP.NET and its ability to accept third party view engines.&lt;/p&gt;

&lt;p&gt;If you're interested in other alternatives, &lt;a href="https://stackoverflow.com/questions/1451319/asp-net-mvc-view-engine-comparison"&gt;this Stack Overflow answer&lt;/a&gt; compares various view engines. Also check out &lt;a href="https://github.com/elfalem/NVue"&gt;NVue&lt;/a&gt;, my experimental attempt at a view engine based on the Vue.js template syntax.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Alternative view engine for ASP.NET Core: Compiling templates</title>
      <dc:creator>elfalem</dc:creator>
      <pubDate>Mon, 18 May 2020 15:53:59 +0000</pubDate>
      <link>https://forem.com/dealeron/alternative-view-engine-for-asp-net-core-compiling-templates-2m2f</link>
      <guid>https://forem.com/dealeron/alternative-view-engine-for-asp-net-core-compiling-templates-2m2f</guid>
      <description>&lt;p&gt;The &lt;a href="https://dev.to/dealeron/alternative-view-engine-for-asp-net-core-parsing-template-syntax-2k1b"&gt;last post&lt;/a&gt; in this series looked at parsing the template syntax. It also promised the next post will cover supporting inline C# expressions. And that's exactly what we'll do. Be sure to check out the previous posts in the series so that it's easier to follow this one.&lt;/p&gt;

&lt;p&gt;In the Razor view engine, you can use the &lt;code&gt;@&lt;/code&gt; symbol to transition from markup into writing plain C#. We're going to do something similar where we treat what's inside mustache tags as C# code. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Your&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;:&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="m"&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;should output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Your&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We'll work with a simple arithmetic expression in this post but we'll still explore the core mechanism through which view engines work. You can find the full contents of the source files discussed below on &lt;a href="https://gist.github.com/elfalem/2d2c173a9d83d912046766f19bedcc01"&gt;this GitHub gist&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  General Approach
&lt;/h2&gt;

&lt;p&gt;At the end of the day, the .NET runtime expects to run code in one of the languages that it supports. So we have to find a way to get from our template syntax to C# code that can be executed. The general approach that's used in such cases is to dynamically construct a C# class from the view template. Once we have a C# representation of the template, we can use APIs in &lt;code&gt;Microsoft.CodeAnalysis&lt;/code&gt; and &lt;code&gt;System.Reflection&lt;/code&gt; namespaces to dynamically compile, load, and run it. If you look at the source code for the Razor view engine, it's essentially using this same approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  View Template to C# Class
&lt;/h2&gt;

&lt;p&gt;As shown in the last post, we can parse the view template to generate a &lt;code&gt;DocumentNode&lt;/code&gt;. We can use the structured information in &lt;code&gt;DocumentNode&lt;/code&gt; to create a C# class. &lt;br&gt;
For example, given the parsed template of &lt;code&gt;Your Message: {{1 + 1}}&lt;/code&gt; the following class can be generated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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.Text&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;StacheTemplateNamespace&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;Bar&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;StringBuilder&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;new&lt;/span&gt; &lt;span class="nf"&gt;StringBuilder&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="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&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;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Your Message: "&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;Append&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="m"&gt;1&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;_output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&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;Note that we give the class the same name as the view template. It also has a method named &lt;code&gt;Execute()&lt;/code&gt; that computes the contents of the template and outputs a string.&lt;/p&gt;

&lt;p&gt;Create a new class &lt;code&gt;Stache/StacheTemplateCompiler.cs&lt;/code&gt; and add the following method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;CreateClassDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DocumentNode&lt;/span&gt; &lt;span class="n"&gt;parsedResult&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;templateClassName&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;StringBuilder&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;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$@"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s"&gt;using System.Text;&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s"&gt;namespace StacheTemplateNamespace&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="err"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;templateClassName&lt;/span&gt;&lt;span class="p"&gt;}&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;StringBuilder&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;new&lt;/span&gt; &lt;span class="nf"&gt;StringBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="s"&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;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;@"
        public string Execute()
        {
            "&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;node&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parsedResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;TextNode&lt;/span&gt; &lt;span class="n"&gt;textNode&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;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"_output.Append(\""&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;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;textNode&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendLine&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;ExpressionNode&lt;/span&gt; &lt;span class="n"&gt;expNode&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;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"_output.Append("&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;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expNode&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendLine&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="k"&gt;break&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="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AppendLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;@"
            return _output.ToString();
        }
    }
}
            "&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="nf"&gt;ToString&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;Since &lt;code&gt;DocumentNode&lt;/code&gt; contains information about whether a parsed node is a &lt;code&gt;TextNode&lt;/code&gt; or &lt;code&gt;ExpressionNode&lt;/code&gt;, &lt;code&gt;CreateClassDocument()&lt;/code&gt; can render the node value as a string or expression accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an Assembly
&lt;/h2&gt;

&lt;p&gt;After creating the C# class in string form, it has to be compiled before it can be executed by the .NET runtime. This compiled code is referred to as an assembly. In &lt;code&gt;StacheTemplateCompiler.cs&lt;/code&gt;, add the following method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Assembly&lt;/span&gt; &lt;span class="nf"&gt;Compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DocumentNode&lt;/span&gt; &lt;span class="n"&gt;parsedResult&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;templateClassName&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;classDocument&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateClassDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsedResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;templateClassName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// to be continued...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;Compile()&lt;/code&gt; method first makes use of the method we defined earlier to generate the class document as a string. Next we take that string and parse it using &lt;code&gt;Microsoft.CodeAnalysis&lt;/code&gt; to generate a syntax tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;syntaxTree&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CSharpSyntaxTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ParseText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classDocument&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that this is analogous to the tokenization and parsing that we performed in the last post. But this time with C# code using Microsoft tooling.&lt;/p&gt;

&lt;p&gt;The next step is to compile the parsed syntax to machine code (IL code). This is achieved by what Microsoft calls a compilation. A compilation represents everything needed to compile some code. It includes a name for the assembly, references to other assemblies, and of course the code we want to compile. Add the following method to &lt;code&gt;StacheTemplateCompiler.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;CSharpCompilation&lt;/span&gt; &lt;span class="nf"&gt;CreateCompilation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SyntaxTree&lt;/span&gt; &lt;span class="n"&gt;syntaxTree&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;systemRuntimeAssemblyLocation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&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;references&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="n"&gt;MetadataReference&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;{&lt;/span&gt;
      &lt;span class="n"&gt;MetadataReference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateFromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;systemRuntimeAssemblyLocation&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;compilationOptions&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;CSharpCompilationOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;OutputKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DynamicallyLinkedLibrary&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;assemblyName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetRandomFileName&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;compilation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CSharpCompilation&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="n"&gt;assemblyName&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;compilationOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;references&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;references&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;compilation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSyntaxTrees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syntaxTree&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;compilation&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;This method prepares the compilation. You can see that we're making a reference to the assembly containing the &lt;code&gt;System.Object&lt;/code&gt; class (&lt;code&gt;System.Runtime.dll&lt;/code&gt;). We want the output to be a DLL (as opposed to EXE). We also picked a random file path for the assembly name since it's not that important for our case. Finally, we add our parsed C# class. We can then invoke this method in &lt;code&gt;Compile()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;compilation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateCompilation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syntaxTree&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We now have all the ingredients that we need to compile the class and create an assembly. We do that in the following method (also in &lt;code&gt;StacheTemplateCompiler.cs&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Assembly&lt;/span&gt; &lt;span class="nf"&gt;LoadAssembly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CSharpCompilation&lt;/span&gt; &lt;span class="n"&gt;compilation&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;using&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;assemblyStream&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;MemoryStream&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;compilation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assemblyStream&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="k"&gt;if&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="n"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&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="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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Diagnostics&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;d&lt;/span&gt; &lt;span class="p"&gt;=&amp;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;d&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="s"&gt;-&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetMessage&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s"&gt;\n"&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="n"&gt;assemblyStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Seek&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;SeekOrigin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Begin&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;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assemblyStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToArray&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This method actually compiles the class and emits the IL code. The result is written to computer memory and loaded to the same domain as our running application. We now have a dynamically created class we can instantiate and whose  methods we can invoke! Overall the &lt;code&gt;Compile()&lt;/code&gt; method looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Assembly&lt;/span&gt; &lt;span class="nf"&gt;Compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DocumentNode&lt;/span&gt; &lt;span class="n"&gt;parsedResult&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;templateClassName&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;classDocument&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateClassDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsedResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;templateClassName&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;syntaxTree&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CSharpSyntaxTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ParseText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classDocument&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;compilation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateCompilation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syntaxTree&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;assembly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;LoadAssembly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;compilation&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;assembly&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;
  
  
  Using the Assembly
&lt;/h2&gt;

&lt;p&gt;We need to make some modifications to the code discussed in the previous posts to use the assembly. For the &lt;code&gt;templateClassName&lt;/code&gt; parameter in &lt;code&gt;StacheTemplateCompiler.Compile()&lt;/code&gt;, we will use the view name. This requires changing &lt;code&gt;StachViewEngine.cs&lt;/code&gt; slightly to include the view name when constructing the &lt;code&gt;StacheView&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// in StachViewEngine.FindView() method&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ViewEngineResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewName&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;StacheView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;possibleViewLocation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewName&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// in StachViewEngine.GetView() method&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;viewNameWithExtension&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;viewPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LastIndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'/'&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;viewName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;viewNameWithExtension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&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;viewNameWithExtension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ViewExtension&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;ViewEngineResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewPath&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;StacheView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appRelativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewName&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We also modify &lt;code&gt;StacheView.cs&lt;/code&gt; to accept the template name in the constructor and store it as an instance variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;StacheView&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;path&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;templateName&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="n"&gt;Path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;TemplateName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;templateName&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;string&lt;/span&gt; &lt;span class="n"&gt;TemplateName&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next we replace the logic in &lt;code&gt;StacheView.RenderAsync()&lt;/code&gt; that looped through the document node with a call to &lt;code&gt;StacheTemplateCompiler.Compile()&lt;/code&gt; we created in this post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// in StacheView.RenderAsync()&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;assembly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StacheTemplateCompiler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TemplateName&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;instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"StacheTemplateNamespace.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;TemplateName&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;processedOutput&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;GetMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Execute"&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;instance&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processedOutput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above code compiles the document node and obtains an assembly. It then instantiates the C# class we dynamically generated and invokes the &lt;code&gt;Execute()&lt;/code&gt; method on it.&lt;/p&gt;

&lt;p&gt;To test our changes, update the contents of &lt;code&gt;Bar.stache&lt;/code&gt; to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Your Message: {{1 + 1}}&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then running the app (&lt;code&gt;dotnet run&lt;/code&gt;) and navigating to &lt;a href="https://localhost:5001/Home/Bar"&gt;https://localhost:5001/Home/Bar&lt;/a&gt; you should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Your&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Other simple expressions should work as well. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Your Message: {{"foobar".Length}}&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Your Message: {{5 == 4}}&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;As shown above, view engines depend on the ability to dynamically compile template syntax into code that can be executed by .NET. A lot of the Roslyn compiler's functionality is exposed as APIs (&lt;code&gt;Microsoft.CodeAnalysis&lt;/code&gt; namespace) which greatly facilitates the analysis of C# (and VB) code. Although it's great that we can show the results of simple expressions, view engines are immensely more useful if they can make use of variable values supplied by the controller. Stay tuned for the next post in which we examine how we can use the values added to the &lt;code&gt;ViewData&lt;/code&gt; in the compiled view template.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Alternative view engine for ASP.NET Core: Parsing template syntax</title>
      <dc:creator>elfalem</dc:creator>
      <pubDate>Sat, 05 Oct 2019 13:24:35 +0000</pubDate>
      <link>https://forem.com/dealeron/alternative-view-engine-for-asp-net-core-parsing-template-syntax-2k1b</link>
      <guid>https://forem.com/dealeron/alternative-view-engine-for-asp-net-core-parsing-template-syntax-2k1b</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/dealeron/creating-an-alternative-view-engine-for-asp-net-core-3kln"&gt;last post&lt;/a&gt;, we looked at how we can hook into the ASP.NET Core architecture to create a custom view engine. Although we had a working view engine, it was quite rudimentary. One of the limitations mentioned was that there is only one variable named &lt;code&gt;Message&lt;/code&gt; that we can bind to. In this post, we'll look at how we can use as many variables as we need for a given template. Be sure to check out the last post if you haven't done so already as it will make it easier to follow this one.&lt;/p&gt;




&lt;p&gt;As it currently stands, our view rendering logic is using direct text replacement to look for &lt;code&gt;{{Message}}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;processedOutput&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{{Message}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nf"&gt;ToString&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processedOutput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In order to build a more robust view engine, we will need to more intelligently analyze the template syntax by tokenizing and parsing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tokenization and Parsing
&lt;/h2&gt;

&lt;p&gt;Tokenization (or lexical analysis) is the process by which we identify tokens from the view template. Tokens are the specific components that are the building blocks of our view template syntax. Suppose that we're tokenizing the following arithmetic expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3 * -4 + 55
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The specific tokens would be: &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;55&lt;/code&gt;. We can also assign categories to tokens. In this case, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;4,&lt;/code&gt; and &lt;code&gt;55&lt;/code&gt; would be operands or numbers and &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt; and &lt;code&gt;+&lt;/code&gt; would be operators.&lt;/p&gt;

&lt;p&gt;After tokenization the next part of the process is parsing. Parsing takes the tokens and generates some sort of data structure (such as a parse tree or abstract syntax tree) that represents the syntactic structure. Parsing the above arithmetic expression would result a tree as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     +
    / \
   *  55
  / \
 3   -
     |
     4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Having a structure like the above tree allows us to see the relationship between tokens so that we can process it appropriately whether that is evaluating an arithmetic expression or rendering a view from a template.&lt;/p&gt;

&lt;p&gt;Looking at our mustache syntax template, we can tokenize and parse it in a similar fashion.&lt;/p&gt;

&lt;p&gt;Original template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Message: {{Message}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The tokens from that template are: &lt;code&gt;Your Message:&lt;/code&gt; (string), &lt;code&gt;{{&lt;/code&gt; (open braces), &lt;code&gt;Message&lt;/code&gt; (string), &lt;code&gt;}}&lt;/code&gt; (close braces).&lt;/p&gt;

&lt;p&gt;In terms of parsing, since our mustache syntax is not quite hierarchical, a tree structure is not ideal. Instead we can use a simple list structure with two types of elements: text (that we render directly) and expression (that we treat as a variable and replace with a value). Here it is represented as a table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----------------------------
|Type       | Value         |                
-----------------------------
|text       | Your Message: |
|expression |{{Message}}    |
-----------------------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementing a parser
&lt;/h2&gt;

&lt;p&gt;Now that we have some idea of how we can tokenize and parse our template syntax, we'll turn our attention to how we can actually implement it in code. Depending on the template syntax that you're using, it may be possible to use an existing parser. For example, if the syntax is similar to HTML, you can perhaps use &lt;a href="https://html-agility-pack.net/"&gt;Html Agility Pack&lt;/a&gt;. Alternatively, if it's mustache or &lt;a href="https://shopify.github.io/liquid/"&gt;Liquid&lt;/a&gt; syntax, you can use &lt;a href="https://github.com/sebastienros/fluid"&gt;fluid parser&lt;/a&gt;. If there is no existing parser for the syntax you are using, then you would have to create it. Although we can probably use the fluid parser for our case, we're going to build our own.&lt;/p&gt;

&lt;p&gt;Creating a parser could be a very complex process but there are tools and libraries to facilitate it. One such library is &lt;a href="https://github.com/datalust/superpower"&gt;Superpower&lt;/a&gt;, a parser construction toolkit. Superpower simplifies the process of creating tokenizers and parsers. The first step is to install the NuGet package into our app from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Superpower
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once installed, create a new file &lt;code&gt;Stache/StacheParser.cs&lt;/code&gt;. In addition to the &lt;code&gt;StacheParser&lt;/code&gt; class, I'm going to include other small classes in the same file. Feel free to create separate files for these if that makes better organizational sense to you. You can find the full contents in &lt;a href="https://gist.github.com/elfalem/b7befb7a91ddb5ba0f12d8a156b54179"&gt;this GitHub gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll first create an enum to represent our token categories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;enum&lt;/span&gt; &lt;span class="n"&gt;Tokens&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;OpenBraces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;CloseBraces&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we'll create a tokenizer in the &lt;code&gt;StacheParser&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;static&lt;/span&gt; &lt;span class="n"&gt;Tokenizer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Tokenizer&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;TokenizerBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EqualTo&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;Tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenBraces&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EqualTo&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;Tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CloseBraces&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MatchedBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExceptIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sc"&gt;'}'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;Many&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Basically we read the input and attempt to match a specific set of characters that map to a token. The &lt;code&gt;Match&lt;/code&gt; statements will be tried in order until a match is found. Note that the above tokenizer will run into issues if there are single braces present in the template (e.g. &lt;code&gt;{{foo{bar}}&lt;/code&gt;). We will not address this limitation in this post as it involves creating more advanced tokenizers as opposed to using the building blocks provided by Superpower.&lt;/p&gt;

&lt;p&gt;The next step is to create a parser. Let's create a class called &lt;code&gt;ParseNode&lt;/code&gt; to represent parsed elements. It will be an abstract class that's derived by three other classes: &lt;code&gt;TextNode&lt;/code&gt; for literal text, &lt;code&gt;ExpressionNode&lt;/code&gt; for a mustache expression that we'll need to replace, and &lt;code&gt;DocumentNode&lt;/code&gt; for a top level structure to hold a list of the other two nodes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ParseNode&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;class&lt;/span&gt; &lt;span class="nc"&gt;TextNode&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ParseNode&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;Value&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;set&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;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExpressionNode&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ParseNode&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;Value&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;set&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;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DocumentNode&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ParseNode&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&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;ParseNode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Nodes&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;set&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;Superpower is a parser combinator so it allows us to combine simpler parsers to create a more complex one. In our case we will create a simple parser for text literals in the &lt;code&gt;StacheParser&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;TokenListParser&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ParseNode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;LiteralParser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="k"&gt;in&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;EqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseNode&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;TextNode&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;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToStringValue&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;The above parser will consume tokens that are of type &lt;code&gt;String&lt;/code&gt; and returns a &lt;code&gt;TextNode&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will create another parser for mustache expressions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;TokenListParser&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ParseNode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ExpressionParser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ob&lt;/span&gt; &lt;span class="k"&gt;in&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;EqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenBraces&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="k"&gt;in&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;EqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cb&lt;/span&gt; &lt;span class="k"&gt;in&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;EqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CloseBraces&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseNode&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;ExpressionNode&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;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToStringValue&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;This parser will consume three tokens in order: an open brace followed by a string followed by a close brace. It will return an &lt;code&gt;ExpressionNode&lt;/code&gt; with the value of the &lt;code&gt;String&lt;/code&gt; token since that represents the variable we need to replace.&lt;/p&gt;

&lt;p&gt;Putting it all together, we have the combined parser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;readonly&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;TokenListParser&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ParseNode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;MainParser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;nodes&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ExpressionParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LiteralParser&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Many&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ParseNode&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;DocumentNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Nodes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nodes&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The combined parser looks for tokens to match either the expression parser or the literal parser. The &lt;code&gt;Many()&lt;/code&gt; tells it to match as many times as possible so that we consume all the tokens and process the entire template. It returns a &lt;code&gt;DocumentNode&lt;/code&gt; with a list of the nodes returned from the other two parsers. We now have our tokenizer and parser that we can use to render views!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using our parser
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;StachView.cs&lt;/code&gt;, we can replace the contents of &lt;code&gt;RenderAsync()&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;template&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Path&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;tokens&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StacheParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Tokenize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;template&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;parsedResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StacheParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&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;processedOutput&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;StringBuilder&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;parsedResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasValue&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;document&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DocumentNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;parsedResult&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="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;node&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nodes&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;TextNode&lt;/span&gt; &lt;span class="n"&gt;textNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;processedOutput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;textNode&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;ExpressionNode&lt;/span&gt; &lt;span class="n"&gt;expNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;processedOutput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;expNode&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="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;              
      &lt;span class="k"&gt;break&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="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&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="n"&gt;parsedResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrorMessage&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processedOutput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&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 above code, we run the template through the tokenizer. The resulting tokens are then parsed giving us a &lt;code&gt;DocumentNode&lt;/code&gt; structure. We then process each parsed node and directly write text nodes or find variable values in &lt;code&gt;ViewData&lt;/code&gt; for expression nodes.&lt;/p&gt;

&lt;p&gt;We are now able to use any variable in our view template and bind to it in our controller.&lt;/p&gt;

&lt;p&gt;For example, we can change our template to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;{{header}}&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{{content}}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;small&amp;gt;&lt;/span&gt;{{footer}}&lt;span class="nt"&gt;&amp;lt;/small&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and the &lt;code&gt;Bar&lt;/code&gt; action in &lt;code&gt;HomeController.cs&lt;/code&gt; to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello World!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Greetings from a mustache template."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"footer"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Powered by ASP.NET Core."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;View&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;Then running the app (&lt;code&gt;dotnet run&lt;/code&gt;) and navigating to &lt;a href="https://localhost:5001/Home/Bar"&gt;https://localhost:5001/Home/Bar&lt;/a&gt; you should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello World!

Greetings from a mustache template.
Powered by ASP.NET Core.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this post we explored the process of building a more flexible view engine that can tokenize and parse the template syntax. We now have gotten rid of one of the limitations mentioned in the first post. Using the Superpower library we can design a template syntax that suits our needs. Stay tuned for the next post in which we'll explore supporting inline CSharp expressions such as &lt;code&gt;{{1 + 1}}&lt;/code&gt;.&lt;/p&gt;
Cover photo by &lt;a href="https://unsplash.com/@pawelskor"&gt;
Paul Skorupskas&lt;/a&gt; via Unsplash



</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Alternative view engine for ASP.NET Core: Hooking into the ASP.NET Core architecture</title>
      <dc:creator>elfalem</dc:creator>
      <pubDate>Fri, 09 Aug 2019 16:40:15 +0000</pubDate>
      <link>https://forem.com/dealeron/creating-an-alternative-view-engine-for-asp-net-core-3kln</link>
      <guid>https://forem.com/dealeron/creating-an-alternative-view-engine-for-asp-net-core-3kln</guid>
      <description>&lt;p&gt;ASP.NET Core is a great open-source framework for building web apps. One of its advantages is its modular architecture, which makes it possible to replace many of the default components with alternative ones. In this post, we'll look at how we can create and use a new view engine with ASP.NET.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Razor View
&lt;/h2&gt;

&lt;p&gt;Let's first create an ASP.NET Core MVC app with a Razor view. You'll need the &lt;a href="https://dotnet.microsoft.com/download"&gt;.NET Core SDK&lt;/a&gt;. Using the terminal on your OS or in your favorite IDE, such as &lt;a href="https://code.visualstudio.com/"&gt;VS Code&lt;/a&gt; (a great, cross-platform IDE), create a project called Foo and initialize it with the default template for an MVC app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir foo
cd foo/
dotnet new mvc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can now run the app with &lt;code&gt;dotnet run&lt;/code&gt; and navigate to &lt;code&gt;https://localhost:5001/&lt;/code&gt; to access the home page displaying a welcome message.&lt;/p&gt;

&lt;p&gt;Now we'll add an action named Bar to the Home controller as well a corresponding Razor view.&lt;/p&gt;

&lt;p&gt;Edit &lt;code&gt;HomeController.cs&lt;/code&gt; to add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello World!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;View&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;Create &lt;code&gt;Views/Home/Bar.cshtml&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Message: @ViewData["Message"]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you stop and run the app again, you should see the text &lt;code&gt;Your Message: Hello World!&lt;/code&gt; when accessing &lt;code&gt;https://localhost:5001/Home/Bar&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  An alternative view engine
&lt;/h2&gt;

&lt;p&gt;As we saw above, the Razor view engine that comes with ASP.NET uses markup files with the extension &lt;code&gt;.cshtml&lt;/code&gt;. The Razor syntax uses the &lt;code&gt;@&lt;/code&gt; symbol to transition to C# and evaluate expressions. As an alternative, what if we use the mustache syntax for markup files? We can use braces to denote variables that will need to be treated as C# expressions. In our case, the above Bar view will look like this in the new template system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Message: {{Message}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We'll use a similar convention as Razor for locating views - i.e. &lt;code&gt;Views/[controller]/[action]&lt;/code&gt; and utilize the file extension &lt;code&gt;.stache&lt;/code&gt;. Let's see how we can implement the Stache View Engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a view engine
&lt;/h2&gt;

&lt;p&gt;A view engine needs to implement two interfaces: &lt;code&gt;IViewEngine&lt;/code&gt; and &lt;code&gt;IView&lt;/code&gt; from the namespace &lt;code&gt;Microsoft.AspNetCore.Mvc.ViewEngines&lt;/code&gt;. In our project, create a top level directory named &lt;code&gt;Stache&lt;/code&gt; containing the files &lt;code&gt;StacheViewEngine.cs&lt;/code&gt; and &lt;code&gt;StacheView.cs&lt;/code&gt;. We'll walk through the key parts of these two interfaces below. You can find the full contents of the two files on &lt;a href="https://gist.github.com/elfalem/10ee2705fc322baf311accb471432373"&gt;this GitHub gist&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  IViewEngine
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.viewengines.iviewengine?view=aspnetcore-2.2"&gt;IViewEngine&lt;/a&gt; requires implementing two methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ViewEngineResult&lt;/span&gt; &lt;span class="nf"&gt;GetView&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;executingFilePath&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;viewPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isMainPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ViewEngineResult&lt;/span&gt; &lt;span class="nf"&gt;FindView&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ActionContext&lt;/span&gt; &lt;span class="n"&gt;context&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;viewName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isMainPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Both methods return a &lt;code&gt;ViewEngineResult&lt;/code&gt; which encapsulates &lt;code&gt;ViewEngineResult.Found&lt;/code&gt;, indicating an instance of the view was found, and &lt;code&gt;ViewEngineResult.NotFound&lt;/code&gt;, indicating that the view was not found and containing the list of locations searched.&lt;/p&gt;

&lt;p&gt;It's helpful to discuss how a view can be referenced when it's returned from a controller to understand the roles these two methods play in the process of rendering a view. In our Bar controller, we just write &lt;code&gt;return View();&lt;/code&gt; which references the view with the same name as the action (i.e. &lt;code&gt;Bar&lt;/code&gt;). We could have also directly named the view: &lt;code&gt;return View("Bar");&lt;/code&gt;. Alternatively it's possible to explicitly provide the full path to a view file: &lt;code&gt;return View("~/Views/Home/Bar.stache");&lt;/code&gt;. In all cases, the framework first invokes the &lt;code&gt;GetView()&lt;/code&gt; method. If a view is not found, it will then invoke &lt;code&gt;FindView()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In cases where the view path is explicitly given, we expect &lt;code&gt;GetView()&lt;/code&gt; to return an instance of that view. In cases where we only have the view name, we fallback to &lt;code&gt;FindView()&lt;/code&gt; to search various paths that we've defined by convention to be possible locations where a view could exist.&lt;/p&gt;

&lt;p&gt;In our implementation of &lt;code&gt;GetView()&lt;/code&gt;, we first check if &lt;code&gt;viewPath&lt;/code&gt; is an actual file path or just the name of the action. We'll get the latter if the view is referenced by name only. In that case, we'll return &lt;code&gt;ViewEngineResult.NotFound&lt;/code&gt; so the call can proceed to &lt;code&gt;FindView()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If it's a file path, we'll pass it to a private method &lt;code&gt;GetAbsolutePath()&lt;/code&gt; to ensure it's well formatted. &lt;code&gt;executingFilePath&lt;/code&gt; will only have a value if there is another view that's currently executing (e.g. the parent view when processing a Razor partial view). If it has a value, it will get combined with the view path to generate a path relative to the parent executing view. Once we have the path, we check if a template exists at that path and return appropriately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ViewEngineResult&lt;/span&gt; &lt;span class="nf"&gt;GetView&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;executingFilePath&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;viewPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isMainPage&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="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;viewPath&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="n"&gt;viewPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EndsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ViewExtension&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StringComparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrdinalIgnoreCase&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;ViewEngineResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Enumerable&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;&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;appRelativePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetAbsolutePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executingFilePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewPath&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;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appRelativePath&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;ViewEngineResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewPath&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;StacheView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;appRelativePath&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;ViewEngineResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewPath&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="n"&gt;appRelativePath&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;For our implementation of &lt;code&gt;FindView()&lt;/code&gt;, we're provided the view name as well as the action context from which we can get the controller name. Based on our convention for locating views, we'll plug in those two values into each of the &lt;code&gt;_viewLocationFormats&lt;/code&gt; (e.g. &lt;code&gt;Views/[controller]/[action].stache&lt;/code&gt;) and check for a template file until one is found. If none are found, we return &lt;code&gt;ViewEngineResult.NotFound&lt;/code&gt; with all the paths we checked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ViewEngineResult&lt;/span&gt; &lt;span class="nf"&gt;FindView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ActionContext&lt;/span&gt; &lt;span class="n"&gt;context&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;viewName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isMainPage&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ActionDescriptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RouteValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"controller"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;controllerName&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;checkedLocations&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="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;locationFormat&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_viewLocationFormats&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;possibleViewLocation&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;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;locationFormat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;controllerName&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;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;possibleViewLocation&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;ViewEngineResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Found&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewName&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;StacheView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;possibleViewLocation&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;checkedLocations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;possibleViewLocation&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;ViewEngineResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotFound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checkedLocations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;throw&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;"Controller route value not found."&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;h3&gt;
  
  
  IView
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.viewengines.iview?view=aspnetcore-2.2"&gt;IView&lt;/a&gt; requires implementing the &lt;code&gt;Path&lt;/code&gt; property and the &lt;code&gt;RenderAsync()&lt;/code&gt; method. &lt;code&gt;Path&lt;/code&gt; is the location of the view template. We populate the &lt;code&gt;Path&lt;/code&gt; property when instantiating the view in &lt;code&gt;GetView()&lt;/code&gt; or &lt;code&gt;FindView()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;RenderAsync&lt;/code&gt; method is responsible for rendering the view given a &lt;code&gt;ViewContext&lt;/code&gt; and is where the magic happens. In this grossly oversimplified example, we just look for the string &lt;code&gt;{{Message}}&lt;/code&gt; in the template and replace it with the value provided in the &lt;code&gt;ViewData&lt;/code&gt;. In a more fleshed out version, this is where your custom syntax parser would do it's work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;RenderAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ViewContext&lt;/span&gt; &lt;span class="n"&gt;context&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;template&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Path&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;processedOutput&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{{Message}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ViewData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Message"&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nf"&gt;ToString&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processedOutput&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;
  
  
  Using the alternative view engine
&lt;/h2&gt;

&lt;p&gt;Let's create an alternative Bar view using the new Stache template syntax. Create the file &lt;code&gt;Views/Home/Bar.stache&lt;/code&gt; with the contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Message: {{Message}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The last step is to tell MVC to use the new view engine. In &lt;code&gt;Startup.cs&lt;/code&gt; modify the MVC configuration to be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddMvc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCompatibilityVersion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CompatibilityVersion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version_2_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddViewOptions&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;=&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;ViewEngines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Insert&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;new&lt;/span&gt; &lt;span class="nf"&gt;StacheViewEngine&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;Note that we're adding the Stache view engine as the first item in the list. This will ensure that the Stache template is used if both &lt;code&gt;.cshtml&lt;/code&gt; and &lt;code&gt;.stache&lt;/code&gt; markup files are found for a given view. If you'd like to default to Razor views instead, you can add Stache to the end of the list: &lt;code&gt;options.ViewEngines.Add(new StacheViewEngine());&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you run the app and navigate to the Bar action &lt;code&gt;https://localhost:5001/Home/Bar&lt;/code&gt;, you should now see the view rendered with Stache!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In the above example, we saw that it's relatively simple to plug in an alternative view engine in place of Razor. It illustrates the possibility of using a variety of markup templates, even simultaneously, with ASP.NET.&lt;/p&gt;

&lt;p&gt;Although we have the foundation on which can build upon, this rudimentary example is quite limited:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is only one variable named &lt;code&gt;Message&lt;/code&gt; that we can bind to. We should be able to use as many variables as needed for a given template.&lt;/li&gt;
&lt;li&gt;We need support for more advanced expressions instead of just variables (e.g. inline expressions such as &lt;code&gt;{{1 + 1}}&lt;/code&gt;), loops to iterate through lists, and if-else conditions for control flow.&lt;/li&gt;
&lt;li&gt;We're missing some of the more advanced concepts of Razor such as layouts, partials and tag helpers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It will be interesting to explore some of these missing features and develop our alternative view engine to implement them. Perhaps we'll do that in future posts.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks to &lt;a href="https://dev.to/sohjsolwin"&gt;@sohjsolwin&lt;/a&gt; for providing feedback on this post. &lt;br&gt;
Also a special shout-out to the blog entry &lt;a href="https://www.davepaquette.com/archive/2016/11/22/creating-a-new-view-engine-in-asp-net-core.aspx"&gt;"Creating a New View Engine in ASP.NET Core"&lt;/a&gt; by Dave Paquette for putting together some of the key puzzle pieces. &lt;br&gt;
Cover photo by &lt;a href="https://unsplash.com/@eryk10"&gt;Eryk&lt;/a&gt; via &lt;a href="https://unsplash.com/"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
