Retargeting Changes for Migration from .NET Framework 4.0 to 4.6.1
- (4.0 | 4.5)
- (4.0 | 4.5.1)
- (4.0 | 4.5.2)
- (4.0 | 4.6)
- (4.0 | 4.6.1)
- (4.0 | 4.6.2)
- (4.0 | 4.7)
- (4.0 | 4.7.1)
- (4.0 | 4.7.2)
- (4.0 | 4.8)
- (4.5 | 4.5.1)
- (4.5 | 4.5.2)
- (4.5 | 4.6)
- (4.5 | 4.6.1)
- (4.5 | 4.6.2)
- (4.5 | 4.7)
- (4.5 | 4.7.1)
- (4.5 | 4.7.2)
- (4.5 | 4.8)
- (4.5.1 | 4.5.2)
- (4.5.1 | 4.6)
- (4.5.1 | 4.6.1)
- (4.5.1 | 4.6.2)
- (4.5.1 | 4.7)
- (4.5.1 | 4.7.1)
- (4.5.1 | 4.7.2)
- (4.5.2 | 4.6)
- (4.5.2 | 4.6.1)
- (4.5.2 | 4.6.2)
- (4.5.2 | 4.7)
- (4.5.2 | 4.7.1)
- (4.5.2 | 4.7.2)
- (4.5.2 | 4.8)
- (4.6 | 4.6.1)
- (4.6 | 4.6.2)
- (4.6 | 4.7)
- (4.6 | 4.7.1)
- (4.6 | 4.7.2)
- (4.6 | 4.8)
- (4.6.1 | 4.6.2)
- (4.6.1 | 4.7)
- (4.6.1 | 4.7.1)
- (4.6.1 | 4.7.2)
- (4.6.1 | 4.8)
- (4.6.2 | 4.7)
- (4.6.2 | 4.7.1)
- (4.6.2 | 4.7.2)
- (4.6.2 | 4.8)
- (4.7 | 4.7.1)
- (4.7 | 4.7.2)
- (4.7 | 4.8)
- (4.7.1 | 4.7.2)
- (4.7.1 | 4.8)
- (4.7.2 | 4.8)
- (4.8 | 4.8.1)
If you are migrating from the .NET Framework 4.0 to 4.6.1, review the following topics for application compatibility issues that may affect your app:
ADO.NET
DbParameter.Precision and DbParameter.Scale are now public virtual members
Details
Precision and Scale are implemented as public virtual properties. They replace the corresponding explicit interface implementations, IDbDataParameter.Precision and IDbDataParameter.Scale.
Suggestion
When re-building an ADO.NET database provider, these differences will require the 'override' keyword to be applied to the Precision and Scale properties. This is only needed when re-building the components; existing binaries will continue to work.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5.1 |
| Type | Retargeting |
Affected APIs
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.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.6 |
| Type | Retargeting |
Affected APIs
MachineKey.Encode and MachineKey.Decode methods are now obsolete
Details
These methods are now obsolete. Compilation of code that calls these methods produces a compiler warning.
Suggestion
The recommended alternatives are Protect(Byte[], String[]) and Unprotect(Byte[], String[]). Alternatively, the build warnings can be suppressed, or they can be avoided by using an older compiler. The APIs are still supported.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
Multi-line ASP.NET TextBox spacing changed when using AntiXSSEncoder
Details
In .NET Framework 4.0, extra lines were inserted between lines of a multi-line text box on postback, if using the System.Web.Security.AntiXss.AntiXssEncoder. In .NET Framework 4.5, those extra line breaks are not included, but only if the web app is targeting .NET Framework 4.5
Suggestion
Be aware that 4.0 web apps retargeted to .NET Framework 4.5 may have multi-line text boxes improved to no longer insert extra line breaks. If this is not desirable, the app can have the old behavior when running on .NET Framework 4.5 by targeting the .NET Framework 4.0.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5 |
| Type | Retargeting |
WebUtility.HtmlEncode and WebUtility.HtmlDecode round-trip BMP correctly
Details
For applications that target the .NET Framework 4.5, characters that are outside the Basic Multilingual Plane (BMP) round-trip correctly when they are passed to the HtmlDecode(String) methods.
Suggestion
This change should have no effect on current applications, but to restore the original behavior, set the targetFramework attribute of the <httpRuntime> element to a string other than "4.5". You can also set the unicodeEncodingConformance and unicodeDecodingConformance attributes of the <webUtility> configuration element to control this behavior independently of the targeted version of the .NET Framework.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
ClickOnce
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.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.6 |
| Type | Retargeting |
Core
Change in path separator character in FullName property of ZipArchiveEntry objects
Details
For apps that target the .NET Framework 4.6.1 and later versions, the path separator character has changed from a backslash ("\") to a forward slash ("/") in the FullName property of ZipArchiveEntry objects created by overloads of the CreateFromDirectory method. The change brings the .NET implementation into conformity with section 4.4.17.1 of the .ZIP File Format Specification and allows .ZIP archives to be decompressed on non-Windows systems.
Decompressing a zip file created by an app that targets a previous version of the .NET Framework on non-Windows operating systems such as the Macintosh fails to preserve the directory structure. For example, on the Macintosh, it creates a set of files whose filename concatenates the directory path, along with any backslash ("\") characters, and the filename. As a result, the directory structure of decompressed files is not preserved.
Suggestion
The impact of this change on .ZIP files that are decompressed on the Windows operating system by APIs in the .NET Framework System.IO namespace should be minimal, since these APIs can seamlessly handle either a forward slash ("/") or a backslash ("\") as the path separator character.
If this change is undesirable, you can opt out of it by adding a configuration setting to the <runtime> section of your application configuration file. The following example shows both the <runtime> section and the Switch.System.IO.Compression.ZipFile.UseBackslash opt-out switch:
<runtime>
<AppContextSwitchOverrides value="Switch.System.IO.Compression.ZipFile.UseBackslash=true" />
</runtime>
In addition, apps that target previous versions of the .NET Framework but are running on the .NET Framework 4.6.1 and later versions can opt in to this behavior by adding a configuration setting to the <runtime> section of the application configuration file. The following shows both the <runtime> section and the Switch.System.IO.Compression.ZipFile.UseBackslash opt-in switch.
<runtime>
<AppContextSwitchOverrides value="Switch.System.IO.Compression.ZipFile.UseBackslash=false" />
</runtime>
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.6.1 |
| Type | Retargeting |
Affected APIs
- ZipFile.CreateFromDirectory(String, String)
- ZipFile.CreateFromDirectory(String, String, CompressionLevel, Boolean)
- ZipFile.CreateFromDirectory(String, String, CompressionLevel, Boolean, Encoding)
CurrentCulture and CurrentUICulture flow across tasks
Details
Beginning in the .NET Framework 4.6, System.Globalization.CultureInfo.CurrentCulture and System.Globalization.CultureInfo.CurrentUICulture are stored in the thread's System.Threading.ExecutionContext, which flows across asynchronous operations.This means that changes to System.Globalization.CultureInfo.CurrentCulture or System.Globalization.CultureInfo.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 System.Globalization.CultureInfo.CurrentCulture and System.Globalization.CultureInfo.CurrentUICulture in all asynchronous tasks).
Suggestion
Apps affected by this change may work around it by explicitly setting the desired System.Globalization.CultureInfo.CurrentCulture or System.Globalization.CultureInfo.CurrentUICulture as the first operation in an async Task. Alternatively, the old behavior (of not flowing System.Globalization.CultureInfo.CurrentCulture/System.Globalization.CultureInfo.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 - System.Globalization.CultureInfo.CurrentCulture/System.Globalization.CultureInfo.CurrentUICulture) would be preserved across Dispatcher operations.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.6 |
| Type | Retargeting |
Affected APIs
- CultureInfo.CurrentCulture
- Thread.CurrentCulture
- CultureInfo.CurrentUICulture
- Thread.CurrentUICulture
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.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.6 |
| Type | Retargeting |
Foreach iterator variable is now scoped within the iteration, so closure capturing semantics are different (in C#5)
Details
Beginning with C# 5 (Visual Studio 2012), foreach iterator variables are scoped within the iteration. This can cause breaks if code was previously depending on the variables to not be included in the foreach's closure. The symptom of this change is that an iterator variable passed to a delegate is treated as the value it has at the time the delegate is created, rather than the value it has at the time the delegate is invoked.
Suggestion
Ideally, code should be updated to expect the new compiler behavior. If the old semantics are required, the iterator variable can be replaced with a separate variable which is explicitly placed outside of the loop's scope.
| Name | Value |
|---|---|
| Scope | Major |
| Version | 4.5 |
| Type | Retargeting |
IAsyncResult.CompletedSynchronously property must be correct for the resulting task to complete
Details
When calling TaskFactory.FromAsync, the implementation of the CompletedSynchronously property must be correct for the resulting task to complete. That is, the property must return true if, and only if, the implementation completed synchronously. Previously, the property was not checked.
Suggestion
If System.IAsyncResult implementations correctly return true for the System.IAsyncResult.CompletedSynchronously property only when a task completed synchronously, then no break will be observed. Users should review System.IAsyncResult implementations they own (if any) to ensure that they correctly evaluate whether a task completed synchronously or not.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
- TaskFactory.FromAsync(IAsyncResult, Action<IAsyncResult>)
- TaskFactory.FromAsync(IAsyncResult, Action<IAsyncResult>, TaskCreationOptions)
- TaskFactory.FromAsync(IAsyncResult, Action<IAsyncResult>, TaskCreationOptions, TaskScheduler)
- TaskFactory.FromAsync<TResult>(IAsyncResult, Func<IAsyncResult,TResult>)
- TaskFactory.FromAsync(Func<AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, Object)
- TaskFactory.FromAsync(Func<AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, Object, TaskCreationOptions)
- TaskFactory.FromAsync<TArg1>(Func<TArg1,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, Object)
- TaskFactory.FromAsync<TArg1>(Func<TArg1,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, Object, TaskCreationOptions)
- TaskFactory.FromAsync<TResult>(Func<AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, Object)
- TaskFactory.FromAsync<TResult>(Func<AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, Object, TaskCreationOptions)
- TaskFactory.FromAsync<TResult>(IAsyncResult, Func<IAsyncResult,TResult>, TaskCreationOptions)
- TaskFactory.FromAsync<TResult>(IAsyncResult, Func<IAsyncResult,TResult>, TaskCreationOptions, TaskScheduler)
- TaskFactory.FromAsync<TArg1,TArg2>(Func<TArg1,TArg2,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, TArg2, Object)
- TaskFactory.FromAsync<TArg1,TArg2>(Func<TArg1,TArg2,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, TArg2, Object, TaskCreationOptions)
- TaskFactory.FromAsync<TArg1,TResult>(Func<TArg1,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, Object)
- TaskFactory.FromAsync<TArg1,TResult>(Func<TArg1,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, Object, TaskCreationOptions)
- TaskFactory.FromAsync<TArg1,TArg2,TResult>(Func<TArg1,TArg2,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, TArg2, Object)
- TaskFactory.FromAsync<TArg1,TArg2,TArg3>(Func<TArg1,TArg2,TArg3,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, TArg2, TArg3, Object)
- TaskFactory.FromAsync<TArg1,TArg2,TArg3>(Func<TArg1,TArg2,TArg3,AsyncCallback,Object,IAsyncResult>, Action<IAsyncResult>, TArg1, TArg2, TArg3, Object, TaskCreationOptions)
- TaskFactory.FromAsync<TArg1,TArg2,TResult>(Func<TArg1,TArg2,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, TArg2, Object, TaskCreationOptions)
- TaskFactory.FromAsync<TArg1,TArg2,TArg3,TResult>(Func<TArg1,TArg2,TArg3,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, TArg2, TArg3, Object)
- TaskFactory.FromAsync<TArg1,TArg2,TArg3,TResult>(Func<TArg1,TArg2,TArg3,AsyncCallback,Object,IAsyncResult>, Func<IAsyncResult,TResult>, TArg1, TArg2, TArg3, Object, TaskCreationOptions)
List<T>.ForEach can throw exception when modifying list item
Details
Beginning in .NET Framework 4.5, a ForEach(Action<T>) enumerator will throw an System.InvalidOperationException exception if an element in the calling collection is modified. Previously, this would not throw an exception but could lead to race conditions.
Suggestion
Ideally, code should be fixed to not modify lists while enumerating their elements because that is never a safe operation. To revert to the previous behavior, though, an app may target .NET Framework 4.0.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
ObsoleteAttribute exports as both ObsoleteAttribute and DeprecatedAttribute in WinMD scenarios
Details
When you create a Windows Metadata library (.winmd file), the System.ObsoleteAttribute attribute is exported as both System.ObsoleteAttribute and Windows.Foundation.DeprecatedAttribute.
Suggestion
Recompilation of existing source code that uses the System.ObsoleteAttribute attribute may generate warnings when consuming that code from C++/CX or JavaScript.We do not recommend applying both System.ObsoleteAttribute and Windows.Foundation.DeprecatedAttribute to code in managed assemblies; it may result in build warnings.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.5.1 |
| Type | Retargeting |
System.Uri parsing adheres to RFC 3987
Details
URI parsing has changed in several ways in .NET Framework 4.5. Note, however, that these changes only affect code targeting .NET Framework 4.5. If a binary targets .NET Framework 4.0, the old behavior will be observed. Changes to URI parsing in .NET Framework 4.5 include:
- URI parsing will perform normalization and character checking according to the latest IRI rules in RFC 3987.
- Unicode normalization form C will only be performed on the host portion of the URI.
- Invalid mailto: URIs will now cause an exception.
- Trailing dots at the end of a path segment are now preserved.
file://URIs do not escape the?character.- Unicode control characters
U+0080throughU+009Fare not supported. - Comma characters
,or%2care not automatically unescaped.
Suggestion
If the old .NET Framework 4.0 URI parsing semantics are necessary (they often aren't), they can be used by targeting .NET Framework 4.0. This can be accomplished by using a System.Runtime.Versioning.TargetFrameworkAttribute on the assembly, or through Visual Studio's project system UI in the 'project properties' page.
| Name | Value |
|---|---|
| Scope | Major |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
- Uri(String)
- Uri(String, Boolean)
- Uri(String, UriKind)
- Uri(Uri, String)
- Uri.TryCreate(String, UriKind, Uri)
- Uri.TryCreate(Uri, String, Uri)
- Uri.TryCreate(Uri, Uri, Uri)
System.Uri.IsWellFormedUriString method returns false for relative URIs with a colon char in first segment
Details
Beginning with the .NET Framework 4.5, IsWellFormedUriString(String, UriKind) will treat relative URIs with a : in their first segment as not well formed. This is a change from System.Uri.IsWellFormedUriString(String, UriKind) behavior in the .NET Framework 4.0 that was made to conform to RFC3986.
Suggestion
This change (like many other URI changes) will only affect applications targeting the .NET Framework 4.5 (or later). To keep using the old behavior, target the app against the .NET Framework 4.0. Alternatively, scan URI's prior to calling System.Uri.IsWellFormedUriString(String, UriKind) looking for : characters that you may want to remove for validation purposes, if the old behavior is desirable.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
Entity Framework
Entity Framework version must match the .NET Framework version
Details
The Entity Framework (EF) version should be matched with the .NET Framework version. Entity Framework 5 is recommended for .NET Framework 4.5. There are some known issues with EF 4.x in a .NET Framework 4.5 project around System.ComponentModel.DataAnnotations. In .NET Framework 4.5, these were moved to a different assembly, so there are issues determining which annotations to use.
Suggestion
Upgrade to Entity Framework 5 for .NET Framework 4.5
| Name | Value |
|---|---|
| Scope | Major |
| Version | 4.5 |
| 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.
| Name | Value |
|---|---|
| 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
ifstatement is used to test for a condition before entering atryblock and in the exit from thetryblock, and the same condition is evaluated in thecatchorfinallyblock, the new 64-bit JIT compiler removes theifcondition from thecatchorfinallyblock when it optimizes code. As a result, code inside theifstatement in thecatchorfinallyblock 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_DWORDvalue nameduseLegacyJitto theHKEY_CURRENT_USER\SOFTWARE\Microsoft\.NETFrameworkkey 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_DWORDvalue nameduseLegacyJitto theHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFrameworkkey of the registry. A value of1enables the legacy 64-bit JIT compiler; a value of0disables 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.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.6 |
| Type | Retargeting |
MSBuild
ResolveAssemblyReference task now warns of dependencies with the wrong architecture
Details
The task emits a warning, MSB3270, which indicates that a reference or any of its dependencies does not match the app's architecture. For example, this occurs if an app that was compiled with the AnyCPU option includes an x86 reference. Such a scenario could result in an app failure at run time (in this case, if the app is deployed as an x64 process).
Suggestion
There are two areas of impact:
- Recompilation generates warnings that did not appear when the app was compiled under a previous version of MSBuild. However, because the warning identifies a possible source of runtime failure, it should be investigated and addressed.
- If warnings are treated as errors, the app will fail to compile.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5.1 |
| 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.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.6 |
| Type | Retargeting |
Affected APIs
- System.Net.Security.SslStream
- System.Net.ServicePointManager
- System.Net.Http.HttpClient
- System.Net.Mail.SmtpClient
- System.Net.HttpWebRequest
- System.Net.FtpWebRequest
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 System.AppContext class can be used to opt out of this feature in either of two ways:
- By programmatically setting compat switches on the System.AppContext, as explained here.
- By adding the following line to the
<runtime>section of the app.config file:
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=true"/>
| Name | Value |
|---|---|
| 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 <AppContextSwitchOverrides> element in the <runtime> 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.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.6 |
| Type | Retargeting |
Affected APIs
- System.Net.Security.SslStream
- System.Net.ServicePointManager
- System.Net.Http.HttpClient
- System.Net.Mail.SmtpClient
- System.Net.HttpWebRequest
- System.Net.FtpWebRequest
Visual Basic .NET
VB.NET no longer supports partial namespace qualification for System.Windows APIs
Details
Beginning in .NET Framework 4.5.2, VB.NET projects cannot specify System.Windows APIs with partially-qualified namespaces. For example, referring to Windows.Forms.DialogResult will fail. Instead, code must refer to the fully qualified name (DialogResult) or import the specific namespace and refer simply to System.Windows.Forms.DialogResult.
Suggestion
Code should be updated to refer to System.Windows APIs either with simple names (and importing the relevant namespace) or with fully qualified names.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5.2 |
| Type | Retargeting |
Windows Communication Foundation (WCF)
Calling CreateDefaultAuthorizationContext with a null argument has changed
Details
The implementation of the System.IdentityModel.Policy.AuthorizationContext returned by a call to the System.IdentityModel.Policy.AuthorizationContext.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:
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.Add the following line to the
<appSettings>section of your app.config file:<add key="appContext.SetSwitch:Switch.System.IdentityModel.EnableCachedEmptyDefaultAuthorizationContext" value="true" />
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.6 |
| Type | Retargeting |
Affected APIs
WCF binding with the TransportWithMessageCredential security mode
Details
Beginning in the .NET Framework 4.6.1, WCF binding that uses the TransportWithMessageCredential security mode can be set up to receive messages with unsigned "to" headers for asymmetric security keys.By default, unsigned "to" headers will continue to be rejected in .NET Framework 4.6.1. They will only be accepted if an application opts into this new mode of operation using the Switch.System.ServiceModel.AllowUnsignedToHeader configuration switch.
Suggestion
Because this is an opt-in feature, it should not affect the behavior of existing apps.
To control whether the new behavior is used or not, use the following configuration setting:
<runtime>
<AppContextSwitchOverrides value="Switch.System.ServiceModel.AllowUnsignedToHeader=true" />
</runtime>
| Name | Value |
|---|---|
| Scope | Transparent |
| Version | 4.6.1 |
| Type | Retargeting |
Affected APIs
- BasicHttpSecurityMode.TransportWithMessageCredential
- BasicHttpsSecurityMode.TransportWithMessageCredential
- SecurityMode.TransportWithMessageCredential
- WSFederationHttpSecurityMode.TransportWithMessageCredential
X509CertificateClaimSet.FindClaims Considers All claimTypes
Details
In apps that target the .NET Framework 4.6.1, if an X509 claim set is initialized from a certificate that has multiple DNS entries in its SAN field, the System.IdentityModel.Claims.X509CertificateClaimSet.FindClaims(String, String) method attempts to match the claimType argument with all the DNS entries.For apps that target previous versions of the .NET Framework, the System.IdentityModel.Claims.X509CertificateClaimSet.FindClaims(String, String) method attempts to match the claimType argument only with the last DNS entry.
Suggestion
This change only affects applications targeting the .NET Framework 4.6.1. This change may be disabled (or enabled if targeting pre-4.6.1) with the DisableMultipleDNSEntries compatibility switch.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.6.1 |
| Type | Retargeting |
Affected APIs
Windows Forms
Application.FilterMessage no longer throws for re-entrant implementations of IMessageFilter.PreFilterMessage
Details
Prior to the .NET Framework 4.6.1, calling FilterMessage(Message) with an PreFilterMessage(Message) which called System.Windows.Forms.Application.AddMessageFilter(IMessageFilter) or System.Windows.Forms.Application.RemoveMessageFilter(IMessageFilter) (while also calling DoEvents()) would cause an System.IndexOutOfRangeException.
Beginning with applications targeting the .NET Framework 4.6.1, this exception is no longer thrown, and re-entrant filters as described above may be used.Suggestion
Be aware that FilterMessage(Message) will no longer throw for the re-entrant PreFilterMessage(Message) behavior described above. This only affects applications targeting the .NET Framework 4.6.1.Apps targeting the .NET Framework 4.6.1 can opt out of this change (or apps targeting older Frameworks may opt in) by using the DontSupportReentrantFilterMessage compatibility switch.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.6.1 |
| Type | Retargeting |
Affected APIs
DataObject.GetData now retrieves data as UTF-8
Details
For apps that target the .NET Framework 4 or that run on the .NET Framework 4.5.1 or earlier versions, DataObject.GetData retrieves HTML-formatted data as an ASCII string. As a result, non-ASCII characters (characters whose ASCII codes are greater than 0x7F) are represented by two random characters.
DataObject.GetData retrieves HTML-formatted data as UTF-8, which represents characters greater than 0x7F correctly.
Suggestion
If you implemented a workaround for the encoding problem with HTML-formatted strings (for example, by explicitly encoding the HTML string retrieved from the Clipboard by passing it to System.Text.UTF8Encoding.GetString(Byte[], Int32, Int32)) and you're retargeting your app from version 4 to 4.5, that workaround should be removed.If the old behavior is needed for some reason, the app can target the .NET Framework 4.0 to get that behavior.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.5.2 |
| Type | Retargeting |
Affected APIs
EncoderParameter ctor is obsolete
Details
The EncoderParameter(Encoder, Int32, Int32, Int32, Int32) constructor is obsolete now and will introduce build warnings if used.
Suggestion
Although the EncoderParameter(Encoder, Int32, Int32, Int32, Int32)constructor will continue to work, the following constructor should be used instead to avoid the obsolete build warning when re-compiling code with .NET Framework 4.5 tools: EncoderParameter(Encoder, Int32, EncoderParameterValueType, IntPtr).
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
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>" />
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.6 |
| 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.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.6.1 |
| Type | Retargeting |
CurrentCulture is not preserved across WPF Dispatcher operations
Details
Beginning in the .NET Framework 4.6, changes to System.Globalization.CultureInfo.CurrentCulture or System.Globalization.CultureInfo.CurrentUICulture made within a System.Windows.Threading.Dispatcher will be lost at the end of that dispatcher operation. Similarly, changes to System.Globalization.CultureInfo.CurrentCulture or System.Globalization.CultureInfo.CurrentUICulture made outside of a Dispatcher operation may not be reflected when that operation executes.Practically speaking, this means that System.Globalization.CultureInfo.CurrentCulture and System.Globalization.CultureInfo.CurrentUICulture changes may not flow between WPF UI callbacks and other code in a WPF application.This is due to a change in System.Threading.ExecutionContext that causes System.Globalization.CultureInfo.CurrentCulture and System.Globalization.CultureInfo.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 System.Globalization.CultureInfo.CurrentCulture and System.Globalization.CultureInfo.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 System.Globalization.CultureInfo.CurrentCulture or System.Globalization.CultureInfo.CurrentUICulture in a field and checking in all Dispatcher operation bodies (including UI event callback handlers) that the correct System.Globalization.CultureInfo.CurrentCulture and System.Globalization.CultureInfo.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 - System.Globalization.CultureInfo.CurrentCulture/System.Globalization.CultureInfo.CurrentUICulture) would be preserved across Dispatcher operations.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.6 |
| Type | Retargeting |
Two-way data-binding to a property with a non-public setter is not supported
Details
Attempting to data bind to a property without a public setter has never been a supported scenario. Beginning in the .NET Framework 4.5.1, this scenario will throw an System.InvalidOperationException. Note that this new exception will only be thrown for apps that specifically target the .NET Framework 4.5.1. If an app targets the .NET Framework 4.5, the call will be allowed. If the app does not target a particular .NET Framework version, the binding will be treated as one-way.
Suggestion
The app should be updated to either use one-way binding, or expose the property's setter publicly. Alternatively, targeting the .NET Framework 4.5 will cause the app to exhibit the old behavior.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5.1 |
| Type | Retargeting |
Affected APIs
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" />'.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.6 |
| Type | Retargeting |
WPF TextBox.Text can be out-of-sync with databinding
Details
In some cases, the Text property reflects a previous value of the databound property value if the property is modified during a databinding write operation.
Suggestion
This should have no negative impact. However, you can restore the previous behavior by setting the KeepTextBoxDisplaySynchronizedWithTextProperty property to false.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
Windows Workflow Foundation (WF)
New (ambiguous) Dispatcher.Invoke overloads could result in different behavior
Details
The .NET Framework 4.5 adds new overloads to Dispatcher.Invoke that include a parameter of type Action. When existing code is recompiled, compilers may resolve calls to Dispatcher.Invoke methods that have a Delegate parameter as calls to Dispatcher.Invoke methods with an Action parameter. If a call to a Dispatcher.Invoke overload with a Delegate parameter is resolved as a call to a Dispatcher.Invoke overload with an Action parameter, the following differences in behavior may occur:
- If an exception occurs, the UnhandledExceptionFilter and UnhandledException events are not raised. Instead, exceptions are handled by the System.Threading.Tasks.TaskScheduler.UnobservedTaskException event.
- Calls to some members, such as Result, block until the operation has completed.
Suggestion
To avoid ambiguity (and potential differences in exception handling or blocking behaviors), code calling Dispatcher.Invoke can pass an empty object[] as a second parameter to the Invoke call to be sure of resolving to the .NET Framework 4.0 method overload.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
- Dispatcher.Invoke(Delegate, Object[])
- Dispatcher.Invoke(Delegate, TimeSpan, Object[])
- Dispatcher.Invoke(Delegate, TimeSpan, DispatcherPriority, Object[])
- Dispatcher.Invoke(Delegate, DispatcherPriority, Object[])
Some WorkFlow drag-and-drop APIs are obsolete
Details
This WorkFlow drag-and-drop API is obsolete and will cause compiler warnings if the app is rebuilt against 4.5.
Suggestion
New System.Activities.Presentation.DragDropHelper APIs that support operations with multiple objects should be used instead. Alternatively, the build warnings can be suppressed or they can be avoided by using an older compiler. The APIs are still supported.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5 |
| Type | Retargeting |
Affected APIs
- DragDropHelper.DoDragMove(WorkflowViewElement, Point)
- DragDropHelper.GetCompositeView(DragEventArgs)
- DragDropHelper.GetDraggedModelItem(DragEventArgs)
- DragDropHelper.GetDroppedObject(DependencyObject, DragEventArgs, EditingContext)
WorkFlow 3.0 types are obsolete
Details
Windows Workflow Foundation (WWF) 3.0 APIs (those from the System.Workflow namespace) are now obsolete.
Suggestion
New WWF 4.0 APIs (in System.Activities) should be used instead. An example of using the new APIs can be found here and further guidance is available here. Alternatively, since the WWF 3.0 APIs are still supported, they may be used and the build-time warning avoided either by suppressing it or by using an older compiler.
| Name | Value |
|---|---|
| Scope | Major |
| Version | 4.5 |
| Type | Retargeting |
XML, XSLT
XML schema validation is stricter
Details
In the .NET Framework 4.5, XML schema validation is more strict. If you use xsd:anyURI to validate a URI such as a mailto protocol, validation fails if there are spaces in the URI. In previous versions of the .NET Framework, validation succeeded. The change affects only applications that target the .NET Framework 4.5.
Suggestion
If looser .NET Framework 4.0 validation is needed, the validating application can target version 4.0 of the .NET Framework. When retargeting to .NET Framework 4.5, however, code review should be done to be sure that invalid URIs (with spaces) are not expected as attribute values with the anyURI data type.
| Name | Value |
|---|---|
| Scope | Minor |
| Version | 4.5 |
| Type | Retargeting |
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 System.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.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.6 |
| Type | Retargeting |
Affected APIs
- XmlWriter.WriteAttributeString(String, String)
- XmlWriter.WriteAttributeString(String, String, String)
- XmlWriter.WriteAttributeString(String, String, String, String)
- XmlWriter.WriteAttributeStringAsync(String, String, String, String)
- XmlWriter.WriteCData(String)
- XmlWriter.WriteCDataAsync(String)
- XmlWriter.WriteChars(Char[], Int32, Int32)
- XmlWriter.WriteCharsAsync(Char[], Int32, Int32)
- XmlWriter.WriteComment(String)
- XmlWriter.WriteCommentAsync(String)
- XmlWriter.WriteEntityRef(String)
- XmlWriter.WriteEntityRefAsync(String)
- XmlWriter.WriteRaw(Char[], Int32, Int32)
- XmlWriter.WriteProcessingInstruction(String, String)
- XmlWriter.WriteProcessingInstructionAsync(String, String)
- XmlWriter.WriteRaw(String)
- XmlWriter.WriteRawAsync(Char[], Int32, Int32)
- XmlWriter.WriteRawAsync(String)
- XmlWriter.WriteString(String)
- XmlWriter.WriteStringAsync(String)
- XmlWriter.WriteSurrogateCharEntity(Char, Char)
- XmlWriter.WriteSurrogateCharEntityAsync(Char, Char)
- XmlWriter.WriteValue(String)
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.
| Name | Value |
|---|---|
| Scope | Edge |
| Version | 4.6 |
| Type | Retargeting |
Povratne informacije
Pošalјite i prikažite povratne informacije za