Retargeting Changes for Migration from .NET Framework 4.6.2 to 4.7

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.6.2 to 4.7, review the following topics for application compatibility issues that may affect your app:

Windows Communication Foundation (WCF)

Serialization of control characters with DataContractJsonSerializer is now compatible with ECMAScript V6 and V8

Details In the .NET framework 4.6.2 and earlier versions, the DataContractJsonSerializer did not serialize some special control characters, such as \b, \f, and \t, in a way that was compatible with the ECMAScript V6 and V8 standards. Starting with the .NET Framework 4.7, serialization of these control characters is compatible with ECMAScript V6 and V8.
Suggestion For apps that target the .NET Framework 4.7, this feature is enabled by default. If this behavior is not desirable, you can opt out of this feature by adding the following line to the <runtime> section of the app.config or web.config file:
<runtime>
<AppContextSwitchOverrides value="Switch.System.Runtime.Serialization.DoNotUseECMAScriptV6EscapeControlCharacter=false" />
</runtime>
Scope Edge
Version 4.7
Type Retargeting
Affected APIs

WCF message security now is able to use TLS1.1 and TLS1.2

Details Starting in the .NET Framework 4.7, customers can configure either TLS1.1 or TLS1.2 in WCF message security in addition to SSL3.0 and TLS1.0 through application configuration settings.
Suggestion In the .NET Framework 4.7, support for TLS1.1 and TLS1.2 in WCF message security is disabled by default. You can enable it by adding the following line to the <runtime> section of the app.config or web.config file:
<runtime>
<AppContextSwitchOverrides value="Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols=false;Switch.System.Net.DontEnableSchUseStrongCrypto=false" />
</runtime>
Scope Edge
Version 4.7
Type Retargeting

ASP.NET

HttpRuntime.AppDomainAppPath Throws a NullReferenceException

Details In the .NET Framework 4.6.2, the runtime throws a T:System.NullReferenceException when retrieving a P:System.Web.HttpRuntime.AppDomainAppPath value that includes null characters.In the .NET Framework 4.6.1 and earlier versions, the runtime throws an T:System.ArgumentNullException.
Suggestion You can do either of the follow to respond to this change:
  • Handle the T:System.NullReferenceException if you application is running on the .NET Framework 4.6.2.
  • Upgrade to the .NET Framework 4.7, which restores the previous behavior and throws an T:System.ArgumentNullException.
Scope Edge
Version 4.6.2
Type Retargeting
Affected APIs

Throttle concurrent requests per session

Details In the .NET Framework 4.6.2 and earlier, ASP.NET executes requests with the same Sessionid sequentially, and ASP.NET always issues the Sessionid through cookie by default. If a page takes a long time to respond, it will significantly degrade server performance just by pressing F5 on the browser. In the fix, we added a counter to track the queued requests and terminate the requests when they exceed a specified limit. The default value is 50. If the the limit is reached, a warning will be logged in the event log, and an HTTP 500 response may be recorded in the IIS log.
Suggestion To restore the old behavior, you can add the following setting to your web.config file to opt out of the new behavior.
<appSettings>
<add key="aspnet:RequestQueueLimitPerSession" value="2147483647"/>
</appSettings>
Scope Edge
Version 4.7
Type Retargeting

Networking

Default value of ServicePointManager.SecurityProtocol is SecurityProtocolType.System.Default

Details Starting with apps that target the .NET Framework 4.7, the default value of the ServicePointManager.SecurityProtocol property is SecurityProtocolType.SystemDefault. This change allows .NET Framework networking APIs based on SslStream (such as FTP, HTTPS, and SMTP) to inherit the default security protocols from the operating system instead of using hard-coded values defined by the .NET Framework. The default varies by operating system and any custom configuration performed by the system administrator. For information on the default SChannel protocol in each version of the Windows operating system, see Protocols in TLS/SSL (Schannel SSP).For applications that target an earlier version of the .NET Framework, the default value of the ServicePointManager.SecurityProtocol property depends on the version of the .NET Framework targeted. See Retargeting Changes in the .NET Framework 4.6 for more information.
Suggestion This change affects applications that target the .NET Framework 4.7 or later versions.If you prefer to use a defined protocol rather than relying on the system default, you can explicitly set the value of the ServicePointManager.SecurityProtocol property.
Scope Minor
Version 4.7
Type Retargeting
Affected APIs

SslStream supports TLS Alerts

Details After a failed TLS handshake, an IOException with an inner Win32Exception exception will be thrown by the first I/O Read/Write operation. The NativeErrorCode code for the Win32Exception can be mapped to the TLS Alert from the remote party using this Schannel documentation.For more information, see RFC 2246: Section 7.2.2 Error alertsThe behavior in .NET 4.6.2 and below is that the transport channel (usually TCP connection) will timeout during either Write or Read if the other party failed the handshake and immediately afterwards rejected the connection.
Suggestion Applications calling network I/O APIs such as Read(Byte[], Int32, Int32)/Write(Byte[], Int32, Int32) should handle IOException or TimeoutException.The TLS Alerts feature is enabled by default starting with .NET 4.7. Applications targeting .NET 4.0 - .NET 4.6.2 running on a .NET 4.7 or higher system will have the feature disabled to preserve compatibility.The following configuration API is available to enable or disable the feature for .NET 4.6 and above applications running on .NET 4.7 or higher framework.
  • Programmatically:
