Aspnetcore: Dotnet test error during creating TestServer after updating to .NET 5 RC2

Created on 14 Oct 2020  ·  8Comments  ·  Source: dotnet/aspnetcore

Describe the bug

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:

  • run the same test from Resharper or Rider the test passed.
  • the same code from the Web application.

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.

To Reproduce

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);
        }

Exceptions

  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 ---

Further technical details

  • ASP.NET Core version
    from sdk 5.0.100-rc.2.20479.15
  • Include the output of 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]
  • The IDE (VS / VS Code/ VS4Mac) you're running on, and it's version
    Dotnet CLI - 5.0.100-rc.2.20479.15
    Resharper 2020.2.4 (doesn't required to reproduce exception)
    VisualStudio 2019 Preview 16.8.0 Preview 4.0 (doesn't required to reproduce exception)
Done area-blazor bug

Most helpful comment

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.

All 8 comments

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.

Was this page helpful?
0 / 5 - 0 ratings