<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Xceno.io]]></title><description><![CDATA[Adventures in software and how to survive them.]]></description><link>https://www.xceno.io</link><generator>RSS for Node</generator><lastBuildDate>Tue, 03 Dec 2024 21:58:37 GMT</lastBuildDate><language><![CDATA[en]]></language><item><title><![CDATA[Unable to resolve symbol ZWNBSP in this context]]></title><description><![CDATA[So, you got a mysterious compile error and if you're lucky, your compiler will
at least show you  instead of just a space.Chances are your…]]></description><link>https://www.xceno.io/posts/2023-11-20-unable-to-resolve-symbol-zwnbsp/</link><guid isPermaLink="false">https://www.xceno.io/posts/2023-11-20-unable-to-resolve-symbol-zwnbsp/</guid><category><![CDATA[File Encodings]]></category><category><![CDATA[Compile Errors]]></category><pubDate>Mon, 20 Nov 2023 13:57:01 GMT</pubDate><content:encoded>&lt;p&gt;So, you got a mysterious compile error and if you&apos;re lucky, your compiler will
at least show you &lt;code class=&quot;language-text&quot;&gt;ZWNBSP&lt;/code&gt; instead of just a space.&lt;/p&gt;
&lt;p&gt;Chances are your file got encoded in &lt;code class=&quot;language-text&quot;&gt;UTF-8 BOM&lt;/code&gt; instead of just &lt;code class=&quot;language-text&quot;&gt;UTF-8&lt;/code&gt;, and your compiler
is choking on the &lt;a href=&quot;https://en.wikipedia.org/wiki/Byte_order_mark&quot;&gt;Byte order mark&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To fix it, convert the file to &lt;code class=&quot;language-text&quot;&gt;UTF-8&lt;/code&gt; &lt;strong&gt;without BOM&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This has happened to me several times over my career in various languages and has cost me hours of senseless debugging.
Maybe you&apos;re lucky enough to find this post quickly when it happened to you.&lt;/p&gt;
&lt;p&gt;As an example, here&apos;s an error message from the Clojure compiler:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;clojure&quot;&gt;&lt;pre class=&quot;language-clojure&quot;&gt;&lt;code class=&quot;language-clojure&quot;&gt;Syntax error compiling at &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;somefile.clj:&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;:&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
Unable to &lt;span class=&quot;token keyword&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;symbol&lt;/span&gt;: ZWNBSP in this context&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Convert to UTF-8 without BOM&lt;/h2&gt;
&lt;h3&gt;VIM&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;:set fileencoding=utf8&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;:set nobomb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save the file.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;IntelliJ&lt;/h3&gt;
&lt;p&gt;You should see your current encoding in the lower right status line.
Click on it and choose &lt;code class=&quot;language-text&quot;&gt;Remove BOM&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Configure IntelliJ to prevent this&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Open &lt;code class=&quot;language-text&quot;&gt;Settings -&amp;gt; Editor -&amp;gt; File Encodings&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set &lt;code class=&quot;language-text&quot;&gt;Create UTF-8 files&lt;/code&gt; to &lt;strong&gt;wih NO BOM&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h6&gt;References&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/2223882/whats-the-difference-between-utf-8-and-utf-8-with-bom&quot;&gt;https://stackoverflow.com/questions/2223882/whats-the-difference-between-utf-8-and-utf-8-with-bom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Byte_order_mark&quot;&gt;https://en.wikipedia.org/wiki/Byte&lt;em&gt;order&lt;/em&gt;mark&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/help/idea/encoding.html#file-encoding-settings&quot;&gt;https://www.jetbrains.com/help/idea/encoding.html#file-encoding-settings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vimdoc.sourceforge.net/htmldoc/options.html#%27bomb%27&quot;&gt;https://vimdoc.sourceforge.net/htmldoc/options.html#%27bomb%27&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Configure zig fmt in a JetBrains IDE]]></title><description><![CDATA[How to use  with any JetBrains IDE in 2023.TL;DRAdd a new custom file watcher in your IDE settings and configure it to run .Detailed…]]></description><link>https://www.xceno.io/posts/2023-10-28-configure-zig-fmt-for-jetbrains-ide/</link><guid isPermaLink="false">https://www.xceno.io/posts/2023-10-28-configure-zig-fmt-for-jetbrains-ide/</guid><category><![CDATA[Zig]]></category><category><![CDATA[Jetbrains]]></category><category><![CDATA[Rider]]></category><category><![CDATA[IntelliJ]]></category><category><![CDATA[CLion]]></category><pubDate>Sat, 28 Oct 2023 16:05:11 GMT</pubDate><content:encoded>&lt;p&gt;How to use &lt;code class=&quot;language-text&quot;&gt;zig fmt&lt;/code&gt; with any JetBrains IDE in 2023.&lt;/p&gt;
&lt;div class=&quot;fold&quot;&gt;&lt;/div&gt;
&lt;br/&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Add a new custom file watcher in your IDE settings and configure it to run &lt;code class=&quot;language-text&quot;&gt;zig fmt&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Detailed version&lt;/h2&gt;
&lt;p&gt;As of today, &lt;a href=&quot;https://ziglang.org/&quot;&gt;Zig&lt;/a&gt; is at version &lt;code class=&quot;language-text&quot;&gt;0.11.0&lt;/code&gt; and has &lt;em&gt;some&lt;/em&gt; support for various
editors via its language server &lt;a href=&quot;https://github.com/zigtools/zls&quot;&gt;zls&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;m personally using the &lt;a href=&quot;https://plugins.jetbrains.com/plugin/22456-zigbrains&quot;&gt;ZigBrains&lt;/a&gt; extension for &lt;em&gt;JetBrains Rider&lt;/em&gt; right now (also works in CLion, IntelliJ, etc.),
which seems to only support formatting for &lt;code class=&quot;language-text&quot;&gt;.zon&lt;/code&gt; but not &lt;code class=&quot;language-text&quot;&gt;.zig&lt;/code&gt; files &lt;a href=&quot;https://github.com/FalsePattern/ZigBrains/tree/0.8.1?tab=readme-ov-file#zon-files&quot;&gt;as of version 0.8.1&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However it may be, you can add file watchers to run &lt;code class=&quot;language-text&quot;&gt;zig fmt&lt;/code&gt; anyway.&lt;/p&gt;
&lt;p&gt;Here&apos;s how:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open Settings -&gt; Tools -&gt; File Watchers&lt;/li&gt;
&lt;li&gt;Add a new &lt;code class=&quot;language-text&quot;&gt;&amp;lt;custom&amp;gt;&lt;/code&gt; watcher.&lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;File Type&lt;/strong&gt; to &lt;code class=&quot;language-text&quot;&gt;ZigLang file&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Scope&lt;/strong&gt; to &lt;code class=&quot;language-text&quot;&gt;Current file&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Program&lt;/strong&gt; to &lt;code class=&quot;language-text&quot;&gt;zig&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Arguments&lt;/strong&gt; to &lt;code class=&quot;language-text&quot;&gt;fmt $FileName$&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Working directory&lt;/strong&gt; to &lt;code class=&quot;language-text&quot;&gt;$FileDir$&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;(optional) Disable &lt;code class=&quot;language-text&quot;&gt;auto-save ...&lt;/code&gt; in the &lt;strong&gt;Advanced Options&lt;/strong&gt; tab.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will run &lt;code class=&quot;language-text&quot;&gt;zig fmt&lt;/code&gt; whenever you save a file.&lt;/p&gt;
&lt;p&gt;Happy hacking!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Install lombok to Eclipse snap]]></title><description><![CDATA[A short tutorial on how to install lombok for a snap install of the Eclipse IDE.TL;DRDownload lombokExtract to whereverCustomize a  file to…]]></description><link>https://www.xceno.io/posts/2019-05-15-install-lombok-to-eclipse-snap/</link><guid isPermaLink="false">https://www.xceno.io/posts/2019-05-15-install-lombok-to-eclipse-snap/</guid><category><![CDATA[Eclipse]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Snap]]></category><category><![CDATA[Lombok]]></category><category><![CDATA[Java]]></category><pubDate>Tue, 14 May 2019 15:04:41 GMT</pubDate><content:encoded>&lt;p&gt;A short tutorial on how to install lombok for a snap install of the Eclipse IDE.&lt;/p&gt;
&lt;div class=&quot;fold&quot;&gt;&lt;/div&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Download lombok&lt;/li&gt;
&lt;li&gt;Extract to wherever&lt;/li&gt;
&lt;li&gt;Customize a &lt;code class=&quot;language-text&quot;&gt;.desktop&lt;/code&gt; file to let eclipse start with lombok or a customized &lt;code class=&quot;language-text&quot;&gt;eclipse.ini&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Detailed version&lt;/h2&gt;
&lt;p&gt;First &lt;a href=&quot;https://projectlombok.org/download&quot;&gt;download lombok&lt;/a&gt; and extract it to wherver you see fit. I chose &lt;code class=&quot;language-text&quot;&gt;~/bin/lombok.jar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you try to run the installer it won&apos;t find your eclipse installation and pointing it to your snap install also won&apos;t work.
But have a look at *Show me what this installer will do to my IDE installation.&quot;
You should see the following message:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;1. First, I copy myself (lombok.jar) to your Eclipse install directory.
2. Then, I edit the eclipse.ini file to add the following entry:
   -javaagent:lombok.jar&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So this is what we&apos;ll end up doing (sort of).
