RazorRuntimeCompilation bug when assembly emitted by Roslyn with empty location added as MVC application part
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Describe the bug
After upgraded to .NET 8.0.200, it demands me to add RazorRuntimeCompilation otherwise the application crashes because it cannot locate the MVC view.
I generated a dynamic controller assembly by Roslyn. This assembly doesn't have location because I loaded it from bytes right after generation, also it doesn't have IsDynamic=true.
Then, I created an ASP.NET Core MVC application (.NET 6, 7, 8), added RazorRuntimeCompilation and added the generated assembly as AssemblyPart. When running the application, it gave below `ArgumentException: Empty path name is not legal` error

After investigation, I found out that RazorRuntimeCompilation just get reference paths from extension method `Microsoft.AspNetCore.Mvc.ApplicationParts.AssemblyPartExtensions.GetReferencePaths(...)` which returns assembly.Location (empty for this kind of assembly).
In later code of `RazorReferenceManager`, `CreateMetadataReference(...)` method doesn't do any null/empty check on the path and caused this error.
### Expected Behavior
Those assemblies dynamically created by Roslyn should not affect RazorRuntimeCompilation due to their empty Location property.
### Steps To Reproduce
- Create ASP.NET Core MVC app
- Add RazorRuntimeCompilation
- Use Roslyn to create dynamic assembly with API controller.
- Load the assembly from stream after Roslyn's emit.
- Add loaded assembly as MVC application part using `new AssemblyPart(asm)`
### Exceptions (if any)
_No response_
### .NET Version
8.0.200
### Anything else?
**Suggestion:**
- `RazorReferenceManager.GetCompilationReferences(...)` should filter out those empty locations.
**Workaround:**
- Create my own ApplicationPart derived class and replace AssemblyPart to evade `GetReferencePaths(...)` call
```
public class MyAssemblyPart: ApplicationPart, IApplicationPartTypeProvider
{
public override string Name => Assembly.GetName().Name!;
public IEnumerable Types => Assembly.DefinedTypes;
public Assembly Assembly { get; }
public MyAssemblyPart(Assembly assembly)
{
Assembly = assembly ?? throw new ArgumentNullException(nameof(assembly));
}
}
```
Contributor guide
Assessment
This issue has not been assessed yet.