Using WebApplicationFactory precompiled .cshtml views are not found
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
I have a web application written using .NET9. In this application I am using the Slim Builder to create the web application (intend to do NativeAOT compilation before actual deployment).
In this application I also use Razor views (.cshtml files) that are automatically precompiled into the application assembly. The application runs fine when I just run the application standalone (even when the .cshtml files are not copied to a deployment location). However, when I want to implement integration tests using the `WebApplicationFactory` and request one of the URLs that should invoke a Razor view, the test stops with a `FileNotFoundException` indicating it cannot find the .cshtml file, which is thrown from the code `RazorHelper.RenderViewToStream` method that is listed below.
I render the view myself using code like this (the method is mapped `WebApplication.MapGet`):
```C#
private static Task HandleIndex(HttpContext httpContext,
[FromServices] IRazorViewEngine viewEngine,
[FromServices] ITempDataProvider tempDataProvider)
{
return RazorHelper.RenderView(@"~/Pages/SharedPages/Index.cshtml",
new IndexModel(),
viewEngine,
tempDataProvider);
}
public static class RazorHelper
{
public static async Task RenderView(string viewPath,
TModel model,
IRazorViewEngine viewEngine,
ITempDataProvider tempDataProvider)
{
HttpContext httpContext = model.HttpContext;
using (StreamWriter streamWriter = new(httpContext.Response.BodyWriter.AsStream()))
{
await RenderViewToStream(viewPath,
model,
httpContext.GetRouteData(),
httpContext,
viewEngine,
tempDataProvider,
streamWriter).ConfigureAwait(ConfigureAwaitOptions.ContinueOnCapturedContext);
}
}
private static async Task RenderViewToStream(string viewPath,
TModel model,
RouteData routeData,
HttpContext httpContext,
IRazorViewEngine viewEngine,
ITempDataProvider tempDataProvider,
StreamWriter streamWriter)
{
// Create the action context
ActionContext actionContext = new(httpContext,
routeData,
new ActionDescriptor());
// Get the actual view
ViewEngineResult viewEngineResult = viewEngine.GetView(null/*executingFilePath*/,
viewPath,
false/*isMainPage*/);
IView? view;
if (viewEngineResult.Success)
{
view = viewEngineResult.View;
}
else
{
throw new FileNotFoundException($@"Unable to find '{viewPath}'");
}
// Create the model and the view data
ViewDataDictionary viewData = new(new EmptyModelMetadataProvider(),
new ModelStateDictionary())
{
Model = model
};
// Create the view context
ViewContext viewContext = new(actionContext,
view,
viewData,
new TempDataDictionary(httpContext,
tempDataProvider),
streamWriter,
new());
// Render the view
await view.RenderAsync(viewContext).
ConfigureAwait(ConfigureAwaitOptions.ContinueOnCapturedContext);
}
}
```
I am wondering why this code works when the ASP.NET core application is running standalone (or is debugged from Visual Studio), but does not work when it is run from an integration test using the `WebApplicationFactory`.
### Expected Behavior
The code above runs both when the application is run, and when doing an integration tests using the `WebApplicationFactory`.
### Steps To Reproduce
_No response_
### Exceptions (if any)
_No response_
### .NET Version
9.0.307
### Anything else?
.NET SDK:
Version: 9.0.307
Commit: 3bc3012cf9
Workload version: 9.0.300-manifests.6f9c3023
MSBuild version: 17.14.28+09c1be848
Runtime Environment:
OS Name: Windows
OS Version: 10.0.22631
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\9.0.307\
.NET workloads installed:
[maui-windows]
Installation Source: VS 17.14.36705.20
Manifest Version: 9.0.111/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.sdk.maui\9.0.111\WorkloadManifest.json
Install Type: Msi
[maccatalyst]
Installation Source: VS 17.14.36705.20
Manifest Version: 26.0.9752/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.sdk.maccatalyst\26.0.9752\WorkloadManifest.json
Install Type: Msi
[android]
Installation Source: VS 17.14.36705.20
Manifest Version: 35.0.78/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.sdk.android\35.0.78\WorkloadManifest.json
Install Type: Msi
[ios]
Installation Source: VS 17.14.36705.20
Manifest Version: 26.0.9752/9.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\9.0.100\microsoft.net.sdk.ios\26.0.9752\WorkloadManifest.json
Install Type: Msi
[aspire]
Installation Source: VS 17.14.36705.20
Manifest Version: 8.2.2/8.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.2.2\WorkloadManifest.json
Install Type: Msi
Configured to use loose manifests when installing new manifests.
Host:
Version: 9.0.11
Architecture: x64
Commit: fa7cdded37
.NET SDKs installed:
5.0.416 [C:\Program Files\dotnet\sdk]
9.0.307 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.22 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.22 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.22 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.11 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables:
Not set
global.json file:
C:\_MVS\personal.NET\global.json
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
Contributor guide
Assessment
This issue has not been assessed yet.