title: Asp.net core and Angular in production: Spa is not being served
body: <p>My web application was scaffolded from the dotnet core 3.0 Angular template.  I want to deploy the first version into production but I am struggling to have the Angular app served.  I am using Kestrel as the webserver (it's an intranet application).</p>
  
  <p>I have published the application with <code>dotnet publish -c Release -o ../app-dist</code> which build the Asp.net application and it triggered <code>ng</code> to build a production release of the client.  The resulting folder structure includes a <code>app-dist/wwwroot</code> folder which has some assets like favicon and it has a <code>app-dist/ClientApp/dist/app</code> folder with the <code>index.html</code> and the compiled <code>js</code> and <code>css</code> assets.  If I start the application by running <code>dotnet app.dll</code> in <code>app-dist</code>, Kestrel starts but it fails to serve the client application.  I can access the minor assets from <code>wwwroot</code> as well as the Razor pages that are used for user authentication.</p>
  
  <p>In my docker deployment, I get the following error when trying to access <code>https://host/</code> or <code>https://host/index.html</code> (as well as <code>http</code> equivalents):</p>
  
  <blockquote>
    <p>System.InvalidOperationException: The SPA default page middleware could not return the default page '/index.html' because it was not found, and no other middleware handled the request.
    Your application is running in Production mode, so make sure it has been published, or that you have built your SPA manually. Alternatively you may wish to switch to the Development environment.</p>
  </blockquote>
  
  <p>When I run the same command in <code>app-dist</code> on my macOS development system I get the same error (after first setting <code>export ASPNETCORE_ENVIRONMENT=production</code>).</p>
  
  <p>In my <code>Startup.cs</code> I have the following:</p>
  
  <pre class="lang-c prettyprint-override"><code>public void ConfigureServices(IServiceCollection services)
  {
      services.AddMvc(); 
  ...
  
  }
  
  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  {
      app.UseStaticFiles();
      if (!env.IsDevelopment())
      {
          app.UseSpaStaticFiles();
      }
  
  ...
  
      app.UseEndpoints(endpoints =&gt;
      {
          endpoints.MapControllerRoute(
              name: "default",
              pattern: "{controller}/{action=Index}/{id?}");
          endpoints.MapRazorPages();
      });
      app.UseSpa(spa =&gt;
      {
          spa.Options.SourcePath = "ClientApp";
          if (env.IsDevelopment())
          {
              spa.UseAngularCliServer(npmScript: "start");
          }
      });
  }
  </code></pre>
  
  <p>In my csproj:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;PropertyGroup&gt;
      &lt;TargetFramework&gt;netcoreapp3.0&lt;/TargetFramework&gt;
      &lt;TypeScriptCompileBlocked&gt;true&lt;/TypeScriptCompileBlocked&gt;
      &lt;TypeScriptToolsVersion&gt;Latest&lt;/TypeScriptToolsVersion&gt;
      &lt;IsPackable&gt;false&lt;/IsPackable&gt;
      &lt;SpaRoot&gt;ClientApp\&lt;/SpaRoot&gt;
      &lt;DefaultItemExcludes&gt;$(DefaultItemExcludes);$(SpaRoot)node_modules\**&lt;/DefaultItemExcludes&gt;
      &lt;BuildServerSideRenderer&gt;false&lt;/BuildServerSideRenderer&gt;
  &lt;/PropertyGroup&gt;
  
  ...
  
  &lt;Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish"&gt;
      &lt;Exec WorkingDirectory="$(SpaRoot)" Command="npm install" /&gt;
      &lt;Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" /&gt;
      &lt;Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " /&gt;
      &lt;ItemGroup&gt;
          &lt;DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" /&gt;
          &lt;DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" /&gt;
          &lt;ResolvedFileToPublish Include="@(DistFiles-&gt;'%(FullPath)')" Exclude="@(ResolvedFileToPublish)"&gt;
                  &lt;RelativePath&gt;%(DistFiles.Identity)&lt;/RelativePath&gt;
                  &lt;CopyToPublishDirectory&gt;PreserveNewest&lt;/CopyToPublishDirectory&gt;
                  &lt;ExcludeFromSingleFile&gt;true&lt;/ExcludeFromSingleFile&gt;
          &lt;/ResolvedFileToPublish&gt;
      &lt;/ItemGroup&gt;
  &lt;/Target&gt;
  </code></pre>
  
  <p>I have tried copying the Angular <code>index.html</code> and compiled files to the <code>wwwroot</code> as well as the <code>ClientApp</code> folder, but neither made a difference.  I also tried setting <code>spa.Options.SourcePath = "ClientApp/dist/app";</code>.  <strong>What seems incorrectly configured, or what should I investigate next?</strong></p>