Runtime Changes for Migration from .NET Framework 4.0 to 4.7.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.1 | 4.8)
- (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.7.1, review the following topics for application compatibility issues that may affect your app:
ADO.NET
ADO.NET now attempts to automatically reconnect broken SQL connections
Details
Beginning in the .NET Framework 4.5.1, the .NET Framework will attempt to automatically reconnect broken SQL connections. Although this will typically make apps more reliable, there are edge cases in which an app needs to know that the connection was lost so that it can take some action upon reconnection.
Suggestion
If this feature is undesirable due to compatibility concerns, it can be disabled by setting the System.Data.SqlClient.SqlConnectionStringBuilder.ConnectRetryCount property of a connection string (or System.Data.SqlClient.SqlConnectionStringBuilder) to 0.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5.1 |
Type | Runtime |
Affected APIs
- IDbConnection.ConnectionString
- SqlConnection.ConnectionString
- ConnectionStringSettings.ConnectionString
- DbConnection.ConnectionString
- DbConnectionStringBuilder.ConnectionString
- SqlConnectionStringBuilder()
- SqlConnectionStringBuilder(String)
- DbConnectionStringBuilder()
- DbConnectionStringBuilder(Boolean)
ASP.NET
ASP.NET MVC now escapes spaces in strings passed in via route parameters
Details
In order to conform to RFC 2396, spaces in route paths are now escaped when populating action parameters from a route. So, whereas /controller/action/some data
would previously match the route /controller/action/{data}
and provide some data
as the data parameter, it will now provide some%20data
instead.
Suggestion
Code should be updated to unescape string parameters from a route. If the original URI is needed, it can be accessed with the RequestUri.OriginalString API.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5.2 |
Type | Runtime |
Affected APIs
HttpRequest.ContentEncoding property prohibits UTF7
Details
Beginning in .NET Framework 4.5, UTF-7 encoding is prohibited in System.Web.HttpRequests' bodies. Data for applications that depend on incoming UTF-7 data will not decode properly in some cases.
Suggestion
Ideally, applications should be updated to not use UTF-7 encoding in System.Web.HttpRequests. Alternatively, legacy behavior can be restored by using the aspnet:AllowUtf7RequestContentEncoding
attribute of the appSettings element.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
HttpUtility.JavaScriptStringEncode escapes ampersand
Details
Starting with the .NET Framework 4.5, System.Web.HttpUtility.JavaScriptStringEncode(String) escapes the ampersand (&) character.
Suggestion
If your app depends on the previous behavior of this method, you can add an aspnet:JavaScriptDoNotEncodeAmpersand setting to the ASP.NET appSettings element in your configuration file.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
IPad should not be used in custom capabilities file because it is now a browser capability
Details
Beginning in .NET Framework 4.5, iPad is an identifier in the default ASP.NET browser capabilities file, so it should not be used in a custom capabilities file
Suggestion
If iPad-specific capabilities are required, it is necessary to modify iPad behavior by setting capabilities on the pre-defined gateway refID "IPad" instead of by generating a new "IPad" ID by user agent matching.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
No longer able to set EnableViewStateMac to false
Details
ASP.NET no longer allows developers to specify <pages enableViewStateMac="false"/>
or <@Page EnableViewStateMac="false" %>
. The view state message authentication code (MAC) is now enforced for all requests with embedded view state. Only apps that explicitly set the EnableViewStateMac property to false
are affected.
Suggestion
EnableViewStateMac must be assumed to be true, and any resulting MAC errors must be resolved (as explained in this guidance, which contains multiple resolutions depending on the specifics of what is causing MAC errors).
Name | Value |
---|---|
Scope | Major |
Version | 4.5.2 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Page.LoadComplete event no longer causes System.Web.UI.WebControls.EntityDataSource control to invoke data binding
Details
The LoadComplete event no longer causes the System.Web.UI.WebControls.EntityDataSource control to invoke data binding for changes to create/update/delete parameters. This change eliminates an extraneous trip to the database, prevents the values of controls from being reset, and produces behavior that is consistent with other data controls, such as System.Web.UI.WebControls.SqlDataSource and System.Web.UI.WebControls.ObjectDataSource. This change produces different behavior in the unlikely event that applications rely on invoking data binding in the LoadComplete event.
Suggestion
If there is a need for databinding, manually invoke databind in an event that is earlier in the post-back.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Sharing session state with ASP.NET StateServer requires all servers in the web farm to use the same .NET Framework version
Details
When enabling System.Web.SessionState.SessionStateMode.StateServer session state, all of the servers in the given web farm must use the same version of the .NET Framework in order for state to be properly shared.
Suggestion
Be sure to upgrade .NET Framework versions on web servers that share state at the same time.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
WebUtility.HtmlDecode no longer decodes invalid input sequences
Details
By default, decoding methods no longer decode an invalid input sequence into an invalid UTF-16 string. Instead, they return the original input.
Suggestion
The change in decoder output should matter only if you store binary data instead of UTF-16 data in strings. To explicitly control this behavior, set the aspnet:AllowRelaxedUnicodeDecoding
attribute of the appSettings element to true
to enable legacy behavior or to false
to enable the current behavior.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
- WebUtility.HtmlDecode(String)
- WebUtility.HtmlDecode(String, TextWriter)
- WebUtility.UrlDecode(String)
Core
AppDomainSetup.DynamicBase is no longer randomized by UseRandomizedStringHashAlgorithm
Details
Prior to the .NET Framework 4.6, the value of DynamicBase would be randomized between application domains, or between processes, if UseRandomizedStringHashAlgorithm was enabled in the app's config file. Beginning in the .NET Framework 4.6, DynamicBase will return a stable result between different instances of an app running, and between different app domains. Dynamic bases will still differ for different apps; this change only removes the random naming element for different instances of the same app.
Suggestion
Be aware that enabling UseRandomizedStringHashAlgorithm
will not result in DynamicBase being randomized. If a random base is needed, it must be produced in your app's code rather than via this API.
Name | Value |
---|---|
Scope | Edge |
Version | 4.6 |
Type | Runtime |
Affected APIs
Assemblies compiled with Regex.CompileToAssembly breaks between 4.0 and 4.5
Details
If an assembly of compiled regular expressions is built with the .NET Framework 4.5 but targets the .NET Framework 4, attempting to use one of the regular expressions in that assembly on a system with .NET Framework 4 installed throws an exception.
Suggestion
To work around this problem, you can do either of the following:
- Build the assembly that contains the regular expressions with the .NET Framework 4.
- Use an interpreted regular expression.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
- Regex.CompileToAssembly(RegexCompilationInfo[], AssemblyName)
- Regex.CompileToAssembly(RegexCompilationInfo[], AssemblyName, CustomAttributeBuilder[])
- Regex.CompileToAssembly(RegexCompilationInfo[], AssemblyName, CustomAttributeBuilder[], String)
BlockingCollection<T>.TryTakeFromAny does not throw anymore
Details
If one of the input collections is marked completed, TryTakeFromAny(BlockingCollection<T>[], T) no longer returns -1 and TakeFromAny(BlockingCollection<T>[], T) no longer throws an exception. This change makes it possible to work with collections when one of the collections is either empty or completed, but the other collection still has items that can be retrieved.
Suggestion
If TryTakeFromAny returning -1 or TakeFromAny throwing were used for control-flow purposes in cases of a blocking collection being completed, such code should now be changed to use .Any(b => b.IsCompleted)
to detect that condition.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
- BlockingCollection<T>.TakeFromAny(BlockingCollection<T>[], T)
- BlockingCollection<T>.TakeFromAny(BlockingCollection<T>[], T, CancellationToken)
- BlockingCollection<T>.TryTakeFromAny(BlockingCollection<T>[], T)
- BlockingCollection<T>.TryTakeFromAny(BlockingCollection<T>[], T, Int32)
- BlockingCollection<T>.TryTakeFromAny(BlockingCollection<T>[], T, TimeSpan)
- BlockingCollection<T>.TryTakeFromAny(BlockingCollection<T>[], T, TimeSpan)
Calling Attribute.GetCustomAttributes on an indexer property no longer throws AmbiguousMatchException if the ambiguity can be resolved by index's type
Details
Prior to the .NET Framework 4.6, calling GetCustomAttribute(s)
on an indexer property which differed from another property only by the type of the index would result in an System.Reflection.AmbiguousMatchException. Beginning in the .NET Framework 4.6, the property's attributes will be correctly returned.
Suggestion
Be aware that GetCustomAttribute(s) will work more frequently now. If an app was previously relying on the System.Reflection.AmbiguousMatchException, reflection should now be used to explicitly look for multiple indexers, instead.
Name | Value |
---|---|
Scope | Edge |
Version | 4.6 |
Type | Runtime |
Affected APIs
- Attribute.GetCustomAttribute(MemberInfo, Type)
- Attribute.GetCustomAttribute(MemberInfo, Type, Boolean)
- Attribute.GetCustomAttributes(MemberInfo)
- Attribute.GetCustomAttributes(MemberInfo, Boolean)
- Attribute.GetCustomAttributes(MemberInfo, Type)
- Attribute.GetCustomAttributes(MemberInfo, Type, Boolean)
- CustomAttributeExtensions.GetCustomAttribute(MemberInfo, Type)
- CustomAttributeExtensions.GetCustomAttribute(MemberInfo, Type, Boolean)
- CustomAttributeExtensions.GetCustomAttribute<T>(MemberInfo)
- CustomAttributeExtensions.GetCustomAttribute<T>(MemberInfo, Boolean)
- CustomAttributeExtensions.GetCustomAttributes(MemberInfo)
- CustomAttributeExtensions.GetCustomAttributes(MemberInfo, Boolean)
- CustomAttributeExtensions.GetCustomAttributes(MemberInfo, Type)
- CustomAttributeExtensions.GetCustomAttributes(MemberInfo, Type, Boolean)
- CustomAttributeExtensions.GetCustomAttributes<T>(MemberInfo)
- CustomAttributeExtensions.GetCustomAttributes<T>(MemberInfo, Boolean)
Change in behavior for Task.WaitAll methods with time-out arguments
Details
Task.WaitAll behavior was made more consistent in .NET Framework 4.5.In the .NET Framework 4, these methods behaved inconsistently. When the time-out expired, if one or more tasks were completed or canceled before the method call, the method threw an System.AggregateException exception. When the time-out expired, if no tasks were completed or canceled before the method call, but one or more tasks entered these states after the method call, the method returned false.
In the .NET Framework 4.5, these method overloads now return false if any tasks are still running when the time-out interval expired, and they throw an System.AggregateException exception only if an input task was cancelled (regardless of whether it was before or after the method call) and no other tasks are still running.
Suggestion
If an System.AggregateException was being caught as a means of detecting a task that was cancelled prior to the WaitAll call being invoked, that code should instead do the same detection via the IsCanceled property (for example: .Any(t => t.IsCanceled)) since .NET Framework 4.6 will only throw in that case if all awaited tasks are completed prior to the timeout.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
- Task.WaitAll(Task[], Int32)
- Task.WaitAll(Task[], Int32, CancellationToken)
- Task.WaitAll(Task[], TimeSpan)
Compiler support for type forwarding when multi-targeting mscorlib
Details
A new CodeDOM feature allows a compiler to compile against the targeted version of mscorlib.dll instead of the .NET Framework 4.5 version of mscorlib.dll.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Deserialization of objects across appdomains can fail
Details
In some cases, when an app uses two or more app domains with different application bases, trying to deserialize objects in the logical call context across app domains throws an exception.
Suggestion
See Mitigation: Deserialization of Objects Across App Domains
Name | Value |
---|---|
Scope | Edge |
Version | 4.5.1 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
EventListener truncates strings with embedded nulls
Details
System.Diagnostics.Tracing.EventListener truncates strings with embedded nulls. Null characters are not supported by the System.Diagnostics.Tracing.EventSource class. The change only affects apps that use System.Diagnostics.Tracing.EventListener to read System.Diagnostics.Tracing.EventSource data in process and that use null characters as delimiters.
Suggestion
System.Diagnostics.Tracing.EventSource data should be updated, if possible, to not use embedded null characters.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5.1 |
Type | Runtime |
Affected APIs
- EventListener()
- EventListener.EnableEvents(EventSource, EventLevel)
- EventListener.EnableEvents(EventSource, EventLevel, EventKeywords)
- EventListener.EnableEvents(EventSource, EventLevel, EventKeywords, IDictionary<String,String>)
EventSource.WriteEvent impls must pass WriteEvent the same parameters that it received (plus ID)
Details
The runtime now enforces the contract that specifies the following: A class derived from System.Diagnostics.Tracing.EventSource that defines an ETW event method must call the base class EventSource.WriteEvent
method with the event ID followed by the same arguments that the ETW event method was passed.
Suggestion
An System.IndexOutOfRangeException exception is thrown if an System.Diagnostics.Tracing.EventListener reads System.Diagnostics.Tracing.EventSource data in process for an event source that violates this contract.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5.1 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Exceptions during unobserved processing in System.Threading.Tasks.Task no longer propagate on finalizer thread
Details
Because the System.Threading.Tasks.Task class represents an asynchronous operation, it catches all non-severe exceptions that occur during asynchronous processing. In the .NET Framework 4.5, if an exception is not observed and your code never waits on the task, the exception will no longer propagate on the finalizer thread and crash the process during garbage collection. This change enhances the reliability of applications that use the Task class to perform unobserved asynchronous processing.
Suggestion
If an app depends on unobserved asynchronous exceptions propagating to the finalizer thread, the previous behavior can be restored by providing an appropriate handler for the UnobservedTaskException event, or by setting a runtime configuration element.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
- Task.Run(Action)
- Task.Run(Action, CancellationToken)
- Task.Run(Func<Task>)
- Task.Run(Func<Task>, CancellationToken)
- Task.Run<TResult>(Func<TResult>)
- Task.Run<TResult>(Func<TResult>, CancellationToken)
- Task.Run<TResult>(Func<Task<TResult>>)
- Task.Run<TResult>(Func<Task<TResult>>, CancellationToken)
- Task.Start()
- Task.Start(TaskScheduler)
List.Sort algorithm changed
Details
Beginning in .NET Framework 4.5, System.Collections.Generic.List<T>'s sort algorithm has changed (to be an introspective sort instead of a quick sort). System.Collections.Generic.List<T>'s sort has never been stable, but this change may cause different scenarios to sort in unstable ways. That simply means that equivalent items may sort in different orders in subsequent calls of the API.
Suggestion
Because the old sort algorithm was also unstable (though in slightly different ways), there should be no code that depends on equivalent items always sorting in a particular order. If there are instances of code depending upon that and being lucky with the old behavior, that code should be updated to use a comparer that will deterministically sort the items in the desired order.
Name | Value |
---|---|
Scope | Transparent |
Version | 4.5 |
Type | Runtime |
Affected APIs
- List<T>.Sort()
- List<T>.Sort(IComparer<T>)
- List<T>.Sort(Comparison<T>)
- List<T>.Sort(Int32, Int32, IComparer<T>)
Marshal.SizeOf and Marshal.PtrToStructure overloads break dynamic code
Details
Beginning in the .NET Framework 4.5.1, dynamically binding to the methods SizeOf<T>(), SizeOf<T>(T), PtrToStructure(IntPtr, Object), PtrToStructure(IntPtr, Type), PtrToStructure<T>(IntPtr), or PtrToStructure<T>(IntPtr, T), (via Windows PowerShell, IronPython, or the C# dynamic keyword, for example) can result in MethodInvocationExceptions
because new overloads of these methods have been added that may be ambiguous to the scripting engines.
Suggestion
Update scripts to clearly indicate which overload should be used. This can typically done by explicitly casting the methods' type parameters as Type. See this link for more detail and examples of how to workaround the issue.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5.1 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Missing Target Framework Moniker results in 4.0 behavior
Details
Applications without a System.Runtime.Versioning.TargetFrameworkAttribute applied at the assembly level will automatically run using the semantics (quirks) of the .NET Framework 4.0. To ensure high quality, it is recommended that all binaries be explicitly attributed with a System.Runtime.Versioning.TargetFrameworkAttribute indicating the version of the .NET Framework they were built with. Note that using a target framework moniker in a project file will cause MSBuild to automatically apply a System.Runtime.Versioning.TargetFrameworkAttribute.
Suggestion
A System.Runtime.Versioning.TargetFrameworkAttribute should be supplied, either through adding the attribute directly to the assembly or by specifying a target framework in the project file or through Visual Studio's project properties GUI.
Name | Value |
---|---|
Scope | Major |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Persian calendar now uses the Hijri solar algorithm
Details
Starting with the .NET Framework 4.6, the System.Globalization.PersianCalendar class uses the Hijri solar algorithm. Converting dates between the System.Globalization.PersianCalendar and other calendars may produce a slightly different result beginning with the .NET Framework 4.6 for dates earlier than 1800 or later than 2023 (Gregorian).Also, PersianCalendar.MinSupportedDateTime is now March 22, 0622
instead of March 21, 0622
.
Suggestion
Be aware that some early or late dates may be slightly different when using the PersianCalendar in .NET Framework 4.6. Also, when serializing dates between processes which may run on different .NET Framework versions, do not store them as PersianCalendar date strings (since those values may be different).
Name | Value |
---|---|
Scope | Minor |
Version | 4.6 |
Type | Runtime |
Affected APIs
Reflection objects can no longer be passed from managed code to out-of-process DCOM clients
Details
Reflection objects can no longer be passed from managed code to out-of-process DCOM clients. The following types are affected:
- System.Reflection.Assembly
- System.Reflection.MemberInfo (and its derived types, including System.Reflection.FieldInfo, System.Reflection.MethodInfo, System.Type, and System.Reflection.TypeInfo)
- System.Reflection.MethodBody
- System.Reflection.Module
- System.Reflection.ParameterInfo
Calls to IMarshal
for the object return E_NOINTERFACE
.
Suggestion
Update marshaling code to work with non-reflection objects.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6 |
Type | Runtime |
Affected APIs
- System.Reflection.Assembly
- System.Reflection.FieldInfo
- System.Reflection.MemberInfo
- System.Reflection.MethodBody
- System.Reflection.MethodInfo
- System.Reflection.Module
- System.Reflection.ParameterInfo
- System.Reflection.TypeInfo
- System.Type
System.Threading.Tasks.Task no longer throw ObjectDisposedException after object is disposed
Details
Except for IAsyncResult.AsyncWaitHandle, System.Threading.Tasks.Task methods no longer throw an System.ObjectDisposedException exception after the object is disposed.This change supports the use of cached tasks. For example, a method can return a cached task to represent an already completed operation instead of allocating a new task. This was impossible in previous .NET Framework versions, because any consumer of the task could dispose of it, which rendered it unusable.
Suggestion
Be aware that Task methods may no longer throw System.ObjectDisposedException in cases when the object is disposed. If an app was depending on this exception to know that a task was disposed, it should be updated to explicitly check the task's status using Status.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
System.Uri escaping now supports RFC 3986
Details
URI escaping has changed in .NET Framework 4.5 to support RFC 3986. Specific changes include:
- System.Uri.EscapeDataString(String) escapes reserved characters based on RFC 3986.
- System.Uri.EscapeUriString(String) does not escape reserved characters.
- System.Uri.UnescapeDataString(String) does not throw an exception if it encounters an invalid escape sequence.
- Unreserved escaped characters are un-escaped.
Suggestion
- Update applications to not rely on System.Uri.UnescapeDataString(String) to throw in the case of an invalid escape sequence. Such sequences must be detected directly now.
- Similarly, expect that Escaped and Unescaped URI and Data strings may vary from .NET Framework 4.0 and .NET Framework 4.5 and should not be compared across .NET versions directly. Instead, they should be parsed and normalized in a single .NET version before any comparisons are made.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
TargetFrameworkName for default app domain no longer defaults to null if not set
Details
The System.AppDomainSetup.TargetFrameworkName was previously null in the default app domain, unless it was explicitly set. Beginning in 4.6, the System.AppDomainSetup.TargetFrameworkName property for the default app domain will have a default value derived from the TargetFrameworkAttribute (if one is present). Non-default app domains will continue to inherit their System.AppDomainSetup.TargetFrameworkName from the default app domain (which will not default to null in 4.6) unless it is explicitly overridden.
Suggestion
Code should be updated to not depend on TargetFrameworkName defaulting to null. If it is required that this property continue to evaluate to null, it can be explicitly set to that value.
Name | Value |
---|---|
Scope | Edge |
Version | 4.6 |
Type | Runtime |
Affected APIs
WinRT stream adapters no long call FlushAsync automatically on close
Details
In Windows Store apps, Windows Runtime stream adapters no longer call the FlushAsync method from the Dispose method.
Suggestion
This change should be transparent. Developers can restore the previous behavior by writing code like this:
using (var stream = GetWindowsRuntimeStream() as Stream)
{
// do something
await stream.FlushAsync();
}
Name | Value |
---|---|
Scope | Transparent |
Version | 4.5.1 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
X509Certificate2.ToString(Boolean) does not throw now when .NET cannot handle the certificate
Details
In .NET Framework 4.5.2 and earlier versions, this method would throw if true
was passed for the verbose parameter and there were certificates installed that weren't supported by the .NET Framework. Now, the method will succeed and return a valid string that omits the inaccessible portions of the certificate.
Suggestion
Any code depending on X509Certificate2.ToString(Boolean) should be updated to expect that the returned string may exclude some certificate data (such as public key, private key, and extensions) in some cases in which the API would have previously thrown.
Name | Value |
---|---|
Scope | Edge |
Version | 4.6 |
Type | Runtime |
Affected APIs
Data
ADO.NET now attempts to automatically reconnect broken SQL connections
Details
Beginning in the .NET Framework 4.5.1, the .NET Framework will attempt to automatically reconnect broken SQL connections. Although this will typically make apps more reliable, there are edge cases in which an app needs to know that the connection was lost so that it can take some action upon reconnection.
Suggestion
If this feature is undesirable due to compatibility concerns, it can be disabled by setting the System.Data.SqlClient.SqlConnectionStringBuilder.ConnectRetryCount property of a connection string (or System.Data.SqlClient.SqlConnectionStringBuilder) to 0.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5.1 |
Type | Runtime |
Affected APIs
- IDbConnection.ConnectionString
- SqlConnection.ConnectionString
- ConnectionStringSettings.ConnectionString
- DbConnection.ConnectionString
- DbConnectionStringBuilder.ConnectionString
- SqlConnectionStringBuilder()
- SqlConnectionStringBuilder(String)
- DbConnectionStringBuilder()
- DbConnectionStringBuilder(Boolean)
Connection pool blocking period for Azure SQL databases is removed
Details
Starting with the .NET Framework 4.6.2, for connection open requests to known Azure SQL databases (*.database.windows.net, *.database.chinacloudapi.cn, *.database.usgovcloudapi.net, *.database.cloudapi.de), the connection pool blocking period is removed, and connection open errors are not cached. Attempts to retry connection open requests will occur almost immediately after transient connection errors. This change allows the connection open attempt to be retried immediately for Azure SQL databases, thereby improving the performance of cloud- enabled apps. For all other connection attempts, the connection pool blocking period continues to be enforced.
In the .NET Framework 4.6.1 and earlier versions, when an app encounters a transient connection failure when connecting to a database, the connection attempt cannot be retried quickly, because the connection pool caches the error and re-throws it for 5 seconds to 1 minute. For more information, see SQL Server Connection Pooling (ADO.NET). This behavior is problematic for connections to Azure SQL databases, which often fail with transient errors that are typically recovered from within a few seconds. The connection pool blocking feature means that the app cannot connect to the database for an extensive period, even though the database is available and the app needs to render within a few seconds.Suggestion
If this behavior is undesirable, the connection pool blocking period can be configured by setting the System.Data.SqlClient.SqlConnectionStringBuilder.PoolBlockingPeriod property introduced in the .NET Framework 4.6.2. The value of the property is a member of the System.Data.SqlClient.PoolBlockingPeriod enumeration that can take either of three values:
The previous behavior can be restored by setting the System.Data.SqlClient.SqlConnectionStringBuilder.PoolBlockingPeriod property to AlwaysBlock.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6.2 |
Type | Runtime |
Affected APIs
Sql_variant data uses sql_variant collation rather than database collation
Details
sql_variant
data uses sql_variant
collation rather than database collation.
Suggestion
This change addresses possible data corruption if the database collation differs from the sql_variant
collation. Applications that rely on the corrupted data may experience failure.
Name | Value |
---|---|
Scope | Transparent |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
SqlBulkCopy uses destination column encoding for strings
Details
When inserting data into a column, System.Data.SqlClient.SqlBulkCopy uses the encoding of the destination column rather than the default encoding for VARCHAR
and CHAR
types. This change eliminates the possibility of data corruption caused by using the default encoding when the destination column does not use the default encoding. In rare cases, an existing application may throw a SqlException exception if the change in encoding produces data that is too big to fit into the destination column.
Suggestion
Expect that System.Data.SqlClient.SqlBulkCopy will no longer corrupt data due to encoding differences. If strings near the destination column's size limit are being copied, it may be necessary to either pre-encode data (to be copied to check that the data will fit in the destination column) or catch System.Data.SqlClient.SqlExceptions.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
SqlConnection can no longer connect to SQL Server 1997 or databases using the VIA adapter
Details
Connections to SQL Server databases using the Virtual Interface Adapter (VIA) protocol are no longer supported. The protocol used to connect to a SQL Server database is visible in the connection string. A VIA connection will contain via:<servername>. If this app is connecting to SQL via a protocol other than VIA (tcp: or np: for example), then no breaking change will be encountered. Also, connections to SQL Server 7 (1997) are no longer supported.
Suggestion
The VIA protocol is deprecated, so an alternative protocol should be used to connect to SQL databases. The most common protocol used is TCP/IP. For more information about connecting through TCP/IP, see Enable the TCP/IP protocol for a database instance. If the database is only accessed from within an intranet, the shared pipes protocol may provide better performance if the network is slow.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Entity Framework
Change in behavior in Data Definition Language (DDL) APIs
Details
The behavior of DDL APIs when AttachDBFilename is specified has changed as follows:
- Connection strings need not specify an Initial Catalog value. Previously, both AttachDBFilename and Initial Catalog were required.
- If both AttachDBFilename and Initial Catalog are specified and the given MDF file exists, the DatabaseExists method returns
true
. Previously, it returnedfalse
. - If both AttachDBFilename and Initial Catalog are specified and the given MDF file exists, calling the DeleteDatabase method deletes the files.
- If DeleteDatabase is called when the connection string specifies an AttachDBFilename value with an MDF that doesn't exist and an Initial Catalog that doesn't exist, the method throws an InvalidOperationException exception. Previously, it threw a SqlException exception.
Suggestion
These changes make it easier to build tools and applications that use the DDL APIs. These changes can affect application compatibility in the following scenarios:
- The user writes code that executes a
DROP DATABASE
command directly instead of calling DeleteDatabase if DatabaseExists returnstrue
. This breaks existing code If the database is not attached but the MDF file exists. - The user writes code that expects the DeleteDatabase method to throw a SqlException rather than an InvalidOperationException when the Initial Catalog and MDF file don't exist.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Different exception handling for ObjectContext.CreateDatabase and DbProviderServices.CreateDatabase methods
Details
Beginning in .NET Framework 4.5, if database creation fails, CreateDatabase
methods will attempt to drop the empty database. If that operation succeeds, the original System.Data.SqlClient.SqlException will be propagated (instead of the System.InvalidOperationException that was always thrown in .NET Framework 4.0)
Suggestion
When catching an System.InvalidOperationException while executing CreateDatabase() or CreateDatabase(DbConnection, Nullable<Int32>, StoreItemCollection), SQLExceptions should now also be caught.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
- ObjectContext.CreateDatabase()
- DbProviderServices.CreateDatabase(DbConnection, Nullable<Int32>, StoreItemCollection)
EF no longer throws for QueryViews with specific characteristics
Details
Entity Framework no longer throws a System.StackOverflowException exception when an app executes a query that involves a QueryView with a 0..1 navigation property that attempts to include the related entities as part of the query. For example, by calling .Include(e => e.RelatedNavProp)
.
Suggestion
This change only affects code that uses QueryViews with 1-0..1 relationships when running queries that call .Include. It improves reliability and should be transparent to almost all apps. However, if it causes unexpected behavior, you can disable it by adding the following entry to the <appSettings>
section of the app's configuration file:
<add key="EntityFramework_SimplifyUserSpecifiedViews" value="false" />
Name | Value |
---|---|
Scope | Edge |
Version | 4.5.2 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
EntityFramework 6.0 loads very slowly in apps launched from Visual Studio
Details
Launching an app from Visual Studio 2013 that uses EntityFramework 6.0 can be very slow.
Suggestion
This issue is fixed in EntityFramework 6.0.2. Update EntityFramework to avoid the performance issue.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Log file name created by the ObjectContext.CreateDatabase method has changed to match SQL Server specifications
Details
When the System.Data.Objects.ObjectContext.CreateDatabase() method is called either directly or by using Code First with the SqlClient provider and an AttachDBFilename value in the connection string, it creates a log file named filename_log.ldf instead of filename.ldf (where filename is the name of the file specified by the AttachDBFilename value). This change improves debugging by providing a log file named according to SQL Server specifications.
Suggestion
If the log file name is important for an app, the app should be updated to expect the standard _log.ldf file name format.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
ObjectContext.Translate and ObjectContext.ExecuteStoreQuery now support enum type
Details
In .NET Framework 4.0, the generic parameter T
of ObjectContext.Translate
and ObjectContext.ExecuteStoreQuery
methods could not be an enum. That scenario is now supported.
Suggestion
If Translate or ExecuteStoreQuery was called on an enum type in .NET Framework 4.0, '0' was returned. If that behavior was desirable, the calls should be replaced with a constant 0 (or the enum equivalent of it).
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
- ObjectContext.Translate<TElement>(DbDataReader)
- ObjectContext.Translate<TEntity>(DbDataReader, String, MergeOption)
- ObjectContext.ExecuteStoreQuery<TElement>(String, Object[])
- ObjectContext.ExecuteStoreQuery<TEntity>(String, String, MergeOption, Object[])
Opt-in break to revert from different 4.5 SQL generation to simpler 4.0 SQL generation
Details
Queries that produce JOIN statements and contain a call to a limiting operation without first using OrderBy now produce simpler SQL. After upgrading to .NET Framework 4.5, these queries produced more complicated SQL than previous versions.
Suggestion
This feature is disabled by default. If Entity Framework generates extra JOIN statements that cause performance degradation, you can enable this feature by adding the following entry to the <appSettings>
section of the application configuration (app.config) file:
<add key="EntityFramework_SimplifyLimitOperations" value="true" />
Name | Value |
---|---|
Scope | Transparent |
Version | 4.5.2 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Globalization
Unicode standard version 8.0 categories now supported
Details
In .NET Framework 4.6.2, Unicode data has been upgraded from Unicode Standard version 6.3 to version 8.0. When requesting Unicode character categories in .NET Framework 4.6.2, some results might not match the results in previous .NET Framework versions. This change mostly affects Cherokee syllables and New Tai Lue vowels signs and tone marks.
Suggestion
Review code and remove/change logic that depends on hard-coded Unicode character categories.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6.2 |
Type | Runtime |
Affected APIs
- Char.GetUnicodeCategory(Char)
- CharUnicodeInfo.GetUnicodeCategory(Char)
- CharUnicodeInfo.GetUnicodeCategory(String, Int32)
LINQ
Enumerable.Empty<TResult> always returns cached instance
Details
Beginning in .NET Framework 4.5, Empty<TResult>() always returns a cached internal instance IEnumerable<T>.Previously, Empty<TResult>() would cache an empty IEnumerable<T> at the time the API was called, meaning that in some conditions in which Empty<TResult>() was called rapidly and concurrently, different instances of the type could be returned for different calls to the API.
Suggestion
Because the previous behavior was non-deterministic, code is unlikely to depend on it. However, in the unlikely case that empty enumerables are being compared and expected to sometimes be unequal, explicit empty arrays should be created (new T[0]
) instead of using Empty<TResult>().
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Managed Extensibility Framework (MEF)
MEF catalogs implement IEnumerable and therefore can no longer be used to create a serializer
Details
Starting with the .NET Framework 4.5, MEF catalogs implement IEnumerable and therefore can no longer be used to create a serializer (System.Xml.Serialization.XmlSerializer object). Trying to serialize a MEF catalog throws an exception.
Suggestion
Can no longer use MEF to create a serializer
Name | Value |
---|---|
Scope | Major |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Networking
ContentDisposition DateTimes returns slightly different string
Details
String representations of System.Net.Mime.ContentDisposition's have been updated, beginning in 4.6, to always represent the hour component of a System.DateTime with two digits. This is to comply with RFC822 and RFC2822. This causes ToString() to return a slightly different string in 4.6 in scenarios where one of the disposition's time elements was before 10:00 AM. Note that ContentDispositions are sometimes serialized via converting them to strings, so any ToString() operations, serialization, or GetHashCode calls should be reviewed.
Suggestion
Do not expect that string representations of ContentDispositions from different .NET Framework versions will correctly compare to one another. Convert the strings back to ContentDispositions, if possible, before conducting a comparison.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6 |
Type | Runtime |
Affected APIs
Deserialization of MailMessage objects serialized under the .NET Framework 4.5 may fail
Details
Starting with the .NET Framework 4.5, MailMessage objects can include non-ASCII characters. In the .NET Framework 4, only ASCII characters are supported. MailMessage objects that contain non-ASCII characters and that are serialized under the .NET Framework 4.5 or later cannot be deserialized under the .NET Framework 4.
Suggestion
Ensure that your code provides exception handling when deserializing a MailMessage object.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
System.Net.PeerToPeer.Collaboration unavailable on Windows 8
Details
The System.Net.PeerToPeer.Collaboration namespace is unavailable on Windows 8 or above.
Suggestion
Apps that support Windows 8 or above must be updated to not depend on this namespace or its members.
Name | Value |
---|---|
Scope | Major |
Version | 4.5 |
Type | Runtime |
Affected APIs
Printing
Data written to PrintSystemJobInfo.JobStream must be in XPS format
Details
The JobStream property exposes the stream of a print job. The user can send raw data to the underlying operating system printing components by writing to this stream.Starting with the .NET Framework 4.5 on Windows 8 and later versions of the Windows operating system, data written to this stream must be in XPS format as a package stream.
Suggestion
To output print content, you can do either of the following:
- Use the XpsDocumentWriter class to output print content. This is the recommended alternative.
- Ensure that the data sent to the stream returned by the JobStream property is in XPS format as a package stream.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
Security
RSACng.VerifyHash now returns False for any verification failure
Details
Starting with the .NET Framework 4.6.2, this method returns False if the signature itself is badly formatted. It now returns false for any verification failure.In the .NET Framework 4.6 and 4.6.1, the method throws a System.Security.Cryptography.CryptographicException if the signature itself is badly formatted.
Suggestion
Any code whose execution depends on handling the System.Security.Cryptography.CryptographicException should instead execute if validation fails and the method returns False.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6.2 |
Type | Runtime |
Affected APIs
SignedXml and EncryptedXml Breaking Changes
Details
In .NET Framework 4.6.2, security fixes in System.Security.Cryptography.Xml.SignedXml and System.Security.Cryptography.Xml.EncryptedXml lead to different run-time behaviors. For example:
- If a document has multiple elements with the same
id
attribute and a signature targets one of those elements as the root of the signature, the document will now be considered invalid. - Documents using non-canonical XPath transform algorithms in references are now considered invalid.
- Documents using non-canonical XSLT transform algorithms in references are now consider invalid.
- Any program making use of external resource detached signatures will be unable to do so.
Suggestion
Developers might want to review the usage of XmlDsigXsltTransform and XmlDsigXsltTransform, as well as types derived from Transform since a document receiver may not be able to process it.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6.2 |
Type | Runtime |
Affected APIs
- System.Security.Cryptography.Xml.Transform
- System.Security.Cryptography.Xml.XmlDsigXPathTransform
- System.Security.Cryptography.Xml.XmlDsigXsltTransform
Serialization
BinaryFormatter can fail to find type from LoadFrom context
Details
As of .NET Framework 4.5, a number of System.Xml.Serialization.XmlSerializer changes may cause differences in deserialization when using System.Runtime.Serialization.Formatters.Binary.BinaryFormatter to deserialize types that had been loaded in the LoadFrom context. These changes are due to the new ways System.Xml.Serialization.XmlSerializer now loads a type which causes different behavior when a System.Runtime.Serialization.Formatters.Binary.BinaryFormatter attempts to deserialize to that type later on. The default serialization binder does not automatically search the LoadFrom context, although it may have worked in some circumstances based on the old behavior of XmlSerializer. Due to the changes, when a type is being loaded from an assembly loaded in a different context, a System.IO.FileNotFoundException may be thrown.
Warning
Binary serialization can be dangerous. For more information, see BinaryFormatter security guide.
Suggestion
If this exception is seen, the Binder
property of the System.Runtime.Serialization.Formatters.Binary.BinaryFormatter can be set to a custom binder that will find the correct type.
var formatter = new BinaryFormatter { Binder = new TypeFinderBinder() }
And then the custom binder:public class TypeFinderBinder : SerializationBinder
{
private static readonly string s_assemblyName = Assembly.GetExecutingAssembly().FullName;
public override Type BindToType(string assemblyName, string typeName)
{
return Type.GetType(String.Format(CultureInfo.InvariantCulture, "{0}, {1}", typeName, s_assemblyName));
}
}
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
- System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
- BinaryFormatter.Deserialize(Stream)
- BinaryFormatter.Deserialize(Stream, HeaderHandler)
Exception message has changed for failed DataContract serialization in case of an unknown type
Details
Beginning in the .NET Framework 4.6, the exception message given if a System.Runtime.Serialization.DataContractSerializer or System.Runtime.Serialization.Json.DataContractJsonSerializer fails to serialize or deserialize due to missing 'known types' has been clarified.
Suggestion
Apps should not depend on specific exception messages. If an app depends on this message, either update it to expect the new message or (preferably) change it to depend only on the exception type.
Name | Value |
---|---|
Scope | Edge |
Version | 4.6 |
Type | Runtime |
Affected APIs
- DataContractJsonSerializer(Type)
- DataContractJsonSerializer(Type, IEnumerable<Type>)
- DataContractJsonSerializer(Type, DataContractJsonSerializerSettings)
- DataContractJsonSerializer(Type, String)
- DataContractJsonSerializer(Type, String, IEnumerable<Type>)
- DataContractJsonSerializer(Type, XmlDictionaryString)
- DataContractJsonSerializer(Type, XmlDictionaryString, IEnumerable<Type>)
- DataContractJsonSerializer(Type, IEnumerable<Type>, Int32, Boolean, IDataContractSurrogate, Boolean)
- DataContractJsonSerializer(Type, String, IEnumerable<Type>, Int32, Boolean, IDataContractSurrogate, Boolean)
- DataContractJsonSerializer(Type, XmlDictionaryString, IEnumerable<Type>, Int32, Boolean, IDataContractSurrogate, Boolean)
- DataContractSerializer(Type)
- DataContractSerializer(Type, DataContractSerializerSettings)
- DataContractSerializer(Type, IEnumerable<Type>)
- DataContractSerializer(Type, String, String)
- DataContractSerializer(Type, String, String, IEnumerable<Type>)
- DataContractSerializer(Type, XmlDictionaryString, XmlDictionaryString)
- DataContractSerializer(Type, XmlDictionaryString, XmlDictionaryString, IEnumerable<Type>)
- DataContractSerializer(Type, IEnumerable<Type>, Int32, Boolean, Boolean, IDataContractSurrogate)
- DataContractSerializer(Type, IEnumerable<Type>, Int32, Boolean, Boolean, IDataContractSurrogate, DataContractResolver)
- DataContractSerializer(Type, String, String, IEnumerable<Type>, Int32, Boolean, Boolean, IDataContractSurrogate)
- DataContractSerializer(Type, String, String, IEnumerable<Type>, Int32, Boolean, Boolean, IDataContractSurrogate, DataContractResolver)
- DataContractSerializer(Type, XmlDictionaryString, XmlDictionaryString, IEnumerable<Type>, Int32, Boolean, Boolean, IDataContractSurrogate)
- DataContractSerializer(Type, XmlDictionaryString, XmlDictionaryString, IEnumerable<Type>, Int32, Boolean, Boolean, IDataContractSurrogate, DataContractResolver)
NetDataContractSerializer fails to deserialize a ConcurrentDictionary serialized with a different .NET version
Details
By design, the System.Runtime.Serialization.NetDataContractSerializer can be used only if both the serializing and deserializing ends share the same CLR types. Therefore, it is not guaranteed that an object serialized with one version of the .NET Framework can be deserialized by a different version.System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue> is a type that is known to not to deserialize correctly if serialized with the .NET Framework 4.5 or earlier and deserialized with the .NET Framework 4.5.1 or later.
Suggestion
There are a number of possible work-arounds for this issue:
- Upgrade the serializing computer to use the .NET Framework 4.5.1, as well.
- Use System.Runtime.Serialization.DataContractSerializer instead of System.Runtime.Serialization.NetDataContractSerializer as this does not expect the exact same CLR types at both serializing and deserializing ends.
- Use System.Collections.Generic.Dictionary<TKey,TValue> instead of System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue> since it does not exhibit this particular 4.5->4.5.1 break.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5.1 |
Type | Runtime |
Affected APIs
SoapFormatter cannot deserialize Hashtable and similar ordered collection objects
Details
The System.Runtime.Serialization.Formatters.Soap.SoapFormatter does not guarantee that objects serialized under one .NET Framework version will successfully deserialize under a different version. Specifically, some ordered collections (like System.Collections.Hashtable) added members between 4.0 and 4.5 such that objects of these types cannot deserialize with .NET Framework 4.0 if they were serialized with .NET Framework 4.5. Note that if the serialized data is both serialized and deserialized with the same .NET Framework version, no issue will occur.
Suggestion
System.Runtime.Serialization.Formatters.Soap.SoapFormatter serialization should be replaced with System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serialization or System.Runtime.Serialization.NetDataContractSerializer to be resilient to .NET Framework changes.
Warning
Binary serialization can be dangerous. For more information, see BinaryFormatter security guide.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
- SoapFormatter.Serialize(Stream, Object)
- SoapFormatter.Serialize(Stream, Object, Header[])
- SoapFormatter.Deserialize(Stream)
- SoapFormatter.Deserialize(Stream, HeaderHandler)
XmlSerializer fails while serializing a type that hides an accessible member with an inaccessible one
Details
When serializing a derived type, the System.Xml.Serialization.XmlSerializer can fail if the type contains an inaccessible field or property that hides (via the 'new' keyword) a field or property of the same name that was previously accessible (public, for example) on the base type.
Suggestion
This problem can be solved by making the new, hiding member accessible to the System.Xml.Serialization.XmlSerializer (by marking it public, for example).Alternatively, the following config setting will revert to 4.0 System.Xml.Serialization.XmlSerializer behavior, which will fix the problem:
<system.xml.serialization>
<xmlSerializer useLegacySerializerGeneration="true" />
</system.xml.serialization>
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
- XmlSerializer.Serialize(Stream, Object)
- XmlSerializer.Serialize(TextWriter, Object)
- XmlSerializer.Serialize(Object, XmlSerializationWriter)
- XmlSerializer.Serialize(XmlWriter, Object)
- XmlSerializer.Serialize(Stream, Object, XmlSerializerNamespaces)
- XmlSerializer.Serialize(TextWriter, Object, XmlSerializerNamespaces)
- XmlSerializer.Serialize(XmlWriter, Object, XmlSerializerNamespaces)
- XmlSerializer.Serialize(XmlWriter, Object, XmlSerializerNamespaces, String)
- XmlSerializer.Serialize(XmlWriter, Object, XmlSerializerNamespaces, String, String)
Setup and Deployment
Product versioning changes in the .NET Framework 4.6 and later versions
Details
Product versioning has changed from the previous releases of the .NET Framework, and particularly from the .NET Framework 4, 4.5, 4.5.1, and 4.5.2. The following are the detailed changes:
- The value of the
Version
entry in theHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
key has changed to4.6.xxxxx
for the .NET Framework 4.6 and its point releases, and to4.7.xxxxx
for the .NET Framework 4.7 and 4.7.1. In the .NET Framework 4.5, 4.5.1, and 4.5.2, it had the format4.5.xxxxx
. - The file and product versioning for .NET Framework files has changed from the earlier versioning scheme of 4.0.30319.x to 4.6.X.0 for the .NET Framework 4.6 and its point releases, and to 4.7.X.0 for the .NET Framework 4.7 and 4.7.1. You can see these new values when you view the file's Properties after right-clicking on a file.
- The AssemblyFileVersionAttribute and AssemblyInformationalVersionAttribute attributes for managed assemblies have Version values in the form 4.6.X.0 for the .NET Framework 4.6 and its point releases, and 4.7.X.0 for the .NET Framework 4.7 and 4.7.1.
- In the .NET Framework 4.6, 4.6.1, 4.6.2, 4.7, and 4.7.1, the Environment.Version property returns the fixed version string
4.0.30319.42000
. In the .NET Framework 4, 4.5, 4.5.1, and 4.5.2, it returns version strings in the format4.0.30319.xxxxx
(for example, "4.0.30319.18010"). Note that we do not recommend application code taking any new dependency on the Environment.Version property.
For more information, see How to: Determine which .NET Framework Versions Are Installed.
Suggestion
In general, applications should depend on the recommended techniques for detecting such things as the runtime version of the .NET Framework and the installation directory:
- To detect the runtime version of the .NET Framework, see How to: Determine Which .NET Framework Versions Are Installed.
- To determine the installation path for the .NET Framework, use the value of the
InstallPath
entry in theHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
key.
Important
The subkey name is NET Framework Setup
, not .NET Framework Setup
.
- To determine the directory path to the .NET Framework common language runtime, call the RuntimeEnvironment.GetRuntimeDirectory() method.
- To get the CLR version, call the RuntimeEnvironment.GetSystemVersion() method. For the .NET Framework 4 and its point releases (the .NET Framework 4.5, 4.5.1, 4.5.2, and .NET Framework 4.6, 4.6.1, 4.6.2, 4.7, and 4.7.1), it returns the string v4.0.30319.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
The .NET Framework 4.6 does not use a 4.5.x.x version when registering itself in the registry
Details
As one might expect, the version key set in the registry (at HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\NET Framework Setup\NDP\v4\Full
) for the .NET Framework 4.6 begins with '4.6', not '4.5'. Apps that depend on these registry keys to know which .NET Framework versions are installed on a machine should be updated to understand that 4.6 is a new possible version, and one that is compatible with previous 4.5.x releases.
Suggestion
Update apps probing for a .NET Framework 4.5 install by looking for 4.5 registry keys to also accept 4.6.
Name | Value |
---|---|
Scope | Edge |
Version | 4.6 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Tools
Contract.Invariant or Contract.Requires<TException> do not consider String.IsNullOrEmpty to be pure
Details
For apps that target the .NET Framework 4.6.1, if the invariant contract for Contract.Invariant or the precondition contract for Requires calls the String.IsNullOrEmpty method, the rewriter emits compiler warning CC1036: "Detected call to method 'System.String.IsNullOrWhiteSpace(System.String)' without [Pure] in method." This is a compiler warning rather than a compiler error.
Suggestion
This behavior was addressed in GitHub Issue #339. To eliminate this warning, you can download and compile an updated version of the source code for the Code Contracts tool from GitHub. Download information is found at the bottom of the page.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6.1 |
Type | Runtime |
Affected APIs
Web Applications
Managed browser hosting controls from the .NET Framework 1.1 and 2.0 are blocked
Details
Hosting these controls is blocked in Internet Explorer.
Suggestion
Internet Explorer will fail to launch an application that uses managed browser hosting controls. The previous behavior can be restored by setting the EnableIEHosting value of the registry subkey HKLM/SOFTWARE/MICROSOFT/.NETFramework
to 1
for x86 systems and for 32-bit processes on x64 systems, and by setting the EnableIEHosting
value of the registry subkey HKLM/SOFTWARE/Wow6432Node/Microsoft/.NETFramework
to 1
for 64-bit processes on x64 systems.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Windows Communication Foundation (WCF)
Error codes for maxRequestLength or maxReceivedMessageSize are different
Details
Messages in WCF web services hosted in Internet Information Services (IIS) or ASP.NET Development Server that exceed maxRequestLength (in ASP.NET) or maxReceivedMessageSize (in WCF) have different error codeThe HTTP status code has changed from 400 (Bad Request) to 413 (Request Entity Too Large), and messages that exceed either the maxRequestLength or the maxReceivedMessageSize setting throw a System.ServiceModel.ProtocolException exception. This includes cases in which the transfer mode is Streamed.
Suggestion
This change facilitates debugging in cases where the message length exceeds the limits allowed by ASP.NET or WCF.You must modify any code that performs processing based on an HTTP 400 status code.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
MinFreeMemoryPercentageToActiveService is now respected
Details
This setting establishes the minimum memory that must be available on the server before a WCF service can be activated. It is designed to prevent System.OutOfMemoryException exceptions. In the .NET Framework 4.5, this setting had no effect. In the .NET Framework 4.5.1, the setting is observed.
Suggestion
An exception occurs if the free memory available on the web server is less than the percentage defined by the configuration setting. Some WCF services that successfully started and ran in a constrained memory environment may now fail.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5.1 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Remove Ssl3 from the WCF TransportDefaults
Details
When using NetTcp with transport security and a credential type of certificate, the SSL 3 protocol is no longer a default protocol used for negotiating a secure connection. In most cases there should be no impact to existing apps as TLS 1.0 has always been included in the protocol list for NetTcp. All existing clients should be able to negotiate a connection using at least TLS1.0.
Suggestion
If Ssl3 is required, use one of the following configuration mechanisms to add Ssl3 to the list of negotiated protocols.
Name | Value |
---|---|
Scope | Edge |
Version | 4.6.2 |
Type | Runtime |
Affected APIs
System.ServiceModel.Web.WebServiceHost object no longer adds a default endpoint
Details
The WebServiceHost object no longer adds a default endpoint if an explicit endpoint has been added by application code.
Suggestion
If users will expect to be able to connect to a default endpoint and other explicit endpoints have been added to the System.ServiceModel.Web.WebServiceHost, default endpoints should also be added explicitly (using System.ServiceModel.ServiceHostBase.AddDefaultEndpoints()).
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
- ServiceHost.AddServiceEndpoint(Type, Binding, String)
- ServiceHost.AddServiceEndpoint(Type, Binding, Uri)
- ServiceHost.AddServiceEndpoint(Type, Binding, String, Uri)
- ServiceHost.AddServiceEndpoint(Type, Binding, Uri, Uri)
- ServiceHost.AddServiceEndpoint(Type, Binding, Uri, Uri)
- ServiceHostBase.AddServiceEndpoint(ServiceEndpoint)
- ServiceHostBase.AddServiceEndpoint(String, Binding, String)
- ServiceHostBase.AddServiceEndpoint(String, Binding, Uri)
- ServiceHostBase.AddServiceEndpoint(String, Binding, String, Uri)
- ServiceHostBase.AddServiceEndpoint(String, Binding, Uri, Uri)
The Replace method in OData URLs is disabled by default
Details
Beginning in the .NET Framework 4.5, the Replace method in OData URLs is disabled by default. When OData Replace is disabled (now by default), any user requests including replace functions (which are uncommon) will fail.
Suggestion
If the replace method is required (which is uncommon), it can be re-enabled through a config settings (System.Data.Services.Configuration.DataServicesFeaturesSection.ReplaceFunction). However, an enabled replace method can open security vulnerabilities and should only be used after careful review.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
WCF AddressHeaderCollection now throws an ArgumentException if an addressHeader element is null
Details
Starting with the .NET Framework 4.7.1, the AddressHeaderCollection(IEnumerable<AddressHeader>) constructor throws an ArgumentException if one of the elements is null
. In the .NET Framework 4.7 and earlier versions, no exception is thrown.
Suggestion
If you encounter compatibility issues with this change on the .NET Framework 4.7.1 or a later version, you can opt-out of it by adding the following line to the <runtime>
section of the app.config file:
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.ServiceModel.DisableAddressHeaderCollectionValidation=true" />
</runtime>
</configuration>
Name | Value |
---|---|
Scope | Minor |
Version | 4.7.1 |
Type | Runtime |
Affected APIs
WCF MsmqSecureHashAlgorithm default value is now SHA256
Details
Starting with the .NET Framework 4.7.1, the default message signing algorithm in WCF for Msmq messages is SHA256. In the .NET Framework 4.7 and earlier versions, the default message signing algorithm is SHA1.
Suggestion
If you run into compatibility issues with this change on the .NET Framework 4.7.1 or later, you can opt-out the change by adding the following line to the <runtime>
section of your app.config file:
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.ServiceModel.UseSha1InMsmqEncryptionAlgorithm=true" />
</runtime>
</configuration>
Name | Value |
---|---|
Scope | Minor |
Version | 4.7.1 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
WCF PipeConnection.GetHashAlgorithm now uses SHA256
Details
Starting with the .NET Framework 4.7.1, Windows Communication Foundation uses a SHA256 hash to generate random names for named pipes. In the .NET Framework 4.7 and earlier versions, it used a SHA1 hash.
Suggestion
If you run into compatibility issue with this change on the .NET Framework 4.7.1 or later, you can opt-out it by adding the following line to the <runtime>
section of your app.config file:
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.ServiceModel.UseSha1InPipeConnectionGetHashAlgorithm=true" />
</runtime>
</configuration>
Name | Value |
---|---|
Scope | Minor |
Version | 4.7.1 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
WCF services that use NETTCP with SSL security and MD5 certificate authentication
Details
The .NET Framework 4.6 adds TLS 1.1 and TLS 1.2 to the WCF SSL default protocol list. When both client and server machines have the .NET Framework 4.6 or later installed, TLS 1.2 is used for negotiation.TLS 1.2 does not support MD5 certificate authentication. As a result, if a customer uses an MD5 certificate, the WCF client will fail to connect to the WCF service.
Suggestion
You can work around this issue so that a WCF client can connect to a WCF server by doing any of the following:
- Update the certificate to not use the MD5 algorithm. This is the recommended solution.
- If the binding is not dynamically configured in source code, update the application's configuration file to use TLS 1.1 or an earlier version of the protocol. This allows you to continue to use a certificate with the MD5 hash algorithm.
Warning
This workaround is not recommended, since a certificate with the MD5 hash algorithm is considered insecure.
The following configuration file does this:
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding>
<security mode= "None/Transport/Message/TransportWithMessageCredential" >
<transport clientCredentialType="None/Windows/Certificate"
protectionLevel="None/Sign/EncryptAndSign"
sslProtocols="Ssl3/Tls1/Tls11">
</transport>
</security>
</binding>
</netTcpBinding>
</bindings>
</system.ServiceModel>
</configuration>
- If the binding is dynamically configured in source code, update the TcpTransportSecurity.SslProtocols property to use TLS 1.1 (SslProtocols.Tls11 or an earlier version of the protocol in the source code.
Warning
This workaround is not recommended, since a certificate with the MD5 hash algorithm is considered insecure.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Windows Forms
PreviewLostKeyboardFocus is called repeatedly if its handler shows a Windows Forms message box
Details
Beginning in the .NET Framework 4.5, calling MessageBox.Show from a PreviewLostKeyboardFocus handler will cause the handler to re-fire when the message box is closed, potentially resulting in an infinite loop of message boxes.
Suggestion
There are two options to work around this issue:
- It may be avoided by calling MessageBox.Show instead of MessageBox.Show.
- It may be avoided by showing the message box from a LostKeyboardFocus event handler (as opposed to a System.Windows.UIElement.PreviewLostKeyboardFocus event handler).
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
- ContentElement.PreviewLostKeyboardFocus
- IInputElement.PreviewLostKeyboardFocus
- UIElement.PreviewLostKeyboardFocus
- UIElement3D.PreviewLostKeyboardFocus
WinForm's CheckForOverflowUnderflow property is now true for System.Drawing
Details
The CheckForOverflowUnderflow property for the System.Drawing.dll assembly is set to true.
Suggestion
Previously when overflows occurred, the result would be silently truncated. Now an System.OverflowException exception is thrown.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Windows Presentation Foundation (WPF)
Chained Popups with StaysOpen=False
Details
A Popup with StaysOpen=False is supposed to close when you click outside the Popup. When two or more such Popups are chained (i.e. one contains another), there were many problems, including:
- Open two levels, click outside P2 but inside P1. Nothing happens.
- Open two levels, click outside P1. Both popups close.
- Open and close two levels. Then try to open P2 again. Nothing happens.
- Try to open three levels. You can't. (Either nothing happens or the first two levels close, depending on where you click.)
These cases (and other variants) now work as expected.
Name | Value |
---|---|
Scope | Edge |
Version | 4.7.1 |
Type | Runtime |
Affected APIs
Changing the IsEnabled property of the parent of a TextBlock control affects any child controls
Details
Starting with the .NET Framework 4.6.2, changing the System.Windows.UIElement.IsEnabled property of the parent of a System.Windows.Controls.TextBlock control affects any child controls (such as hyperlinks and buttons) of the System.Windows.Controls.TextBlock control.In the .NET Framework 4.6.1 and earlier versions, controls inside a System.Windows.Controls.TextBlock did not always reflect the state of the System.Windows.UIElement.IsEnabled property of the System.Windows.Controls.TextBlock parent.
Suggestion
None. This change conforms to the expected behavior for controls inside a System.Windows.Controls.TextBlock control.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6.2 |
Type | Runtime |
Affected APIs
FlowDocument may show an extra line of text
Details
In some cases, a FlowDocument element will display an extra line of text when running on the .NET Framework 4.5 compared to how it displayed when run on the .NET Framework 4.0. There are no known cases of the change causing any text to be displayed poorly or illegibly, but it could cause text to appear that previously was omitted from a FlowDocument's view.
Suggestion
In some cases, decreasing the display element's PageHeight property by one can restore the previous number of displayed lines.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
GlyphRun.ComputeInkBoundingBox() and FormattedText.Extent return different values beginning in .NET Framework 4.5
Details
Improvements were made to ComputeInkBoundingBox() and Extent in the .NET Framework 4.5 to address issues where the boxes were too small for the contained glyphs in some cases in the .NET Framework 4.0. As a result of this, some bounding boxes will be larger beginning in the .NET Framework 4.5, resulting in subtle differences in UI layout.
Suggestion
Be aware that some glyph bounding box sizes have increased. These changes will usually improve presentation and hit box testing, but if the older (pre-.NET 4.5) behavior is desired, it can be opted into by adding the following entry to the app.config file:
<appsettings>
<add key="IncludeAllInkInBoundingBox" value="false">
</appsettings>
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Horizontal scrolling and virtualization
Details
This change applies to an System.Windows.Controls.ItemsControl that does its own virtualization in the direction orthogonal to the main scrolling direction (the chief example is System.Windows.Controls.DataGrid with EnableColumnVirtualization="True"). The outcome of certain horizontal scrolling operations has been changed to produce results that are more intuitive and more analogous to the results of comparable vertical operations.
The operations include "Scroll Here" and "Right Edge", to use the names from the menu obtained by right-clicking a horizontal scrollbar. Both of these compute a candidate offset and call SetHorizontalOffset(Double).After scrolling to the new offset, the notion of "here" or "right edge" may have changed because newly de-virtualized content has changed the value of System.Windows.Controls.Primitives.IScrollInfo.ExtentWidth.Prior to .NET Framework 4.6.2, the scroll operation simply uses the candidate offset, even though it may not be "here" or at the "right edge" any more. This results in effects like "bouncing" the scroll thumb, best illustrated by example. Suppose a System.Windows.Controls.DataGrid has ExtentWidth=1000 and Width=200. A scroll to "Right Edge" uses candidate offset 1000 - 200 = 800. While scrolling to that offset, new columns are de- virtualized; let's suppose they are very wide, so that the System.Windows.Controls.Primitives.IScrollInfo.ExtentWidth changes to 2000. The scroll ends with HorizontalOffset=800, and the thumb "bounces" back to near the middle of the scrollbar - precisely at 800/2000 = 40%.The change is to recompute a new candidate offset when this situation occurs, and try again. (This is how vertical scrolling works already.) The change produces a more predictable and intuitive experience for the end user, but it could also affect any app that depends on the exact value of System.Windows.Controls.Primitives.IScrollInfo.HorizontalOffset after a horizontal scroll, whether invoked by the end user or by an explicit call to SetHorizontalOffset(Double).Suggestion
An app that uses a predicted value for System.Windows.Controls.Primitives.IScrollInfo.HorizontalOffset should be changed to fetch the actual value (and the value of System.Windows.Controls.Primitives.IScrollInfo.ExtentWidth) after any horizontal scroll that could change System.Windows.Controls.Primitives.IScrollInfo.ExtentWidth due to de-virtualization.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6.2 |
Type | Runtime |
Affected APIs
New enum values in WPF's PageRangeSelection
Details
Two new members (System.Windows.Controls.PageRangeSelection.CurrentPage and System.Windows.Controls.PageRangeSelection.SelectedPages) have been added to the System.Windows.Controls.PageRangeSelection enum.
Suggestion
In most cases, these changes won't impact user code. Code that depends on a particular number of elements existing in GetNames(Type) or GetValues(Type) calls on the System.Windows.Controls.PageRangeSelection type should be modified, though.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
PreviewLostKeyboardFocus is called repeatedly if its handler shows a Windows Forms message box
Details
Beginning in the .NET Framework 4.5, calling MessageBox.Show from a PreviewLostKeyboardFocus handler will cause the handler to re-fire when the message box is closed, potentially resulting in an infinite loop of message boxes.
Suggestion
There are two options to work around this issue:
- It may be avoided by calling MessageBox.Show instead of MessageBox.Show.
- It may be avoided by showing the message box from a LostKeyboardFocus event handler (as opposed to a System.Windows.UIElement.PreviewLostKeyboardFocus event handler).
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
- ContentElement.PreviewLostKeyboardFocus
- IInputElement.PreviewLostKeyboardFocus
- UIElement.PreviewLostKeyboardFocus
- UIElement3D.PreviewLostKeyboardFocus
WPF DataTemplate elements are now visible to UIA
Details
Previously, System.Windows.DataTemplate elements were invisible to UI Automation. Beginning in 4.5, UI Automation will detect these elements. This is useful in many cases, but can break tests that depend on UIA trees not containing System.Windows.DataTemplate elements.
Suggestion
UI Automation tests for this app may need updated to account for the UIA tree now including previously invisible System.Windows.DataTemplate elements. For example, tests that expect some elements to be next to each other may now need to expect previously invisible UIA elements in between. Or tests that rely on certain counts or indexes for UIA elements may need updated with new values.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
WPF DispatcherSynchronizationContext.CreateCopy now returns a new copy instead of the current instance
Details
In the .NET Framework 4, CreateCopy() returned a reference to the current instance, primarily as a performance optimization. In the .NET Framework 4.5, it returns a new instance which makes it possible for the first time to conclude that equal references indicate the executing thread is in the correct synchronization context. It is unlikely that code that checks the identity of these references will be affected, but because of the change, code that calls CreateCopy() should be tested as part of migration to the .NET Framework 4.5 or newer.
Suggestion
Be aware that CreateCopy() will now return a new System.Threading.SynchronizationContext object. Previously, code that used equivalence of references generated this way was not actually checking whether it was in the proper context, but does when built against .NET Framework 4.5 or later. While unlikely to cause issues, exercising the affected code paths should be enough to determine if this poses any problem.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
WPF Printing Stack Update
Details
WPF's Printing APIs using System.Printing.PrintQueue now call Window's Print Document Package API in favor of the now deprecated XPS Print API. The change was made with serviceability in mind; neither users nor developers should see any changes in behavior or API usage. The new printing stack is enabled by default when running in Windows 10 Creators Update. The old printing stack will still continue to work just as before in older Windows versions.
Suggestion
To use the old stack in Windows 10 Creators Update, set the UseXpsOMPrinting
REG_DWORD value of the HKEY_CURRENT_USER\Software\Microsoft\.NETFramework\Windows Presentation Foundation\Printing
registry key to 1
.
Name | Value |
---|---|
Scope | Edge |
Version | 4.7 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
WPF spell checking in text-enabled controls will not work in Windows 10 for languages not in the OS's input language list
Details
When running on Windows 10, the spell checker may not work for WPF text-enabled controls because platform spell-checking capabilities are available only for languages present in the input languages list.In Windows 10, when a language is added to the list of available keyboards, Windows automatically downloads and installs a corresponding Feature on Demand (FOD) package that provides spell-checking capabilities. By adding the language to the input languages list, the spell checker will be supported.
Suggestion
Be aware that the language or text to be spell-checked must be added as an input language for spell-checking to work in Windows 10.
Name | Value |
---|---|
Scope | Edge |
Version | 4.6 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
WPF TextBox defaults to undo limit of 100
Details
In .NET Framework 4.5, the default undo limit for a WPF textbox is 100 (as opposed to being unlimited in .NET Framework 4.0)
Suggestion
If an undo limit of 100 is too low, the limit can be set explicitly with UndoLimit
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
WPF TextBox selected text appears a different color when the text box is inactive
Details
In .NET Framework 4.5, when a WPF text box control is inactive (it doesn't have focus), the selected text inside the box will appear a different color than when the control is active.
Suggestion
The previous (.NET Framework 4.0) behavior may be restored by setting the AreInactiveSelectionHighlightBrushKeysSupported property to false
.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
WPF TreeViewItem must be used within a TreeView
Details
A change was introduced in 4.5 that restricts usage of System.Windows.Controls.TreeViewItem elements outside of a System.Windows.Controls.TreeView. This manifests under the following conditions:
- System.Windows.Controls.TreeViewItem's visual parent is not a panel. (A System.Windows.Controls.TreeViewItem generated for a System.Windows.Controls.TreeView will have a panel as its parent)
- The System.Windows.Controls.TreeViewItem is a descendant of a System.Windows.Controls.VirtualizingStackPanel acting as the "items host" for a list control (ListBox, DataGrid, ListView, etc.). Virtualization doesn't need to be enabled.
- The System.Windows.Controls.VirtualizingStackPanel is item-scrolling (
ScrollUnit="Item"
). - Someone calls
VirtualizingStackPanel.MakeVisible(v)
to scroll an elementv
into view. This can be done explicitly, or implicitly in a number of ways; perhaps the most common way is simply clicking onv
to give it the keyboard focus. - The visual-parent chain from
v
to the System.Windows.Controls.VirtualizingStackPanel passes through the System.Windows.Controls.TreeViewItem.
In other words, this is seen when a System.Windows.Controls.TreeViewItem is used outside of a System.Windows.Controls.TreeView, and the user clicks on a descendant of the System.Windows.Controls.TreeViewItem to bring it into view. If the System.Windows.Controls.TreeViewItem has no focusable descendants, you'll never see this issue. An example of a situation where this is hit is when a System.Windows.Controls.TreeViewItem is the root of a DataTemplate. When this issue is hit, there is an InvalidCastException that occurs within the WPF framework.
Suggestion
A hotfix will be made available for this.
Name | Value |
---|---|
Scope | Minor |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
WPF windows are rendered without clipping when extending outside a single monitor
Details
In the .NET Framework 4.6 running on Windows 8 and above, the entire window is rendered without clipping when it extends outside of single display in a multi-monitor scenario. This is different from previous versions of the .NET Framework which would clip WPF windows that extended beyond a single display.
Suggestion
This behavior (whether to clip or not) can be explicitly set using the <EnableMultiMonitorDisplayClipping>
element in <appSettings>
in an application's configuration file, or by setting the EnableMultiMonitorDisplayClipping
property at app startup.
Name | Value |
---|---|
Scope | Minor |
Version | 4.6 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Windows Workflow Foundation (WF)
System.Activities is now APTCA
Details
The assembly is marked with the System.Security.AllowPartiallyTrustedCallersAttribute attribute.
Suggestion
Derived classes cannot be marked with the System.Security.SecurityCriticalAttribute. Previously, derived types had to be marked with the System.Security.SecurityCriticalAttribute. However, this change should have no real impact.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
WF serializes Expressions.Literal<T> DateTimes differently now (breaks custom XAML parsers)
Details
The associated ValueSerializer object will convert a System.DateTime or System.DateTimeOffset object whose Second and System.DateTime.Millisecond components are non-zero and (for a System.DateTime value) whose Kind property is not Unspecified to property element syntax instead of a string. This change allows System.DateTime and System.DateTimeOffset values to be round-tripped. Custom XAML parsers that assume that input XAML is in the attribute syntax will not function correctly.
Suggestion
This change allows System.DateTime and System.DateTimeOffset values to be round-tripped. Custom XAML parsers that assume that input XAML is in the attribute syntax will not function correctly.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
Workflow now throws original exception instead of NullReferenceException in some cases
Details
In the .NET Framework 4.6.2 and earlier versions, when the Execute method of a workflow activity throws an exception with a null
value for the Message property, the System.Activities Workflow runtime throws a System.NullReferenceException, masking the original exception.In the .NET Framework 4.7, the previously masked exception is thrown.
Suggestion
If your code relies on handling the System.NullReferenceException, change it to catch the exceptions that could be thrown from your custom activities.
Name | Value |
---|---|
Scope | Minor |
Version | 4.7 |
Type | Runtime |
Affected APIs
- CodeActivity.Execute(CodeActivityContext)
- AsyncCodeActivity.BeginExecute(AsyncCodeActivityContext, AsyncCallback, Object)
- AsyncCodeActivity<TResult>.BeginExecute(AsyncCodeActivityContext, AsyncCallback, Object)
- WorkflowInvoker.Invoke()
Workflow SQL persistence adds primary key clusters and disallows null values in some columns
Details
Starting with the .NET Framework 4.7, the tables created for the SQL Workflow Instance Store (SWIS) by the SqlWorkflowInstanceStoreSchema.sql script use clustered primary keys. Because of this, identities do not support null
values. The operation of SWIS is not impacted by this change. The updates were made to support SQL Server Transactional Replication.
Suggestion
The SQL file SqlWorkflowInstanceStoreSchemaUpgrade.sql must be applied to existing installations in order to experience this change. New database installations will automatically have the change.
Name | Value |
---|---|
Scope | Edge |
Version | 4.7 |
Type | Runtime |
Affected APIs
Not detectable via API analysis.
XML, XSLT
XmlSchemaException now sets line positions properly
Details
If the SetLineInfo value is passed to the Load method and a validation error occurs, the LineNumber and LinePosition properties now contain line information.
Suggestion
Exception-handling code that assumes LineNumber and LinePosition will not be set should be updated since these properties will now be set properly when SetLineInfo is used while loading XML.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
XmlTextReader DTD entity expansion is limited to 10,000,000 characters
Details
DTD entity expansion is now limited to 10,000,000 characters. Loading XML files without DTD entity expansion or with limited DTD entity expansion is unaffected. Files with DTD entities that expand to more than 10,000,000 characters fail to load, and now throw an exception.
Suggestion
If the limit of DTD entity expansion is too low 10,000,000, the value can be overridden with the MaxCharactersFromEntities property. An System.Xml.XmlReaderSettings with the proper System.Xml.XmlReaderSettings.MaxCharactersFromEntities value can be passed to XmlReader.Create
that takes System.Xml.XmlReaderSettings (ie. Create(String, XmlReaderSettings))
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
- System.Xml.XmlTextReader
- XmlTextReader()
- XmlTextReader(Stream)
- XmlTextReader(Stream, XmlNameTable)
- XmlTextReader(Stream, XmlNodeType, XmlParserContext)
- XmlTextReader(TextReader)
- XmlTextReader(TextReader, XmlNameTable)
- XmlTextReader(String)
- XmlTextReader(String, Stream)
- XmlTextReader(String, Stream, XmlNameTable)
- XmlTextReader(String, TextReader)
- XmlTextReader(String, TextReader, XmlNameTable)
- XmlTextReader(String, XmlNameTable)
- XmlTextReader(String, XmlNodeType, XmlParserContext)
- XmlTextReader(XmlNameTable)
XSLT forward compat now works
Details
In the .NET Framework 4, XSLT 1.0 forward compatibility had the following issues:
- Loading a style sheet failed if its version was set to 2.0 and the parser encountered an unrecognized XSLT 1.0 construct.
- The
xsl:sort
construct failed to sort data if the style sheet version was set to 1.1.In the .NET Framework 4.5, these issues have been fixed, and XSLT 1.0 forward compatibility mode works properly.
Suggestion
Most apps should be unaffected, however data will be sorted differently in some cases now that xsl:sort is respected. If xsl:sort
is used in 1.1 style sheets, confirm that apps were not depending on the unsorted order of data. If apps rely on the 4.0 sorting behavior, remove xsl:sort
from the style sheet.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
XSLT style sheet exception message changed
Details
In the .NET Framework 4.5, the text of the error message when an XSLT file is too complex is "The style sheet is too complex." In previous versions, the error message was "XSLT compile error." Application code that depends on the text of the error message will no longer work. However, the exception types remain the same, so this change should have no real impact.
Suggestion
Update any app code depending on the exception message from this error condition to expect the new message, or (even better) update the code to depend only on the exception type (System.Xml.Xsl.XsltException), which has not changed.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Runtime |
Affected APIs
- XslCompiledTransform.Load(String)
- XslCompiledTransform.Load(Type)
- XslCompiledTransform.Load(XmlReader)
- XslCompiledTransform.Load(IXPathNavigable)
- XslCompiledTransform.Load(MethodInfo, Byte[], Type[])
- XslCompiledTransform.Load(String, XsltSettings, XmlResolver)
- XslCompiledTransform.Load(XmlReader, XsltSettings, XmlResolver)
- XslCompiledTransform.Load(IXPathNavigable, XsltSettings, XmlResolver)
XML parsing changes
Name | Value |
---|---|
Scope | Minor |
Version | 4.5.2 |
Type | Runtime |
Details
For security reasons, the following changes were introduced into XML parsing APIS:
- XmlReaderSettings.MaxCharactersFromEntities is set to 10 million when XmlReaderSettings is initialized.
- XmlReaderSettings.XmlResolver is set to
null
by default.
Note
XmlReaderSettings is used by all XML parsers, so while this change helps the XmlReader case, it also affects other scenarios.
Suggestion
To revert to the previous behavior, you can set a value in the registry. Add a DWORD value named EnableLegacyXmlSettings
to the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\XML
registry key, and set its value to 1
. You can also add the registry value in the HKEY_CURRENT_USER hive instead.
Affected APIs
In addition, any XML API that depends on XmlResolver, either directly or indirectly, is affected.
Feedback
Submit and view feedback for