.Net Core 3.1 on Azure App Service

I have a .Net Core 3.1 app that runs perfectly fine on a Mac using Rider. I frequently use Razor Smart Pages. However once deployed to Azure App Service (both Windows and Linux), all links that resolve to a smart razor page can’t be found.

For instance, /events is not a smart razor page and works just fine. However when I try to visit something like /event/1, I get the following error:

System.IO.FileNotFoundException: Unable to find the specified file.
   at Interop.Sys.GetCwdHelper(Byte* ptr, Int32 bufferSize)
   at Interop.Sys.GetCwd()
   at ServiceStack.Host.Handlers.RequestInfoHandler.GetRequestInfo(IRequest httpReq) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\RequestInfoHandler.cs:line 303
   at ServiceStack.Host.Handlers.RequestInfoHandler.ProcessRequestAsync(IRequest httpReq, IResponse httpRes, String operationName) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\RequestInfoHandler.cs:line 211
   at ServiceStack.Host.Handlers.HttpAsyncTaskHandler.Middleware(HttpContext context, Func`1 next) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\Host\Handlers\HttpAsyncTaskHandler.cs:line 160
   at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_1.<Use>b__1(HttpContext context)
   at Microsoft.AspNetCore.Builder.UseExtensions.<>c__DisplayClass0_2.<Use>b__2()
   at ServiceStack.AppHostBase.ProcessRequest(HttpContext context, Func`1 next) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack\AppHostBase.NetCore.cs:line 189
   at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Also when I visit a smart razor pages like /actions, I will get the same error unless I manually add the trailing / then it works. I have reviewed sample projects and documentation and running out of options.

I was able to reproduce the issue locally by simply publishing the web app locally and then from the output directory running the command dotnet MyApp.dll. This behavior is the same on netcoreapp3.1 and netcoreapp3.0. If I revert my code to netcoreapp2.2, smart routing razor pages work properly after publishing.

So to update the situation, my code from the IDE will behave normally in netcore 2.2, 3.0 and 3.1. However I get different behavior after a plain vanilla dotnet publish locally on my Macbook Pro. This behavior also occurs when published to Azure App Service for both Windows and Linux.

I have reviewed the documentation @ https://docs.microsoft.com/en-us/dotnet/core/run-time-config/compilation which details the differences in compilation between 2.2 and 3.0 and set all properties to false in my project files but smart razor pages continue to fail after publish.

<TieredCompilation>false</TieredCompilation>
<TieredCompilationQuickJit>false</TieredCompilationQuickJit>
<TieredCompilationQuickJitForLoops>false</TieredCompilationQuickJitForLoops>

Further debugging, I ran my app with netcoreapp3.0 and used the ?virtualPathCount to see all the files in the virtual path, on my app and the Validation app, I could see no files with .cshtml as the file extension. However when I swapped my app to netcoreapp2.2, I could see razor files in the virtual path list. Seems like their may be a bug in regards to netcore 3 and razor files.

Thanks Microsoft! So it seems the MvcRazorCompileOnPublish project property is no longer supported or is not behaving properly with 3.0 and above, see https://github.com/dotnet/aspnetcore/issues/16688 for more details. The solution to this problem is as follows:

  1. Change MvcRazorCompileOnPublish to RazorCompileOnPublish in your web application project.
  2. Reference Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation is your project.
  3. In Startup.cs, add .AddRazorRuntimeCompilation() to services.AddMvc()
  4. Profit!

Yeah I noticed the dev time razor reload was broken in .NET Core 3.0 and required adding AddRazorRuntimeCompilation() to all MVC or Razor .NET Core project templates a while ago.

Thanks for the tip on the renamed <RazorCompileOnPublish/> it was disabled in the comments, I’ll update them to use the renamed property as well.

Does this also effect Docker deployments on netcoreapp3.1?

I’m in the same boat here.
My application starts to work in Docker as soon as I change the following line to true.

<RazorCompileOnPublish>false</RazorCompileOnPublish>

Otherwise, my browser gets a Content-Type “application/cshtml” from the service, which would ask me to download the file instead of rendering the view and returning it as html.

Yes some features of Razor doesn’t support pre-compilation.

I understand that it is not supported, so we have to add the compilation at runtime, like you do in debug mode?

I am asking as you only include the reference to the required package when you are working in debug mode.

Or am I missing something else?

Sorry for these seemingly simple questions, I am just trying to understand why my browser wants to download the page instead of render it. I know the browser does not support “application/cshtml” as Content-Type, so there has to be a way to make it work at runtime and not lose the advanced features of Razor.

ok that’s annoying, AddRazorRuntimeCompilation() isn’t required when running in Release mode but seems to be required in published .NET Apps.

I’ve updated the razor template to always include it in this commit.

1 Like