Retargeting Changes for Migration from .NET Framework 4.5.2 to 4.6

Introduction

Retargeting changes affect apps that are recompiled to target a different .NET Framework. They include:

  • Changes in the design-time environment. For example, build tools may emit warnings when previously they did not.

  • Changes in the runtime environment. These affect only apps that specifically target the retargeted .NET Framework. Apps that target previous versions of the .NET Framework behave as they did when running under those versions.

In the topics that describe retargeting changes, we have classified individual items by their expected impact, as follows:

Major This is a significant change that affects a large number of apps or that requires substantial modification of code.

Minor This is a change that affects a small number of apps or that requires minor modification of code.

Edge case This is a change that affects apps under very specific scenarios that are not common.

Transparent This is a change that has no noticeable effect on the app's developer or user. The app should not require modification because of this change.

If you are migrating from the .NET Framework 4.5.2 to 4.6, review the following topics for application compatibility issues that may affect your app:

ASP.NET

HtmlTextWriter does not render <br/> element correctly

Details Beginning in the .NET Framework 4.6, calling RenderBeginTag(String) and RenderEndTag() with a <BR /> element will correctly insert only one <BR /> (instead of two)
Suggestion If an app depended on the extra <BR /> tag, RenderBeginTag(String) should be called a second time. Note that this behavior change only affects apps that target the .NET Framework 4.6 or later, so another option is to target a previous version of the .NET Framework in order to get the old behavior.
Scope Edge
Version 4.6
Type Retargeting
Affected APIs

ClickOnce

Apps published with ClickOnce that use a SHA-256 code-signing certificate may fail on Windows 2003

Details The executable is signed with SHA256. Previously, it was signed with SHA1 regardless of whether the code-signing certificate was SHA-1 or SHA-256. This applies to:
  • All applications built with Visual Studio 2012 or later.
  • Applications built with Visual Studio 2010 or earlier on systems with the .NET Framework 4.5 present.
In addition, if the .NET Framework 4.5 or later is present, the ClickOnce manifest is also signed with SHA-256 for SHA-256 certificates regardless of the .NET Framework version against which it was compiled.
Suggestion The change in signing the ClickOnce executable affects only Windows Server 2003 systems; they require that KB 938397 be installed.The change in signing the manifest with SHA-256 even when an app targets the .NET Framework 4.0 or earlier versions introduces a runtime dependency on the .NET Framework 4.5 or a later version.
Scope Edge
Version 4.5
Type Retargeting

ClickOnce supports SHA-256 on 4.0-targeted apps

Details Previously, a ClickOnce app with a certificate signed with SHA-256 would require .NET Framework 4.5 or later to be present, even if the app targeted 4.0. Now, .NET Framework 4.0-targeted ClickOnce apps can run on .NET Framework 4.0, even if signed with SHA-256.
Suggestion This change removes that dependency and allows SHA-256 certificates to be used to sign ClickOnce apps that target .NET Framework 4 and earlier versions.
Scope Minor
Version 4.6
Type Retargeting

Core

CurrentCulture and CurrentUICulture flow across tasks

Details Beginning in the .NET Framework 4.6, CurrentCulture and CurrentUICulture are stored in the thread's ExecutionContext, which flows across asynchronous operations.This means that changes to CurrentCulture or CurrentUICulture will be reflected in tasks which are later run asynchronously. This is different from the behavior of previous .NET Framework versions (which would reset CurrentCulture and CurrentUICulture in all asynchronous tasks).
Suggestion Apps affected by this change may work around it by explicitly setting the desired CurrentCulture or CurrentUICulture as the first operation in an async Task. Alternatively, the old behavior (of not flowing CurrentCulture/CurrentUICulture) may be opted into by setting the following compatibility switch:
AppContext.SetSwitch("Switch.System.Globalization.NoAsyncCurrentCulture", true);
This issue has been fixed by WPF in .NET Framework 4.6.2. It has also been fixed in .NET Frameworks 4.6, 4.6.1 through KB 3139549. Applications targeting .NET Framework 4.6 or later will automatically get the right behavior in WPF applications - CurrentCulture/CurrentUICulture) would be preserved across Dispatcher operations.
Scope Minor
Version 4.6
Type Retargeting
Affected APIs

ETW event names cannot differ only by a "Start" or "Stop" suffix

Details In the .NET Framework 4.6 and 4.6.1, the runtime throws an ArgumentException when two Event Tracing for Windows (ETW) event names differ only by a "Start" or "Stop" suffix (as when one event is named LogUser and another is named LogUserStart). In this case, the runtime cannot construct the event source, which cannot emit any logging.
Suggestion To prevent the exception, ensure that no two event names differ only by a "Start" or "Stop" suffix.This requirement is removed starting with the .NET Framework 4.6.2; the runtime can disambiguate event names that differ only by the "Start" and "Stop" suffix.
Scope Edge
Version 4.6
Type Retargeting

