Retargeting changes for migration to .NET Framework 4.5.x
This article lists the app compatibility issues that were introduced in .NET Framework 4.5, 4.5.1, and 4.5.2.
.NET Framework 4.5
ASP.NET
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
Apps published with ClickOnce that use a SHA-256 code-signing certificate may fail on Windows 2003
Details
The executable is signed with SHA256. Previously, it was signed with SHA1 regardless of whether the code-signing certificate was SHA-1 or SHA-256. This applies to:
- All applications built with Visual Studio 2012 or later.
- Applications built with Visual Studio 2010 or earlier on systems with the .NET Framework 4.5 present. In addition, if the .NET Framework 4.5 or later is present, the ClickOnce manifest is also signed with SHA-256 for SHA-256 certificates regardless of the .NET Framework version against which it was compiled.
Suggestion
The change in signing the ClickOnce executable affects only Windows Server 2003 systems; they require that KB 938397 be installed. The change in signing the manifest with SHA-256 even when an app targets the .NET Framework 4.0 or earlier versions introduces a runtime dependency on the .NET Framework 4.5 or a later version.
Name | Value |
---|---|
Scope | Edge |
Version | 4.5 |
Type | Retargeting |
Core
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
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+0080
throughU+009F
are not supported. - Comma characters
,
or%2c
are 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 |
Windows Forms
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
Windows Communication Foundation (WCF)
Writing binary output using BodyWriter
Details
If you're deriving from the class System.ServiceModel.Channels.BodyWriter and using the implementation of OnWriteBodyContents(XmlDictionaryWriter writer)
to write binary output, some changes may need to be made when you retarget to .NET Framework 4.5. Check the write state, and if it's WriterState.Start
, emit the Binary
wrapping XML element as shown in the following code snippet.
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
bool wroteStartElement = false;
if (writer.WriteState == WriteState.Start)
{
writer.WriteStartElement("Binary", string.Empty);
wroteStartElement = true;
}
writer.WriteBase64(buffer, offset, count);
if (wroteStartElement)
{
writer.WriteEndElement();
}
}
In addition, if you're deriving from the class System.ServiceModel.Channels.StreamBodyWriter
and have overridden the method OnWriteBodyContents(XmlDictionaryWriter writer)
, some changes may be required. When targeting .NET Framework 4.0, it was necessary to explicitly write the Binary
element when overriding this method. This is no longer needed when you target .NET Framework 4.5, and doing so causes the body to not be written.
Windows Presentation Foundation (WPF)
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
.
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 |
WorkflowDesigner.Load doesn't remove symbol property
Details
When targeting the .NET Framework 4.5 in the workflow designer, and loading a re-hosted 3.5 workflow with the Load() method, a System.Xaml.XamlDuplicateMemberException is thrown while saving the workflow.
Suggestion
This bug only manifests when targeting .NET Framework 4.5 in the workflow designer, so it can be worked around by setting the WorkflowDesigner.Context.Services.GetService<DesignerConfigurationService>().TargetFrameworkName
to the 4.0 .NET Framework.
Alternatively, the issue may be avoided by using the Load(String) method to load the workflow, instead of Load().
Name | Value |
---|---|
Scope | Major |
Version | 4.5 |
Type | Retargeting |
Affected APIs
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 |
.NET Framework 4.5.1
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
Core
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 |
Entity Framework
Building an Entity Framework edmx with Visual Studio 2013 can fail with error MSB4062 if using the EntityDeploySplit or EntityClean tasks
Details
MSBuild 12.0 tools (included in Visual Studio 2013) changed MSBuild file locations, causing older Entity Framework targets files to be invalid. The result is that EntityDeploySplit
and EntityClean
tasks fail because they are unable to find Microsoft.Data.Entity.Build.Tasks.dll
. Note that this break is because of a toolset (MSBuild/VS) change, not because of a .NET Framework change. It will only occur when upgrading developer tools, not when merely upgrading the .NET Framework.
Suggestion
Entity Framework targets files are fixed to work with the new MSBuild layout beginning in the .NET Framework 4.6. Upgrading to that version of the Framework will fix this issue. Alternatively, this workaround can be used to patch the targets files directly.
Name | Value |
---|---|
Scope | Major |
Version | 4.5.1 |
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 |
Windows Presentation Foundation (WPF)
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
.NET Framework 4.5.2
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 Forms
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.
For apps that target the .NET Framework 4.5 or later and run on the .NET Framework 4.5.2, 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
Windows Workflow Foundation (WF)
WorkflowDesigner.Load doesn't remove symbol property
Details
When targeting the .NET Framework 4.5 in the workflow designer, and loading a re-hosted 3.5 workflow with the Load() method, a System.Xaml.XamlDuplicateMemberException is thrown while saving the workflow.
Suggestion
This bug only manifests when targeting .NET Framework 4.5 in the workflow designer, so it can be worked around by setting the WorkflowDesigner.Context.Services.GetService<DesignerConfigurationService>().TargetFrameworkName
to the 4.0 .NET Framework.
Alternatively, the issue may be avoided by using the Load(String) method to load the workflow, instead of Load().
Name | Value |
---|---|
Scope | Major |
Version | 4.5 |
Type | Retargeting |
Affected APIs
Feedback
https://aka.ms/ContentUserFeedback.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see:Submit and view feedback for