Since snaps are immutable we cannot copy &lt;code class=&quot;language-text&quot;&gt;lombok.jar&lt;/code&gt; to the installation directory. That&apos;s why we&apos;ve chosen another dir.
Now all that&apos;s left to do is pointing eclipse to it.&lt;/p&gt;
&lt;p&gt;To do this, create or copy an &lt;code class=&quot;language-text&quot;&gt;eclipse.ini&lt;/code&gt; file to your preferred location and add the following line to the bottom:&lt;br&gt;
&lt;code class=&quot;language-text&quot;&gt;-javaagent:/PATH/TO/YOUR/LOMBOK.jar&lt;/code&gt;.
You can copy the original one from &lt;code class=&quot;language-text&quot;&gt;/snap/eclipse/current/eclipse.ini&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now create a &lt;a href=&quot;https://wiki.archlinux.org/index.php/Desktop_entries&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;.desktop&lt;/code&gt;&lt;/a&gt; file like &lt;code class=&quot;language-text&quot;&gt;~/.local/share/applications/eclipse_eclipse.desktop&lt;/code&gt; with the following content:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[Desktop Entry]
X-SnapInstanceName=eclipse
Version=1.0
Type=Application
Name=Eclipse+Lombok
Icon=/snap/eclipse/40/icon.xpm
Exec=env BAMF_DESKTOP_FILE_HINT=/var/lib/snapd/desktop/applications/eclipse_eclipse.desktop /snap/bin/eclipse --launcher.ini /PATH/TO/YOUR/ECLIPSE.INI %U
Comment=Eclipse IDE
Categories=Development;IDE;
Terminal=false
StartupWMClass=eclipse&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With this in place you&apos;ll find an &lt;code class=&quot;language-text&quot;&gt;Eclipse+Lombok&lt;/code&gt; entry in your applications menu. Happy coding!&lt;/p&gt;
&lt;h6&gt;References&lt;/h6&gt;
&lt;small&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rzwitserloot/lombok/issues/1700&quot;&gt;https://github.com/rzwitserloot/lombok/issues/1700&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://askubuntu.com/questions/1051926/how-to-make-eclipse-installed-via-snap-use-a-differerent-configuration-when-star/1051927#1051927&quot;&gt;https://askubuntu.com/questions/1051926/how-to-make-eclipse-installed-via-snap-use-a-differerent-configuration-when-star/1051927#1051927&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/small&gt;</content:encoded></item><item><title><![CDATA[Developing with UnrealEngine 4 on Linux]]></title><description><![CDATA[EpicGames has a neat little QuickStart Guide for getting UnrealEngine up and running on Linux, but you might still run into some gotchas…]]></description><link>https://www.xceno.io/posts/2019-04-25-unreal-engine-on-linux/</link><guid isPermaLink="false">https://www.xceno.io/posts/2019-04-25-unreal-engine-on-linux/</guid><category><![CDATA[Linux]]></category><category><![CDATA[Pop!_OS]]></category><category><![CDATA[UnrealEngine]]></category><category><![CDATA[HowTo]]></category><pubDate>Thu, 25 Apr 2019 23:55:29 GMT</pubDate><content:encoded>&lt;p&gt;EpicGames has a neat little QuickStart Guide for getting UnrealEngine up and running on Linux, but you might still run into some gotchas.
Unfortunately, the new Docs aren&apos;t accepting PRs (yet?), so here&apos;s a quick braindump of what I&apos;ve run into.&lt;/p&gt;
&lt;div class=&quot;fold&quot;&gt;&lt;/div&gt;
&lt;h1&gt;Getting started&lt;/h1&gt;
&lt;p&gt;I was following the guide mentioned above on a fresh install of &lt;a href=&quot;https://system76.com/pop&quot;&gt;Pop!_OS 19.04&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;By all means, read the official &lt;a href=&quot;https://docs.unrealengine.com/en-us/Platforms/Linux/BeginnerLinuxDeveloper/SettingUpAnUnrealWorkflow&quot;&gt;Linux Quick Start&lt;/a&gt; first. After you&apos;re done, continue here.&lt;/p&gt;
&lt;p&gt;If you&apos;re lucky and use UE &gt;= 4.20 check out the &lt;a href=&quot;https://docs.unrealengine.com/en-us/Platforms/Linux/NativeToolchain&quot;&gt;Native Toolchain&lt;/a&gt; provided by Epic Games.&lt;/p&gt;
&lt;h1&gt;Various problems I ran into&lt;/h1&gt;
&lt;h2&gt;Problem 1: UE can&apos;t be built with clang-8&lt;/h2&gt;
&lt;p&gt;While running &lt;code class=&quot;language-text&quot;&gt;make&lt;/code&gt; i noticed that pop comes installed with &lt;code class=&quot;language-text&quot;&gt;clang-8&lt;/code&gt; which is currently unsupported by UE.
You can easily solve this by installing &lt;code class=&quot;language-text&quot;&gt;clang-7&lt;/code&gt; and setting it up as an alternative like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; update-alternatives
  --install /usr/bin/clang clang /usr/bin/clang-7 &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
  --slave /usr/bin/clang++ clang++ /usr/bin/clang++-7

