After updating .NET Core 3.1 to .NET 5 RC2 (and all nugets) I got an exception during running tests from the console.
But the exception doesn't occur when I run:
The problem occurs only when I run test from the console using the dotnet test command, so I think the problem is related to 'dotnet test' from .NET 5 or the APS package has some issue.
Minimalistic repro can be found there https://github.com/WojciechNagorski/AspDotnet5Issue
The exception can be reproduced using the command:
dotnet test .\test.net5
I created also a test for .NET Core 3.1 that presents that the problem doesn't exist for the old version of .NET.
dotnet test .\test.netcore3.1
Description
I just create a new ASP project:
```c#
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
with almost default startup:
```c#
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetupValidation();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
where SetupValidation() method is an extension that registers all validators in all assemblies:
```c#
public static IMvcBuilder SetupValidation(this IMvcBuilder builder)
{
static void RegisterValidators(FluentValidationMvcConfiguration conf)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic && a.DefinedTypes.Any(t => typeof(IRequestValidator).GetTypeInfo().IsAssignableFrom(t) && !t.IsAbstract)))
{
conf.RegisterValidatorsFromAssembly(assembly);
}
}
return builder.AddFluentValidation(RegisterValidators);
}
The last step is the test method where I just create `TestServer`.
```c#
[Fact]
public void Test1()
{
TestServer server = new TestServer(Program.CreateHostBuilder(new string[] { })
.ConfigureTestServices(collection =>
{
}));
var client = server.CreateClient();
Assert.NotNull(client);
}
Error Message:
System.Reflection.ReflectionTypeLoadException : Unable to load one or more of the requested types.
Could not load type 'Microsoft.AspNetCore.Components.Forms.ReadRequest' from assembly 'Microsoft.AspNetCore.Components.Web, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' because it contains an object field at offset 4 that is incorrectly aligned or overlapped by a non-object field.
Stack Trace:
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at test.MvcBuilderExtensions.<>c.<SetupValidation>b__0_1(Assembly a) in C:\work\test\test\MvcBuilderExtensions.cs:line 17
at System.Linq.Enumerable.WhereArrayIterator`1.MoveNext()
at test.MvcBuilderExtensions.<SetupValidation>g__RegisterValidators|0_0(FluentValidationMvcConfiguration conf) in C:\work\test\test\MvcBuilderExtensions.cs:line 17
at FluentValidation.AspNetCore.FluentValidationMvcExtensions.AddFluentValidation(IMvcBuilder mvcBuilder, Action`1 configurationExpression) in C:\Projects\FluentValidation\src\FluentValidation.AspNetCore\FluentValidationMvcExtensions.cs:line 77
at test.MvcBuilderExtensions.SetupValidation(IMvcBuilder builder) in C:\work\test\test\MvcBuilderExtensions.cs:line 23
at test.Startup.ConfigureServices(IServiceCollection services) in C:\work\test\test\Startup.cs:line 18
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.InvokeCore(Object instance, IServiceCollection services)
at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.<>c__DisplayClass9_0.<Invoke>g__Startup|0(IServiceCollection serviceCollection)
at Microsoft.AspNetCore.Hosting.StartupLoader.ConfigureServicesDelegateBuilder`1.<>c__DisplayClass15_1.<BuildStartupServicesFilterPipeline>g__InvokeStartup|1(IServiceCollection serviceCollection)
at Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.ConfigureTestServicesStartupConfigureServicesFilter.<>c__DisplayClass2_0.<ConfigureServices>b__0(IServiceCollection serviceCollection)
at Microsoft.AspNetCore.Hosting.StartupLoader.ConfigureServicesDelegateBuilder`1.<>c__DisplayClass15_0.<BuildStartupServicesFilterPipeline>g__RunPipeline|0(IServiceCollection services)
at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.Invoke(Object instance, IServiceCollection services)
at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.<>c__DisplayClass8_0.<Build>b__0(IServiceCollection services)
at Microsoft.AspNetCore.Hosting.StartupLoader.ConfigureServicesDelegateBuilder`1.<>c__DisplayClass14_0.<ConfigureServices>g__ConfigureServicesWithContainerConfiguration|0(IServiceCollection services)
at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.ConfigureServices(IServiceCollection services)
at Microsoft.AspNetCore.Hosting.WebHost.EnsureApplicationServices()
at Microsoft.AspNetCore.Hosting.WebHost.Initialize()
at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
at Microsoft.AspNetCore.TestHost.TestServer..ctor(IWebHostBuilder builder, IFeatureCollection featureCollection)
at Microsoft.AspNetCore.TestHost.TestServer..ctor(IWebHostBuilder builder)
at test.integration.Example.Test1() in C:\work\test\test.integration\Example.cs:line 12
--- End of stack trace from previous location ---
dotnet --info❯ dotnet --info
.NET SDK (reflecting any global.json):
Version: 5.0.100-rc.2.20479.15
Commit: da7dfa8840
Runtime Environment:
OS Name: Windows
OS Version: 10.0.18362
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\5.0.100-rc.2.20479.15\
Host (useful for support):
Version: 5.0.0-rc.2.20475.5
Commit: c5a3f49c88
.NET SDKs installed:
2.1.804 [C:\Program Files\dotnet\sdk]
2.2.207 [C:\Program Files\dotnet\sdk]
3.1.101 [C:\Program Files\dotnet\sdk]
3.1.102 [C:\Program Files\dotnet\sdk]
5.0.100-rc.2.20479.15 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.0-rc.2.20475.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.0-rc.2.20475.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.0-rc.2.20475.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Could not load type 'Microsoft.AspNetCore.Components.Forms.ReadRequest' from assembly 'Microsoft.AspNetCore.Components.Web, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' because it contains an object field at offset 4 that is incorrectly aligned or overlapped by a non-object field.
CC: Blazor
@SteveSandersonMS do you happen what may cause this?
Yeah we'll probably have to fix this in 5.0.
There's a type in the .Web project that is only intended for use on WebAssembly, and it has a fixed struct layout that assumes 32-bit only. This isn't normally a problem because at runtime the type is never used if you're not on WebAssembly. However if you use reflection to walk over all the loaded types, you can attempt to load it on server code and hence trigger a type load exception (assuming server is 64-bit).
Fixing it is pretty trivial - we just change the struct to be safe for 64-bit runtimes too by aligning fields to 8-byte boundaries, like our other fixed-layout structs. I'll look into doing this.
@SteveSandersonMS thanks for investigation. I think that use reflection to walk over all the loaded types is common use case, especially when we use dependency injection.
@SteveSandersonMS I thought about this problem and one thing is not clear to me. Why the problem occurs only when I run this code from the test but when I run the application from the console it works correctly. In this case, I use reflection to go through all types and it doesn't cause an error.
The command:
dotnet run --project .\test.net5\test\test.csproj
Output:
Building...
Register
Hosting environment: Development
Content root path: C:\work\AspDotnet5Issue\test.net5\test
Now listening on: https://localhost:5001
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
this is roadblocking in creating migrations in a real project for me, is there any workaround?
I’d suggest considering updating to RTM packages from the .NET nightly build feed.
Most helpful comment
Yeah we'll probably have to fix this in 5.0.
There's a type in the
.Webproject that is only intended for use on WebAssembly, and it has a fixed struct layout that assumes 32-bit only. This isn't normally a problem because at runtime the type is never used if you're not on WebAssembly. However if you use reflection to walk over all the loaded types, you can attempt to load it on server code and hence trigger a type load exception (assuming server is 64-bit).Fixing it is pretty trivial - we just change the struct to be safe for 64-bit runtimes too by aligning fields to 8-byte boundaries, like our other fixed-layout structs. I'll look into doing this.