Must be the very first thing the application does since ServicePointManager will initialize only once:
AppContext.SetSwitch("TestSwitch.LocalAppContext.DisableCaching", true);
AppContext.SetSwitch("Switch.System.Net.DontEnableTlsAlerts", true); // Set to 'false' to enable the feature in .NET 4.6 - 4.6.2.
  • AppConfig:
<runtime>
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableTlsAlerts=true"/>
Scope Edge
Version 4.7
Type Retargeting
Affected APIs

Security

CspParameters.ParentWindowHandle now expects HWND value

Details The ParentWindowHandle value, introduced in .NET Framework 2.0, allows an application to register a parent window handle value such that any UI required to access the key (such as a PIN prompt or consent dialog) opens as a modal child to the specified window.Starting with apps that target the .NET Framework 4.7, a Windows Forms application can set the ParentWindowHandle property with code like the following:
cspParameters.ParentWindowHandle = form.Handle;
In previous versions of the .NET Framework, the value was expected to be an IntPtr representing a location in memory where the HWND value resided. Setting the property to form.Handle on Windows 7 and earlier versions had no effect, but on Windows 8 and later versions, it results in a "CryptographicException: The parameter is incorrect."
Suggestion Applications targeting .NET 4.7 or higher wishing to register a parent window relationship are encouraged to use the simplified form:
cspParameters.ParentWindowHandle = form.Handle;
Users who had identified that the correct value to pass was the address of a memory location which held the value form.Handle can opt out of the behavior change by setting the AppContext switch Switch.System.Security.Cryptography.DoNotAddrOfCspParentWindowHandle to true.
  • By programmatically setting compat switches on the AppContext, as explained here
  • By adding the following line to the <runtime> section of the app.config file:
<runtime>
<AppContextSwitchOverrides value="Switch.System.Security.Cryptography.DoNotAddrOfCspParentWindowHandle=true"/>
</runtime>
Conversely, users who wish to opt in to the new behavior on the .NET Framework 4.7 runtime when the application loads under older .NET Framework versions can set the AppContext switch to false.
Scope Minor
Version 4.7
Type Retargeting
Affected APIs

Windows Presentation Foundation (WPF)

Calls to System.Windows.Input.PenContext.Disable on touch-enabled systems may throw an ArgumentException

Details Under some circumstances, calls to the internal System.Windows.Intput.PenContext.Disable method on touch-enabled systems may throw an unhandled T:System.ArgumentException because of reentrancy.
Suggestion This issue has been addressed in the .NET Framework 4.7. To prevent the exception, upgrade to a version of the .NET Framework starting with the .NET Framework 4.7.
Scope Edge
Version 4.6.1
Type Retargeting

NullReferenceException in exception handling code from ImageSourceConverter.ConvertFrom

Details An error in the exception handling code for ConvertFrom(ITypeDescriptorContext, CultureInfo, Object) caused an incorrect NullReferenceException to be thrown instead of the intended exception (e.g. DirectoryNotFoundException, FileNotFoundException), this change corrects that error so that the method now throws the right exception.By default all applications targeting .NET Framework 4.6.2 and below will continue to throw NullReferenceException for compatibility, developers targeting .NET Framework 4.7 and above should see the right exceptions.// Replace the space with an 'x' if applicable
Suggestion Developers who wish to revert to getting NullReferenceException when targeting .NET Framework 4.7 can add/merge the following to their application's App.config file:
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.Windows.Media.ImageSourceConverter.OverrideExceptionWithNullReferenceException=true"/>
</runtime>
</configuration>
Scope Edge
Version 4.7
Type Retargeting
Affected APIs

WPF Grid allocation of space to star-columns