&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; update-alternatives
  --install /usr/bin/clang clang /usr/bin/clang-8 &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;
  --slave /usr/bin/clang++ clang++ /usr/bin/clang++-8&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This results in &lt;code class=&quot;language-text&quot;&gt;clang++&lt;/code&gt; following the version of &lt;code class=&quot;language-text&quot;&gt;clang&lt;/code&gt; so you can easily switch between your installs by running
&lt;code class=&quot;language-text&quot;&gt;sudo update-alternatives --config clang&lt;/code&gt;, which in my case looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;There are 2 choices for the alternative clang (providing /usr/bin/clang).

  Selection    Path              Priority   Status
------------------------------------------------------------
* 0            /usr/bin/clang-7   100       auto mode
  1            /usr/bin/clang-7   100       manual mode
  2            /usr/bin/clang-8   100       manual mode&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I do this for a lot of tools and SDKs and it works beautifully.
If you find yourself changing alternatives often, register yourself an alias in &lt;code class=&quot;language-text&quot;&gt;.bashrc&lt;/code&gt; like so: &lt;code class=&quot;language-text&quot;&gt;alias change-clang=&amp;quot;sudo update-alternatives --config clang&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Problem 2: Fresh install of QTCreator 5 + QT5&lt;/h2&gt;
&lt;p&gt;The quick start guide jumps from compiling the engine straight into the project setup inside QTCreator. However, only installing QTCreator via apt is not enough - Run the official QT5 setup instead, which comes with all necessary dependencies (qt 5.12.3 at the time of writing).&lt;/p&gt;
&lt;h2&gt;Problem 3: clang error: invalid linker name in argument &apos;-fuse-ld=lld&apos;&lt;/h2&gt;
&lt;p&gt;You&apos;re missing &lt;a href=&quot;https://lld.llvm.org/&quot;&gt;LLD&lt;/a&gt; on your system.
Either run &lt;code class=&quot;language-text&quot;&gt;SetupToolchain.sh&lt;/code&gt; in the engines root folder or install &lt;code class=&quot;language-text&quot;&gt;lld&lt;/code&gt; via your package manager.&lt;/p&gt;
&lt;h1&gt;Wrapping up&lt;/h1&gt;
&lt;p&gt;That&apos;s basically it.
If you&apos;re lucky you won&apos;t even need to read this post!&lt;/p&gt;
&lt;p&gt;All in all, it was surprisingly easy considering that Linux isn&apos;t exactly a first class citizen for game development &lt;a href=&quot;https://youtu.be/Nuqlf0KCSdY&quot;&gt;yet&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What comes next is setting up a CI environment, but I&apos;ll save that for another post.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Orchard CMS: Strongly typed WebApi routing]]></title><description><![CDATA[If you're developing WebApi projects in Orchard, you're probably used to declare your API routes as a simple string array. However, we can…]]></description><link>https://www.xceno.io/posts/2017-11-04-orchard-cms-strongly-typed-webapi-routing/</link><guid isPermaLink="false">https://www.xceno.io/posts/2017-11-04-orchard-cms-strongly-typed-webapi-routing/</guid><category><![CDATA[Orchard CMS]]></category><category><![CDATA[WebApi]]></category><category><![CDATA[Routing]]></category><category><![CDATA[C#]]></category><pubDate>Mon, 04 Dec 2017 22:12:45 GMT</pubDate><content:encoded>&lt;p&gt;If you&apos;re developing WebApi projects in Orchard, you&apos;re probably used to declare your API routes as a simple string array. However, we can get fully compile-time checked routes that are also easy to refactor.&lt;/p&gt;
&lt;div class=&quot;fold&quot;&gt;&lt;/div&gt;
&lt;p&gt;If you check the &lt;a href=&quot;http://docs.orchardproject.net/en/latest/Documentation/WebApi-In-Orchard/&quot;&gt;Orchard Docs&lt;/a&gt; or any tutorials for setting up API routes you&apos;ll
quickly end up with a RouteConfig like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApiRoutes&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token type-list&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;IHttpRouteProvider&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;IEnumerable&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;RouteDescriptor&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetRoutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;RouteDescriptor&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;HttpRouteDescriptor&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Default Api&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              Priority &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              RouteTemplate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;api/users&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              Defaults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyCustomModule&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                controller &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Users&quot;&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;HttpRouteDescriptor&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
              Name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Default Api&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              Priority &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              RouteTemplate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;api/users/{id}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
              Defaults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;
              &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyCustomModule&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                controller &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Users&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; RouteParameter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Optional
              &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;

            &lt;span class=&quot;token comment&quot;&gt;// etc...&lt;/span&gt;

        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I have some problems with this approach: It becomes quite unwieldy pretty soon, it&apos;s hard to refactor and easy to introduce bugs.&lt;br/&gt; If you&apos;ve ever searched