Entity Framework

Building an Entity Framework edmx with Visual Studio 2013 can fail with error MSB4062 if using the EntityDeploySplit or EntityClean tasks

Details MSBuild 12.0 tools (included in Visual Studio 2013) changed MSBuild file locations, causing older Entity Framework targets files to be invalid. The result is that EntityDeploySplit and EntityClean tasks fail because they are unable to find Microsoft.Data.Entity.Build.Tasks.dll. Note that this break is because of a toolset (MSBuild/VS) change, not because of a .NET Framework change. It will only occur when upgrading developer tools, not when merely upgrading the .NET Framework.
Suggestion Entity Framework targets files are fixed to work with the new MSBuild layout beginning in the .NET Framework 4.6. Upgrading to that version of the Framework will fix this issue. Alternatively, this workaround can be used to patch the targets files directly.
Scope Major
Version 4.5.1
Type Retargeting

JIT

IL ret not allowed in a try region

Details Unlike the JIT64 just-in-time compiler, RyuJIT (used in .NET Framework 4.6) does not allow an IL ret instruction in a try region. Returning from a try region is disallowed by the ECMA-335 specification, and no known managed compiler generates such IL. However, the JIT64 compiler will execute such IL if it is generated using reflection emit.
Suggestion If an app is generating IL that includes a ret opcode in a try region, the app may target .NET Framework 4.5 to use the old JIT and avoid this break. Alternatively, the generated IL may be updated to return after the try region.
Scope Edge
Version 4.6
Type Retargeting

New 64-bit JIT compiler in the .NET Framework 4.6

Details Starting with the .NET Framework 4.6, a new 64-bit JIT compiler is used for just-in-time compilation. In some cases, an unexpected exception is thrown or a different behavior is observed than if an app is run using the 32-bit compiler or the older 64-bit JIT compiler. This change does not affect the 32-bit JIT compiler.The known differences include the following:
  • Under certain conditions, an unboxing operation may throw a NullReferenceException in Release builds with optimization turned on.
  • In some cases, execution of production code in a large method body may throw a StackOverflowException.
  • Under certain conditions, structures passed to a method are treated as reference types rather than as value types in Release builds. One of the manifestations of this issue is that the individual items in a collection appear in an unexpected order.
  • Under certain conditions, the comparison of UInt16 values with their high bit set is incorrect if optimization is enabled.
  • Under certain conditions, particularly when initializing array values, memory initialization by the OpCodes.Initblk IL instruction may initialize memory with an incorrect value. This can result either in an unhandled exception or incorrect output.
  • Under certain rare conditions, a conditional bit test can return the incorrect Boolean value or throw an exception if compiler optimizations are enabled.
  • Under certain conditions, if an if statement is used to test for a condition before entering a try block and in the exit from the try block, and the same condition is evaluated in the catch or finally block, the new 64-bit JIT compiler removes the if condition from the catch or finally block when it optimizes code. As a result, code inside the if statement in the catch or finally block is executed unconditionally.
Suggestion Mitigation of known issues
If you encounter the issues listed above, you can address them by doing any of the following:
  • Upgrade to the .NET Framework 4.6.2. The new 64-bit compiler included with the .NET Framework 4.6.2 addresses each of these known issues.
  • Ensure that your version of Windows is up to date by running Windows Update. Service updates to the .NET Framework 4.6 and 4.6.1 address each of these issues except the NullReferenceException in an unboxing operation.
  • Compile with the older 64-bit JIT compiler. See the Mitigation of other issues section for more information on how to do this.
Mitigation of other issues
If you encounter any other difference in behavior between code compiled with the older 64-bit compiler and the new 64-bit JIT compiler, or between the debug and release versions of your app that are both compiled with the new 64-bit JIT compiler, you can do the following to compile your app with the older 64-bit JIT compiler:
  • On a per-application basis, you can add the < element to your application's configuration file. The following disables compilation with the new 64-bit JIT compiler and instead uses the legacy 64-bit JIT compiler.
<?xml version ="1.0"?>
<configuration>
<runtime>
<useLegacyJit enabled="1" />
</runtime>
</configuration>
  • On a per-user basis, you can add a REG_DWORD value named useLegacyJit to the HKEY_CURRENT_USER\SOFTWARE\Microsoft.NETFramework key of the registry. A value of 1 enables the legacy 64-bit JIT compiler; a value of 0 disables it and enables the new 64-bit JIT compiler.
  • On a per-machine basis, you can add a REG_DWORD value named useLegacyJit to the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework key of the registry. A value of 1 enables the legacy 64-bit JIT compiler; a value of 0 disables it and enables the new 64-bit JIT compiler.