Details Starting with the .NET Framework 4.7, WPF replaces the algorithm that Grid uses to allocate space to *-columns. This will change the actual width assigned to *-columns in a number of cases:
  • When one or more *-columns also have a minimum or maximum width that overrides the proportional allocation for that colum. (The minimum width can derive from an explicit MinWidth declaration, or from an implicit minimum obtained from the column's content. The maximum width can only be defined explicitly, from a MaxWidth declaration.)
  • When one or more *-columns declare an extremely large *-weight, greater than 10^298.
  • When the *-weights are sufficiently different to encounter floating-point instability (overflow, underflow, loss of precision).
  • When layout rounding is enabled, and the effective display DPI is sufficiently high.
In the first two cases, the widths produced by the new algorithm can be significantly different from those produced by the old algorithm; in the last case, the difference will be at most one or two pixels.The new algorithm fixes several bugs present in the old algorithm:
  • Total allocation to columns can exceed the Grid's width. This can occur when allocating space to a column whose proportional share is less than its minimum size. The algorithm allocates the minimum size, which decreases the space available to other columns. If there are no *-columns left to allocate, the total allocation will be too large.
  • Total allocation can fall short of the Grid's width. This is the dual problem to #1, arising when allocating to a column whose proportional share is greater than its maximum size, with no *-columns left to take up the slack.
  • Two *-columns can receive allocations not proportional to their *-weights. This is a milder version of #1/#2, arising when allocating to *-columns A, B, and C (in that order), where B's proportional share violates its min (or max) constraint. As above, this changes the space available to column C, who gets less (or more) proportional allocation than A did,
  • Columns with extremely large weights (> 10^298) are all treated as if they had weight 10^298. Proportional differences between them (and between columns with slightly smaller weights) are not honored.
  • Columns with inifinte weights are not handled correctly. [Actually you can't set a weight to Infinity, but this is an artificial restriction. The allocation code was trying to handle it, but doing a bad job.]
  • Several minor problems while avoiding overflow, underflow, loss of precision and similar floating-point issues.
  • Adjustments for layout rounding are incorrect at sufficiently high DPI.
The new algorithm produces results that meet the following criteria:A. The actual width assigned to a *-column is never less than its minimum width nor greater than its maximum width.B. Each -column that is not assigned its minimum or maximum width is assigned a width proportional to its -weight. To be precise, if two columns are declared with width x and y respectively, and if neither column receives its minimum or maximum width, the actual widths v and w assigned to the columns are in the same proportion: v / w == x / y.C. The total width allocated to "proportional" *-columns is equal to the space available after allocating to the constrained columns (fixed, auto, and *-columns that are allocated their min or max width). This might be zero, for instance if the sum of the minimum widths exceeds the Grid's availbable width.D. All these statements are to be interpreted with respect to the "ideal" layout. When layout rounding is in effect, the actual widths can differ from the ideal widths by as much as one pixel.The old algorithm honored (A) but failed to honor the other criteria in the cases outlined above.Everything said about columns and widths in this article applies as well to rows and heights.
Suggestion By default, apps that target versions of the .NET Framework starting with the .NET Framework 4.7 will see the new algorithm, while apps that target the .NET Framework 4.6.2 or earlier versions will see the old algorithm.To override the default, use the following configuration setting:
<runtime>
<AppContextSwitchOverrides value="Switch.System.Windows.Controls.Grid.StarDefinitionsCanExceedAvailableSpace=true" />
</runtime>
The value 'true' selects the old algorithm, 'false' selects the new algorithm.
Scope Minor
Version 4.7
Type Retargeting

WPF Pointer-Based Touch Stack

Details This change adds the ability to enable an optional WM_POINTER based WPF touch/stylus stack. Developers that do not explicitly enable this should see no change in WPF touch/stylus behavior.Current Known Issues With optional WM_POINTER based touch/stylus stack:
  • No support for real-time inking.
  • While inking and StylusPlugins will still work, they will be processed on the UI Thread which can lead to poor performance.
  • Behavioral changes due to changes in promotion from touch/stylus events to mouse events
  • Manipulation may behave differently
  • Drag/Drop will not show appropriate feedback for touch input
  • This does not affect stylus input
  • Drag/Drop can no longer be initiated on touch/stylus events
  • This can potentially hang the application until mouse input is detected.
  • Instead, developers should initiate drag and drop from mouse events.
Suggestion Developers who wish to enable this stack can add/merge the following to their application's App.config file:
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.Windows.Input.Stylus.EnablePointerSupport=true"/>
</runtime>
</configuration>
Removing this or setting the value to false will turn this optional stack off.Please note that this stack is available only on Windows 10 Creators Update and above.
Scope Edge
Version 4.7
Type Retargeting

Windows Workflow Foundation (WF)

Workflow checksums changed from MD5 to SHA1

Details To support debugging with Visual Studio, the Workflow runtime generates a checksum for a workflow instance using a hashing algorithm. In the .NET Framework 4.6.2 and earlier versions, workflow checksum hashing used the MD5 algorithm, which caused issues on FIPS-enabled systems. Starting with the .NET Framework 4.7, the algorithm is SHA1. If your code has persisted these checksums, they will be incompatible.
Suggestion If your code is unable to load workflow instances due to a checksum failure, try setting the AppContext switch "Switch.System.Activities.UseMD5ForWFDebugger" to true.In code:
System.AppContext.SetSwitch("Switch.System.Activities.UseMD5ForWFDebugger", true);
Or in configuration:
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.Activities.UseMD5ForWFDebugger=true" />
</runtime>
</configuration>
Scope Minor
Version 4.7
Type Retargeting