for hours on end why a route isn&apos;t hit, called with wrong or messed up parameters just to find a dumb typo in your &lt;code class=&quot;language-text&quot;&gt;RouteConfig&lt;/code&gt;, you know what I&apos;m talking
about.&lt;/p&gt;
&lt;p&gt;So what to do about it?&lt;/p&gt;
&lt;p&gt;Initially, I spent some time trying to implement my own
&lt;a href=&quot;https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;AttributeRouting&lt;/code&gt;&lt;/a&gt; in Orchard, but it just didn&apos;t go too well. So
after a while I ditched that idea and began from scratch. You can see the result below:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// C#7 syntax for brevity&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ExampleController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token type-list&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ApiController&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;IHttpActionResult&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;value1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;value2&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetDetails&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;IHttpActionResult&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;FromBody&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Created&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;IHttpActionResult&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token attribute&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;FromBody&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;IHttpActionResult&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Delete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ApiRoutes&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token type-list&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;IHttpRouteProvider&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;IEnumerable&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;RouteDescriptor&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetRoutes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; route &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;ApiRouteFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Statics&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ModuleAreaName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;api&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;BuildRoute&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ExampleController&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;              &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GetList&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;BuildRoute&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ExampleController&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;         &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GetDetails&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{id:int}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;BuildRoute&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ExampleController&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Post&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;       &lt;span class=&quot;token string&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;BuildRoute&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ExampleController&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Put&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;        &lt;span class=&quot;token string&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{id:int}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;BuildRoute&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ExampleController&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;         &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Delete&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;     &lt;span class=&quot;token string&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{id:int}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;//...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you&apos;re in a hurry, go grab the source from &lt;a href=&quot;https://github.com/xceno/Orchard.Tools&quot;&gt;Github&lt;/a&gt; and get back coding. Read on for some details about the
implementation.&lt;/p&gt;
&lt;h2&gt;How it works&lt;/h2&gt;
&lt;p&gt;Let&apos;s start with the call to &lt;code class=&quot;language-text&quot;&gt;BuildRoute&lt;/code&gt; and dig deeper from there.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ExampleController.cs&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;IHttpActionResult&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetDetails&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;// ApiRoutes.cs&lt;/span&gt;
route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;BuildRoute&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ExampleController&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GetDetails&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{id:int}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;// ApiRouteFactory.cs&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;HttpRouteDescriptor&lt;/span&gt; &lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;BuildRoute&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TController&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TParam&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Expression&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;Func&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TController&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Func&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;TParam&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; IHttpActionResult&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; expression&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt; routeParts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;TController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token type-list&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ApiController&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; actionName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ReflectOnMethod&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;TController&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;NameOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;expression&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;MakeRouteDescriptor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token type-expression class-name&quot;&gt;TController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; routeParts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; actionName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you&apos;re not familiar with &lt;code class=&quot;language-text&quot;&gt;Func&amp;lt;T, TResult&amp;gt;&lt;/code&gt; &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/bb549151(v=vs.110).aspx&quot;&gt;MSDN explains it pretty good&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[Func] encapsulates a method that has one parameter and returns a value of the type specified by the TResult parameter.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Therefore, &lt;code class=&quot;language-text&quot;&gt;BuildRoute&lt;/code&gt;s first parameter is an expression that takes a controller as input and expects a function as result, which itself takes one parameter and returns &lt;code class=&quot;language-text&quot;&gt;IHttpActionResult&lt;/code&gt;. (Yeah, read that again slowly.)&lt;/p&gt;
&lt;p&gt;This expression is what brings us all the intellisense, type safety and refactoring goodness. If we change the signature of &lt;code class=&quot;language-text&quot;&gt;GetDetails&lt;/code&gt;, our module will no longer compile.
The code that makes this possible resides in &lt;code class=&quot;language-text&quot;&gt;ReflectOnMethod&lt;/code&gt; and was shamelessly stolen from &lt;a href=&quot;https://stackoverflow.com/questions/8225302/get-the-name-of-a-method-using-an-expression/26976055#26976055&quot;&gt;this excellent StackOverflow answer&lt;/a&gt;. (Thanks kędrzu!)&lt;/p&gt;
&lt;h4&gt;MakeRouteDescriptor&lt;/h4&gt;
&lt;p&gt;At this point, all that remains is some string parsing and building the &lt;code class=&quot;language-text&quot;&gt;HttpRouteDescriptor&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;HttpRouteDescriptor&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MakeRouteDescriptor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Type&lt;/span&gt; controller&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; routeSlug&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; action&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; route &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;routePrefix &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; routeSlug&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; ctrlIndex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; controller&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;LastIndexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Controller&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; StringComparison&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Ordinal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; controllerName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; controller&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ctrlIndex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MakeRouteDescriptor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;moduleAreaName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        route&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        controllerName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        action&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token named-parameter punctuation&quot;&gt;httpMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;HttpMethodOfAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;action&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;HttpRouteDescriptor&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;MakeRouteDescriptor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; area&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; route&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; controller&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; action&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; priority &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;HttpMethod&lt;/span&gt; httpMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; defaults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;ExpandoObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; underlyingObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;IDictionary&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    underlyingObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;area&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; area&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    underlyingObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;controller&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; controller&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    underlyingObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;action&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; action&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; constraints &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ParseRouteAttributeConstraints&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;route&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; httpMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;HttpRouteDescriptor&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        RouteTemplate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CleanupRoute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;route&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Defaults &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Priority &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; priority&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        Constraints &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; constraints
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are two interesting things going on, but first things first.
You&apos;re probably asking yourself: WTF is the &lt;code class=&quot;language-text&quot;&gt;ExpandoObject&lt;/code&gt; doing here?
Well, in this example absolutely nothing. You could use a dictionary instead. It just happened that I wrote some modules which fiddle around with the generated routes and having an &lt;code class=&quot;language-text&quot;&gt;ExpandoObject&lt;/code&gt; makes it easier to do so.&lt;/p&gt;
&lt;p&gt;With that out of the way, let&apos;s continue.&lt;/p&gt;
&lt;h4&gt;HttpMethodOfAction&lt;/h4&gt;
&lt;p&gt;Maybe you noticed that every action in the &lt;code class=&quot;language-text&quot;&gt;ExampleController&lt;/code&gt; starts with a &lt;code class=&quot;language-text&quot;&gt;HttpVerb&lt;/code&gt;. This is the only important thing you&apos;ll need to remember when using the module.&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;BuildRoute&amp;lt;TController&amp;gt;(...)&lt;/code&gt; function will parse the action name for the verb and assign it to the resulting &lt;code class=&quot;language-text&quot;&gt;RouteDescriptor&lt;/code&gt;.
Sounds fancy, but again, there&apos;s absolutely no magic going on there:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// The inner workings of the ApiRouteFactory&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// when determining the HTTP Verb for a controller action.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;HttpMethod&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;HttpMethodOfAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; actionName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;actionName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;StartsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HttpMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Method&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; StringComparison&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OrdinalIgnoreCase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; HttpMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Post&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;actionName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;StartsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HttpMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Put&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Method&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; StringComparison&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OrdinalIgnoreCase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; HttpMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Put&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Yep, there is no official HttpMethod.Patch!&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;actionName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;StartsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Patch&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; StringComparison&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OrdinalIgnoreCase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;HttpMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;PATCH&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;actionName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;StartsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HttpMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Delete&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Method&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; StringComparison&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OrdinalIgnoreCase&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; HttpMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Delete&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; HttpMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Get&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So an &lt;code class=&quot;language-text&quot;&gt;actionName&lt;/code&gt; of &lt;code class=&quot;language-text&quot;&gt;&amp;quot;GetSomething&amp;quot;&lt;/code&gt; will result in &lt;code class=&quot;language-text&quot;&gt;HttpMethod.Get&lt;/code&gt; and so on.&lt;/p&gt;
&lt;h4&gt;ParseRouteAttributeConstraints&lt;/h4&gt;
&lt;p&gt;And once again some string parsing. When defining routes, we can use &lt;a href=&quot;https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/creating-a-route-constraint-cs&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;RouteContstraints&lt;/code&gt;&lt;/a&gt; to narrow down the request that matches a particular route.
So if we define a route like this: &lt;code class=&quot;language-text&quot;&gt;GET &amp;quot;api/example/{id}&amp;quot;&lt;/code&gt;, any requests that fill in &lt;strong&gt;anything&lt;/strong&gt; for the id parameter will match. This may be wanted in some cases, but most of the time it&apos;s a good idea to restrict parameters to a certain type, like an integer: &lt;code class=&quot;language-text&quot;&gt;GET &amp;quot;api/example/{id:int}&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is exactly what the following code does. It looks at all the parts of our route and extracts the &lt;code class=&quot;language-text&quot;&gt;RouteContstraints&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/// &amp;lt;summary&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// &amp;lt;para&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// Creates route constraints from the given route.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// Use the return value as input for &amp;lt;c&gt;HttpRouteDescriptor.Contraints&amp;lt;/c&gt;.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// &amp;lt;/para&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// &amp;lt;example&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// &quot;http://example.com/api/users/{id:int}&quot; will create an integer contstraint for the id parameter.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// &amp;lt;/example&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// &amp;lt;/summary&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// &amp;lt;param name=&quot;route&quot;&gt;The absolute route to be parsed.&amp;lt;/param&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// &amp;lt;param name=&quot;defaults&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// An object that will be filled with all optional parameters.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// Should be used as value for &amp;lt;c&gt;HttpRouteDescriptor.Defaults&amp;lt;/c&gt;.&amp;lt;/param&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;/// &amp;lt;param name=&quot;httpMethod&quot;&gt;The routes http-verb.&amp;lt;/param&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;dynamic&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ParseRouteAttributeConstraints&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; route&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ExpandoObject&lt;/span&gt; defaults&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HttpMethod&lt;/span&gt; httpMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; split &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; route&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string character&quot;&gt;&apos;/&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; StringSplitOptions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RemoveEmptyEntries&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; attributes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; split&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Where&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;StartsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;EndsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;dynamic&lt;/span&gt;&lt;/span&gt; constraints &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;ExpandoObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; underlyingObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;IDictionary&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;constraints&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; attr &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; attributes&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; tmpSplit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; attr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string character&quot;&gt;&apos;{&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string character&quot;&gt;&apos;}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string character&quot;&gt;&apos;:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmpSplit&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tmpSplit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Length &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;underlyingObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ContainsKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; typeName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmpSplit&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; isOptional &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; typeName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;EndsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isOptional&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                typeName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; typeName&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;TrimEnd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string character&quot;&gt;&apos;?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;IDictionary&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;defaults&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; RouteParameter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Optional&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;/span&gt; constraint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetConstraintForTypename&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;typeName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isOptional&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;constraint &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                underlyingObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; constraint&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                Debug&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;No matching IHttpRouteConstraint found for type &apos;{0}&apos;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; typeName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;httpMethod &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        underlyingObject&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;httpMethod&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;HttpMethodConstraint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;httpMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; HttpMethod&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; constraints&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;IHttpRouteConstraint&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetConstraintForTypename&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;string&lt;/span&gt;&lt;/span&gt; typename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt;&lt;/span&gt; isOptional&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;/* List of all route constraints:
        * https://msdn.microsoft.com/en-us/library/system.web.http.routing.constraints(v=vs.118).aspx
        */&lt;/span&gt;

    &lt;span class=&quot;token class-name&quot;&gt;IHttpRouteConstraint&lt;/span&gt; constraint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;typename&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bool&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;boolean&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            constraint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;BoolRouteConstraint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;int&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            constraint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;IntRouteConstraint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;long&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            constraint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;LongRouteConstraint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;float&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            constraint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;FloatRouteConstraint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;double&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            constraint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;DoubleRouteConstraint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            constraint &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;AlphaRouteConstraint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; isOptional &lt;span class=&quot;token punctuation&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;OptionalRouteConstraint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;constraint&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; constraint&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I chose to only implement the most commonly used constraints, but feel free to extend the code above by going through &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/system.web.http.routing.constraints(v=vs.118).aspx&quot;&gt;this list on MSDN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The TLDR version of this code: Take an attribute like &lt;code class=&quot;language-text&quot;&gt;{id:int}&lt;/code&gt;, split it into &lt;code class=&quot;language-text&quot;&gt;key = &amp;quot;id&amp;quot;&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;constraint = &amp;quot;int&amp;quot;&lt;/code&gt;, and update the &lt;code class=&quot;language-text&quot;&gt;RouteConstraints&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;RouteDefaults&lt;/code&gt; accordingly.&lt;/p&gt;
