title: Dynamically include precompiled (Razor) views in .NET Core 2.1
body: <p><strong>Idea</strong><br>
  I'm trying to build a modular .NET Core MVC application, were I can add 'modules' (extensions) just by copying the required libraries to a predefined folder. The application defines a set of dependencies (DI), error handling and basic layout; the modules provide the actual application or page logic.</p>
  
  <p>We've build a proof of concept, using <a href="http://extcore.net/" rel="nofollow noreferrer">ExtCore</a> - the concept works great, Controllers are added automatically and the 'plain' Views are recognized easily (the ones set as 'Embedded Resource').</p>
  
  <p><strong>Challenge</strong><br>
  However, I don't like the fact that Views are set to 'Embedded Resource', as it will be a small performance hit as the Razor page is now build at runtime. </p>
  
  <p><strong>What we've tried</strong><br>
  As .NET Core 2.1 now has the ability to create <a href="https://docs.microsoft.com/en-us/aspnet/core/razor-pages/ui-class?view=aspnetcore-2.1&amp;tabs=visual-studio" rel="nofollow noreferrer">Reusable Razor UI</a>, I've created a  project with a reference to <code>&lt;Project Sdk="Microsoft.NET.Sdk.Razor"&gt;</code> and compiled it to a Razor library (*.Views.dll). </p>
  
  <p>When I link the Razor View library as project dependency in (main) application, everything works fine. However, the goal still is to make the application fully plug-and-play and allow libraries to be included just by deploying them to a folder.</p>
  
  <p>I've tried to achieve this extending the Razor View Engine using a <code>PhysicalFileProvider</code>, but it won't recognize the views in the library.</p>
  
  <pre class="lang-cs prettyprint-override"><code> services.Configure&lt;RazorViewEngineOptions&gt;(opt =&gt;
   {
       opt.FileProviders.Add(new PhysicalFileProvider("path/to/extension"));
   });
  </code></pre>
  
  <p>The result always is an exception telling me that <code>/Views/[controller]/[action].cshtml</code> is not found.</p>
  
  <p>Searching other answers I came across <a href="https://github.com/CodeFuller/stackoverflow/tree/Q49579800-Precompiled-Views-In-Library" rel="nofollow noreferrer">this</a> project, which creates a <code>ViewLocationExpander</code>. I tried implementing various versions of this idea without luck - most likely because this is an older concept based on .NET Core 1.x which still uses a project dependency; although the Razor View engine now searches the namespace of the assembly.</p>
  
  <pre class="lang-cs prettyprint-override"><code>services.Configure&lt;RazorViewEngineOptions&gt;(opt =&gt;
  {
      opt.FileProviders.Add(new PhysicalFileProvider("path/to/extension");
      opt.ViewLocationExpanders.Add(new DynamicLocationExpander());
  });
  </code></pre>
  
  <p>Where <code>DynamicLocationExpander</code> looks like:</p>
  
  <pre class="lang-cs prettyprint-override"><code>public class DynamicLocationExpander: IViewLocationExpander
  {
  
      public DynamicLocationExpander()
      {
  
      }
  
      public void PopulateValues(ViewLocationExpanderContext context)
      {
  
      }
  
      public IEnumerable&lt;string&gt; ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable&lt;string&gt; viewLocations)
      {
          string assembly = ((ControllerActionDescriptor)context.ActionContext.ActionDescriptor)
              .ControllerTypeInfo.AsType().Assembly.GetName().Name;
  
          foreach (var viewLocation in viewLocations)
              yield return $"{assembly}/{viewLocation}";
      }
  }
  </code></pre>
  
  <p><strong>Question</strong><br>
  How can we dynamically link a Razor View library, containing precompiled views, to the Razor Engine in a (parent) application?</p>