You can also let us know about the problem by reporting a bug on Microsoft Connect.
Scope Edge
Version 4.6
Type Retargeting

Networking

Certificate EKU OID validation

Details Starting with .NET Framework 4.6, the SslStream or ServicePointManager classes perform enhanced key use (EKU) object identifier (OID) validation. An enhanced key usage (EKU) extension is a collection of object identifiers (OIDs) that indicate the applications that use the key. EKU OID validation uses remote certificate callbacks to ensure that the remote certificate has the correct OIDs for the intended purpose.
Suggestion If this change is undesirable, you can disable certificate EKU OID validation by adding the following switch to the <AppContextSwitchOverrides> in the ` of your app configuration file:
<runtime>
<AppContextSwitchOverrides
value="Switch.System.Net.DontCheckCertificateEKUs=true" />
</runtime>
[!IMPORTANT] This setting is provided for backward compatibility only. Its use is otherwise not recommended.
Scope Minor
Version 4.6
Type Retargeting
Affected APIs

Only Tls 1.0, 1.1 and 1.2 protocols supported in System.Net.ServicePointManager and System.Net.Security.SslStream

Details Starting with the .NET Framework 4.6, the ServicePointManager and SslStream classes are only allowed to use one of the following three protocols: Tls1.0, Tls1.1, or Tls1.2. The SSL3.0 protocol and RC4 cipher are not supported.
Suggestion The recommended mitigation is to upgrade the sever-side app to Tls1.0, Tls1.1, or Tls1.2. If this is not feasible, or if client apps are broken, the AppContext class can be used to opt out of this feature in either of two ways:
  1. By programmatically setting compat switches on the AppContext, as explained here
  2. By adding the following line to the <runtime> section of the app.config file: <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=true"/>;
Scope Minor
Version 4.6
Type Retargeting
Affected APIs

TLS 1.x by default passes the SCH_SEND_AUX_RECORD flag to the underlying SCHANNEL API

Details When using TLS 1.x, the .NET Framework relies on the underlying Windows SCHANNEL API. Starting with .NET Framework 4.6, the SCH_SEND_AUX_RECORD flag is passed by default to SCHANNEL. This causes SCHANNEL to split data to be encrypted into two separate records, the first as a single byte and the second as n-1 bytes.In rare cases, this breaks communication between clients and existing servers that make the assumption that the data resides in a single record.
Suggestion If this change breaks communication with an existing server, you can disable sending the SCH_SEND_AUX_RECORD flag and restore the previous behavior of not splitting data into separate records by adding the following switch to the element in the section of your app configuration file:
<runtime>
<AppContextSwitchOverrides
value="Switch.System.Net.DontEnableSchSendAuxRecord=true" />
</runtime>
[!IMPORTANT] This setting is provided for backward compatibility only. Its use is otherwise not recommended.
Scope Edge
Version 4.6
Type Retargeting
Affected APIs

Windows Communication Foundation (WCF)

Calling CreateDefaultAuthorizationContext with a null argument has changed

Details The implementation of the AuthorizationContext returned by a call to the CreateDefaultAuthorizationContext(IList<IAuthorizationPolicy>) with a null authorizationPolicies argument has changed its implementation in the .NET Framework 4.6.
Suggestion In rare cases, WCF apps that use custom authentication may see behavioral differences. In such cases, the previous behavior can be restored in either of two ways:
  1. Recompile your app to target an earlier version of the .NET Framework than 4.6. For IIS-hosted services, use the <httpRuntime targetFramework="x.x" /> element to target an earlier version of the .NET Framework.
  2. Add the following line to the <appSettings> section of your app.config file: <add key="appContext.SetSwitch:Switch.System.IdentityModel.EnableCachedEmptyDefaultAuthorizationContext" value="true" />
Scope Minor
Version 4.6
Type Retargeting
Affected APIs

Windows Forms

Icon.ToBitmap successfully converts icons with PNG frames into Bitmap objects

Details Starting with the apps that target the .NET Framework 4.6, the Icon.ToBitmap method successfully converts icons with PNG frames into Bitmap objects.

In apps that target the .NET Framework 4.5.2 and earlier versions, the Icon.ToBitmap method throws an ArgumentOutOfRangeException exception if the Icon object has PNG frames.

This change affects apps that are recompiled to target the .NET Framework 4.6 and that implement special handling for the ArgumentOutOfRangeException that is thrown when an Icon object has PNG frames. When running under the .NET Framework 4.6, the conversion is successful, an ArgumentOutOfRangeException is no longer thrown, and therefore the exception handler is no longer invoked.

Suggestion If this behavior is undesirable, you can retain the previous behavior by adding the following element to the <runtime> section of your app.config file:
<AppContextSwitchOverrides
value="Switch.System.Drawing.DontSupportPngFramesInIcons=true" />
If the app.config file already contains the AppContextSwitchOverrides element, the new value should be merged with the value attribute like this:
<AppContextSwitchOverrides
value="Switch.System.Drawing.DontSupportPngFramesInIcons=true;<previous key>=<previous value>" />
Scope Minor
Version 4.6
Type Retargeting
Affected APIs

Windows Presentation Foundation (WPF)

CurrentCulture is not preserved across WPF Dispatcher operations

Details Beginning in the .NET Framework 4.6, changes to CurrentCulture or CurrentUICulture made within a Dispatcher will be lost at the end of that dispatcher operation. Similarly, changes to CurrentCulture or CurrentUICulture made outside of a Dispatcher operation may not be reflected when that operation executes.Practically speaking, this means that CurrentCulture and CurrentUICulture changes may not flow between WPF UI callbacks and other code in a WPF application.This is due to a change in ExecutionContext that causes CurrentCulture and CurrentUICulture to be stored in the execution context beginning with apps targeting the .NET Framework 4.6. WPF dispatcher operations store the execution context used to begin the operation and restore the previous context when the operation is completed. Because CurrentCulture and CurrentUICulture are now part of that context, changes to them within a dispatcher operation are not persisted outside of the operation.
Suggestion Apps affected by this change may work around it by storing the desired CurrentCulture or CurrentUICulture in a field and checking in all Dispatcher operation bodies (including UI event callback handlers) that the correct CurrentCulture and CurrentUICulture are set. Alternatively, because the ExecutionContext change underlying this WPF change only affects apps targeting the .NET Framework 4.6 or newer, this break can be avoided by targeting the .NET Framework 4.5.2.Apps that target .NET Framework 4.6 or later can also work around this by setting the following compatibility switch:
AppContext.SetSwitch("Switch.System.Globalization.NoAsyncCurrentCulture", true);
This issue has been fixed by WPF in .NET Framework 4.6.2. It has also been fixed in .NET Frameworks 4.6, 4.6.1 through KB 3139549. Applications targeting .NET Framework 4.6 or later will automatically get the right behavior in WPF applications - CurrentCulture/CurrentUICulture) would be preserved across Dispatcher operations.
Scope Minor
Version 4.6
Type Retargeting

WPF layout rounding of margins has changed

Details The way in which margins are rounded and borders and the background inside of them has changed. As a result of this change:
  • The width or height of elements may grow or shrink by at most one pixel.
  • The placement of an object can move by at most one pixel.
  • Centered elements can be vertically or horizontally off center by at most one pixel.
By default, this new layout is enabled only for apps that target the .NET Framework 4.6.
Suggestion Since this modification tends to eliminate clipping of the right or bottom of WPF controls at high DPIs, apps that target earlier versions of the .NET Framework but are running on the .NET Framework 4.6 can opt into this new behavior by adding the following line to the <runtime> section of the app.config file:
<AppContextSwitchOverrides value="Switch.MS.Internal.DoNotApplyLayoutRoundingToMarginsAndBorderThickness=false" />'
Apps that target the .NET Framework 4.6 but want WPF controls to render using the previous layout algorithm can do so by adding the following line to the <runtime> section of the app.config file:
<AppContextSwitchOverrides value="Switch.MS.Internal.DoNotApplyLayoutRoundingToMarginsAndBorderThickness=true" />'.
Scope Minor
Version 4.6
Type Retargeting

XML, XSLT

XmlWriter throws on invalid surrogate pairs

Details For apps that target the .NET Framework 4.5.2 or previous versions, writing an invalid surrogate pair using exception fallback handling does not always throw an exception. For apps that target the .NET Framework 4.6, attempting to write an invalid surrogate pair throws an ArgumentException.
Suggestion If necessary, this break can be avoided by targeting the .NET Framework 4.5.2 or earlier. Alternatively, invalid surrogate pairs can be pre-processed into valid xml prior to writing them.
Scope Edge
Version 4.6
Type Retargeting
Affected APIs

XSD Schema validation now correctly detects violations of unique constraints if compound keys are used and one key is empty

Details Versions of the .NET Framework prior to 4.6 had a bug that caused XSD validation to not detect unique constraints on compound keys if one of the keys was empty. In the .NET Framework 4.6, this issue is corrected. This will result in more correct validation, but it may also result in some XML not validating which previously would have.
Suggestion If looser .NET Framework 4.0 validation is needed, the validating application can target version 4.5 (or earlier) of the .NET Framework. When retargeting to .NET Framework 4.6, however, code review should be done to be sure that duplicate compound keys (as described in this issue's description) are not expected to validate.
Scope Edge
Version 4.6
Type Retargeting