&lt;p&gt;And that&apos;s it!&lt;/p&gt;
&lt;p&gt;If you read until this point, thanks!&lt;br/&gt;
I&apos;d warmly welcome any comments, ideas, and bug reports. Just Shoot me a mail. Also, check out the full source on &lt;a href=&quot;https://github.com/xceno/Orchard.Tools&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Over and out.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Orchard CMS: Beware of SQL Keywords]]></title><description><![CDATA[Just a quick reminder, before you debug hours on end (like me).Sometimes while developing a new Orchard module I get carried away and forget…]]></description><link>https://www.xceno.io/posts/2017-12-01-orchard-cms-beware-of-sql-keywords/</link><guid isPermaLink="false">https://www.xceno.io/posts/2017-12-01-orchard-cms-beware-of-sql-keywords/</guid><category><![CDATA[Orchard CMS]]></category><category><![CDATA[nHibernate]]></category><category><![CDATA[SQL]]></category><category><![CDATA[C#]]></category><category><![CDATA[Random]]></category><pubDate>Fri, 01 Dec 2017 19:23:20 GMT</pubDate><content:encoded>&lt;p&gt;Just a quick reminder, before you debug hours on end (like me).&lt;/p&gt;
&lt;div class=&quot;fold&quot;&gt;&lt;/div&gt;
&lt;p&gt;Sometimes while developing a new Orchard module I get carried away and forget about other stuff.
Reserved SQL keywords for example. Then we might end up with a class like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ShoppingCartEntryPart&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token type-list&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;ContentPart&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ShoppingCartEntryRecord&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; Order
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Retrieve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Order&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Order&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; Price
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Retrieve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Price&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Price&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and a migration like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  SchemaBuilder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;CreateTable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;ShoppingCartEntryRecord&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    table &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; table
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ContentPartRecord&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Price&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token generic-method&quot;&gt;&lt;span class=&quot;token function&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;token generic class-name&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Order&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  ContentDefinitionManager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;AlterPartDefinition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token type-expression class-name&quot;&gt;ShoppingCartEntryPart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    config &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Attachable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The module will of course compile, but as soon as we use the &lt;code class=&quot;language-text&quot;&gt;ContentManager&lt;/code&gt; to retrieve or store it, it will crash with an exception like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NHibernate.Exceptions.GenericADOException:&lt;/strong&gt;&lt;br/&gt;
&apos;could not insert: [ReservedKeywordsTest.Models.ShoppingCartEntryRecord#12][sql: insert into reservedkeywordstest_shoppingcartentryrecord (price, order, id) values (?, ?, ?)]&apos;&lt;br/&gt;&lt;br/&gt;
&lt;strong&gt;InnerException&lt;/strong&gt;&lt;br/&gt;
SqlCeException: There was an error parsing the query.&lt;br/&gt;
[ Token line number = 1, Token line offset = 66, Token in error = Order ]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&apos;s because we&apos;re using SQL-Server or SQLCE where &lt;code class=&quot;language-text&quot;&gt;ORDER&lt;/code&gt; is a reserved keyword.
Check &lt;a href=&quot;https://docs.microsoft.com/en-us/sql/t-sql/language-elements/reserved-keywords-transact-sql&quot;&gt;this list on MSDN&lt;/a&gt; for all reserved keywords.&lt;/p&gt;
&lt;p&gt;In the example above we&apos;d just need to rename &lt;code class=&quot;language-text&quot;&gt;Order&lt;/code&gt; to something like &lt;code class=&quot;language-text&quot;&gt;SortOrder&lt;/code&gt; and we&apos;re good to go again.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Orchard CMS: Overriding the Admin Theme]]></title><description><![CDATA[Overriding the admin theme is easy, but no one seems to talk about it. Let's change that here.Almost everything in Orchard is achieved by…]]></description><link>https://www.xceno.io/posts/2017-11-12-orchard-cms-overriding-the-admin-theme/</link><guid isPermaLink="false">https://www.xceno.io/posts/2017-11-12-orchard-cms-overriding-the-admin-theme/</guid><category><![CDATA[Orchard CMS]]></category><category><![CDATA[Themes]]></category><category><![CDATA[Customizing]]></category><category><![CDATA[C#]]></category><category><![CDATA[HowTo]]></category><pubDate>Sun, 12 Nov 2017 20:02:34 GMT</pubDate><content:encoded>&lt;p&gt;Overriding the admin theme is easy, but no one seems to talk about it. Let&apos;s change that here.&lt;/p&gt;
&lt;div class=&quot;fold&quot;&gt;&lt;/div&gt;
&lt;p&gt;Almost everything in Orchard is achieved by implementing an interface. Orchard will collect all the implementations
and loop through them, or it selects the one with the highest priority; depending on the feature.&lt;/p&gt;
&lt;p&gt;Good news everybody, it&apos;s the same for overriding themes!&lt;/p&gt;
&lt;h2&gt;TLDR;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Implement &lt;a href=&quot;https://github.com/OrchardCMS/Orchard/blob/1.10.x/src/Orchard/Themes/IThemeSelector.cs&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;IThemeSelector&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Make sure you check the &lt;a href=&quot;https://github.com/OrchardCMS/Orchard/blob/1.10.x/src/Orchard/UI/Admin/AdminFilter.cs#L36&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;AdminFilter&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Return a &lt;code class=&quot;language-text&quot;&gt;ThemeSelectorResult&lt;/code&gt; with a higher priority than the default admin theme.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Activate&lt;/code&gt; your custom admin theme. (Do &lt;strong&gt;not&lt;/strong&gt; click &lt;code class=&quot;language-text&quot;&gt;Set current&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;csharp&quot;&gt;&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;MyAwesomeAdminTheme&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;System&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Web&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Routing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;Orchard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Themes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;Orchard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UI&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Admin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OverrideTheAdmin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token type-list&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;IThemeSelector&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token return-type class-name&quot;&gt;ThemeSelectorResult&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetTheme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;RequestContext&lt;/span&gt; context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; AdminFilter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;IsApplied&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token constructor-invocation class-name&quot;&gt;ThemeSelectorResult&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                  Priority &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  ThemeName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;MyAwesomeAdminTheme&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that&apos;s about it, from here on it&apos;s customizing as usual.&lt;/p&gt;
&lt;h2&gt;How it works&lt;/h2&gt;
&lt;p&gt;This section shines a little light on the code above. If you&apos;ve got some time and want to know what you&apos;re doing (I hope you do), this is for you.&lt;/p&gt;
&lt;p&gt;To get a list of all implementations of a certain interface, simply inject it as &lt;code class=&quot;language-text&quot;&gt;IEnumberable&amp;lt;ISomeInterface&amp;gt;&lt;/code&gt; and autofac will take care of the rest.&lt;/p&gt;
&lt;p&gt;So on every request that returns a &lt;a href=&quot;https://github.com/OrchardCMS/Orchard/blob/1.10.x/src/Orchard/Themes/ThemeFilter.cs&quot;&gt;themed result&lt;/a&gt;, Orchard will collect all &lt;code class=&quot;language-text&quot;&gt;IThemeSelector&lt;/code&gt; implementations, including your new admin theme selector. Because of this, it&apos;s important to check that the current route is actually the admin dashboard by calling &lt;code class=&quot;language-text&quot;&gt;AdminFilter.IsApplied&lt;/code&gt;. Otherwise you would also override your active frontend themes.&lt;/p&gt;
&lt;p&gt;It will then &lt;a href=&quot;https://github.com/OrchardCMS/Orchard/blob/1.10.x/src/Orchard.Web/Modules/Orchard.Themes/Services/ThemeService.cs#L108&quot;&gt;order them by priority&lt;/a&gt; (highest first),
and take the first &lt;em&gt;active&lt;/em&gt; theme that matches the name of the current &lt;code class=&quot;language-text&quot;&gt;ThemeSelectorResult&lt;/code&gt;.
The result is assigned as current theme to the current request.&lt;/p&gt;
&lt;p&gt;Happy coding!&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;Fun fact&lt;/h4&gt;
&lt;p&gt;For some reason there are two identical implementations of the &lt;code class=&quot;language-text&quot;&gt;GetRequestTheme&lt;/code&gt; function. One in &lt;a href=&quot;https://github.com/OrchardCMS/Orchard/blob/1.10.x/src/Orchard.Web/Modules/Orchard.Themes/Services/ThemeService.cs#L108&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Orchard.Themes/Services/ThemeService.cs&lt;/code&gt;&lt;/a&gt; the other in &lt;a href=&quot;https://github.com/OrchardCMS/Orchard/blob/1.10.x/src/Orchard/Themes/ThemeManager.cs&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Orchard/Themes/ThemeManager.cs&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;</content:encoded></item></channel></rss>