runtime: ASP.NET MVC 2.0 apps don't work on 2.1 runtime

Repro Steps

  1. dotnet new mvc. Make sure your app targets netcoreapp2.0.
  2. dotnet build
  3. Install the latest shared framework somewhere. I installed 2.1.0-preview1-25714-02
  4. /path/to/dotnet --fx-version 2.1.0-preview1-25714-02 bin\Debug\netcoreapp2.0\RollForwardTest.dll

Expected results

The app should run successfully

Actual results

An error is thrown:

fail: Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider[48]
      An error occurred while reading the key ring.
System.IO.FileLoadException: Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at System.SpanHelpers.IndexOf[T](T& searchSpace, T value, Int32 length)
   at System.SpanExtensions.IndexOf[T](ReadOnlySpan`1 span, T value)
   at System.FixedBufferExtensions.GetFixedBufferStringLength(ReadOnlySpan`1 span)
   at System.FixedBufferExtensions.GetStringFromFixedBuffer(ReadOnlySpan`1 span)
   at System.IO.SearchResultHandler.FileSystemInfoResultHandler.IsResultIncluded(String fullPath, String userPath, WIN32_FIND_DATA& findData, FileSystemInfo& result)
   at System.IO.Win32FileSystemEnumerableIterator`1.IsResultIncluded(WIN32_FIND_DATA& findData, TSource& result)
   at System.IO.Win32FileSystemEnumerableIterator`1.CommonInit()
   at System.IO.Win32FileSystemEnumerableIterator`1..ctor(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler`1 resultHandler)
   at System.IO.Win32FileSystem.EnumerateFileSystemInfos(String fullPath, String searchPattern, SearchOption searchOption, SearchTarget searchTarget)
   at System.IO.DirectoryInfo.EnumerateFileSystemInfos(String searchPattern, SearchOption searchOption)
   at Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.<GetAllElementsCore>d__11.MoveNext()
   at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository.GetAllElements()
   at Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetAllKeys()
   at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.CreateCacheableKeyRingCore(DateTimeOffset now, IKey keyJustAdded)
   at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider.GetCacheableKeyRing(DateTimeOffset now)
   at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingProvider.GetCurrentKeyRingCore(DateTime utcNow)

Notes

See related issue https://github.com/dotnet/corefx/issues/23988 for why this error is being thrown.

We will need to address this issue in the context of when 2.0 apps are run on 2.1 runtime.

/cc @Petermarcu @ericstj @weshaggard

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 49 (47 by maintainers)

Most upvoted comments

I verified success with latest 2.1 preview:

D:\git\repros\mvc2>more bin\Debug\netcoreapp2.0\mvc2.runtimeconfig.json
{
  "runtimeOptions": {
    "tfm": "netcoreapp2.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "2.0.0"
    },
    "configProperties": {
      "System.GC.Server": true
    }
  }
}

D:\git\repros\mvc2>dotnet --fx-version 2.1.0-preview1-26019-03 bin\Debug\netcoreapp2.0\mvc2.dll
Hosting environment: Production
Content root path: D:\git\repros\mvc2
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Also tested this scenario with auto roll-forward from 2.0 to 2.1 when 2.0 is not installed (with new roll-forward policy changes via https://github.com/dotnet/core-setup/issues/3469)

D:\git\repros\mvc2>dotnet --list-runtimes
Microsoft.NETCore.App 2.1.0-preview1-26019-03 [C:\Program Files\dotnet\shared]

D:\git\repros\mvc2>dotnet bin\Debug\netcoreapp2.0\mvc2.dll
Hosting environment: Production
Content root path: D:\git\repros\mvc2
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

Snippet from COREHOST_TRACE=1:

--- Resolving FX directory, name 'Microsoft.NETCore.App' version '2.0.0'
Searching FX directory in [C:\Program Files\dotnet]
Attempting FX roll forward starting from [2.0.0]
'Roll forward on no candidate fx' enabled with value [1]. Looking for the least production greater than or equal to [2.0.0]
No production greater than or equal to [2.0.0] found. Looking for the least preview greater than [2.0.0]
Found version [2.1.0-preview1-26019-03]
Applying patch roll forward from [2.1.0-preview1-26019-03]
Inspecting version... [2.1.0-preview1-26019-03]
Changing Selected FX version from [] to [C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.0-preview1-26019-03]
Chose FX version [C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.0-preview1-26019-03]

The API do not have to be identical - the public S.R.CS.Unsafe can have extra APIs. You just need to add the ones that System.Memory needs.

Yes remove the IsNETCoreApp/IsUAP properties and remove the netcoreapp build configurations. Also remove the TreatAsOutOfBox suppression once those other properties are removed.

used in some tests

The tests should still depend on the public S.R.CS.Unsafe.

@eerhardt @jkotas here’s our offline meeting notes.

We discussed three classes of scenarios and approaches to each.

The three scenarios:

  1. Framework should win. This is the current scenario as described in this issue’s repro steps (assembly added to framework package is newer than the app’s)
  2. App should win. The app wants to bring in a newer OOB assembly like System.Collections.Immutable
  3. Unknown who should win. The app has locally build framework assemblies or assembly references (not package references) but a roll-forward to a newer framework has occurred.

The proposed solutions to each:

  1. Add new metadata to the framework’s deps.json to include the package version so we can make decisions on which is the newer version that we should use (details TBD, but could be as simple as including the versions of some of the decomposed packages that we previously only shipped OOB, such as System.Runtime.CompilerServices.Unsafe)
  2. App local wins (like today)
  3. App local wins (like today). The app should be re-targeted to the newer framework version, or the older framework should be installed (the one the app targeted).

Note that scenario (2) could change into scenario (1) when the OOB assembly becomes older than the current framework’s assembly during a roll-forward scenario.