Overview
I have an application running as a Windows service on Windows Server 2019. My application references a number of nuget packages, particularly including:
Microsoft.SharePoint.Client
Microsoft.SharePoint.Client.Runtime
The nuget versions are both 16.1.23311.12000
(the latest stable as of a couple days ago).
When running the application, I always end up getting this error:
InvalidCastException - Message: [A]Microsoft.SharePoint.Client.FieldUserValue cannot be cast to [B]Microsoft.SharePoint.Client.FieldUserValue. Type A originates from 'Microsoft.SharePoint.Client, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' in the context 'Default' at location 'path\to\my\program\Microsoft.SharePoint.Client.dll'. Type B originates from 'Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' in the context 'Default' at location 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.SharePoint.Client\v4.0_16.0.0.0__71e9bce111e9429c\Microsoft.SharePoint.Client.dll'.
Attempts
1 - Binding Redirect
At first I thought I just needed to do a binding redirect in my app.config
, so I have tried this:
App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.SharePoint.Client.Runtime" />
<bindingRedirect oldVersion="0.0.0.0-16.1.23311.12000" newVersion="16.1.23311.12000"/>
</dependentAssembly>
</assemblyBinding>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.SharePoint.Client" />
<bindingRedirect oldVersion="0.0.0.0-16.1.23311.12000" newVersion="16.1.23311.12000"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
... stuff in here ...
</entityFramework>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<connectionStrings>
... stuff in here ...
</connectionStrings>
</configuration>
Same error after stopping and restarting the Windows Service that runs this app.
2 - Other attempts from SO question
Other things I've tried from this question (Assembly binding redirect does not work):
- Moved binding as close to the top as possible, from a comment on this answer. This caused the service to fail to start.
- Verified the expected assembly version was in my application's root directory.
- Verified the built MyProgram.exe.config file was in my application's root directory.
- Tried including
culture="neutral"
from this answer.
Same error.
3 - Fusion Log Viewer
Then I configured Fusion Log viewer according to this tutorial. After restarting the service again, I noticed two binding attempts for both assemblies (see screenshot):
Some initial questions:
- Why would my application (or any application) try to bind to the same assembly twice?
- Why would my application attempt to bind to the assembly late (notice it's 4 seconds after the initial binding)?
And here are the respective logs of each of the four bindings:
Microsoft.SharePoint.Client.Runtime, Version 16.1.0.0...
**GOOD: **Redirect found in application configuration file, exactly as expected.
*** Assembly Binder Log Entry (2/20/2023 @ 11:11:00 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable path\to\my\program\MyProgram.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Microsoft.SharePoint.Client.Runtime, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
(Fully-specified)
LOG: Appbase = file:///path/to/my/program/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProgram.exe
Calling assembly : Microsoft.SharePoint.Client, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: path\to\my\program\MyProgram.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Redirect found in application configuration file: 16.1.0.0 redirected to 16.1.0.0.
LOG: Post-policy reference: Microsoft.SharePoint.Client.Runtime, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///path/to/my/program/Microsoft.SharePoint.Client.Runtime.DLL.
LOG: Assembly download was successful. Attempting setup of file: path\to\my\program\Microsoft.SharePoint.Client.Runtime.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Microsoft.SharePoint.Client.Runtime, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
LOG: Binding succeeds. Returns assembly from path\to\my\program\Microsoft.SharePoint.Client.Runtime.dll.
LOG: Assembly is loaded in default load context.
Microsoft.SharePoint.Client.Runtime, version 16.0.0.0
GOOD: Redirect found in application configuration file, exactly as expected.
*** Assembly Binder Log Entry (2/20/2023 @ 11:12:01 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable path\to\my\program\MyProgram.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Microsoft.SharePoint.Client.Runtime, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
(Fully-specified)
LOG: Appbase = file:///path/to/my/program/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProgram.exe
Calling assembly : Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: path\to\my\program\MyProgram.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Redirect found in application configuration file: 16.0.0.0 redirected to 16.1.0.0.
LOG: Post-policy reference: Microsoft.SharePoint.Client.Runtime, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
LOG: Binding succeeds. Returns assembly from path\to\my\program\Microsoft.SharePoint.Client.Runtime.dll.
LOG: Assembly is loaded in default load context.
Microsoft.SharePoint.Client, versino 16.1.0.0
GOOD: Uses the local assembly version since it couldn't find another in the GAC **BAD: **Why didn't it use the assembly binding redirect from the application configuration file?
*** Assembly Binder Log Entry (2/20/2023 @ 11:11:00 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable path\to\my\program\MyProgram.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Microsoft.SharePoint.Client, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
(Fully-specified)
LOG: Appbase = file:///path/to/my/program/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProgram.exe
Calling assembly : CRS.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: path\to\my\program\MyProgram.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Microsoft.SharePoint.Client, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///path/to/my/program/Microsoft.SharePoint.Client.DLL.
LOG: Assembly download was successful. Attempting setup of file: path\to\my\program\Microsoft.SharePoint.Client.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Microsoft.SharePoint.Client, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
LOG: Binding succeeds. Returns assembly from path\to\my\program\Microsoft.SharePoint.Client.dll.
LOG: Assembly is loaded in default load context.
Microsoft.SharePoint.Client, version 16.0.0.0
**BAD: **Doesn't use the redirect defined in the application configuration file **BAD: **Loads the wrong version from the GAC
*** Assembly Binder Log Entry (2/20/2023 @ 11:12:01 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable path\to\my\program\MyProgram.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
(Fully-specified)
LOG: Appbase = file:///path/to/my/program/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProgram.exe
Calling assembly : Microsoft.SharePoint.Client.Runtime, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: path\to\my\program\MyProgram.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
LOG: Found assembly by looking in the GAC.
LOG: Binding succeeds. Returns assembly from C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.SharePoint.Client\v4.0_16.0.0.0__71e9bce111e9429c\Microsoft.SharePoint.Client.dll.
LOG: Assembly is loaded in default load context.
WRN: Multiple versions of the same assembly were loaded into one context of an application domain:
WRN: Context: Default | Domain ID: 1 | Assembly Name: Microsoft.SharePoint.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
WRN: Context: Default | Domain ID: 1 | Assembly Name: Microsoft.SharePoint.Client, Version=16.1.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
WRN: This might lead to runtime failures.
WRN: It is recommended that you remove the dependency on multiple versions, and change the app.config file to point to the required version of the assembly only.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information.
Summary
- Any thoughts?
- Where else can I check for things that could be causing this?
- Why doesn't the redirect work for
Microsoft.SharePoint.Client
but it does forMicrosoft.SharePoint.Client.Runtime v16.1.0.0
? - Why doesn't the redirect work for
Microsoft.SharePoint.Client.Runtime v16.0.0.0
?