{"id":2014,"date":"2012-11-19T10:00:00","date_gmt":"2012-11-19T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/2012\/11\/19\/all-about-httpruntime-targetframework\/"},"modified":"2023-03-09T03:02:26","modified_gmt":"2023-03-09T11:02:26","slug":"all-about-httpruntime-targetframework","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/all-about-httpruntime-targetframework\/","title":{"rendered":"All about"},"content":{"rendered":"<h3>Background \u2013 on quirks and compatibility<\/h3>\n<p>The .NET Framework (including ASP.NET) strives to maintain near-100% compatibility when an existing framework is updated on a machine. We try to ensure as much as possible that if an application was developed and deployed against .NET Framework 4, it will just continue to work on 4.5. This normally means keeping quirky, buggy, or undesirable behaviors in the product between versions, as fixing them may negatively affect applications which were relying on those behaviors.<\/p>\n<p>Consider creating a new Console Application project targeting .NET Framework 4 and putting the following in Program.cs:<\/p>\n<pre class=\"code\">Program\r\n{\r\n   static void Main(string[] args)\r\n    {\r\n        List &lt; int &gt; list = new List &lt; int &gt;() { 1, 2, 3 };\r\n        list.ForEach(i =&gt;\r\n        {\r\n            Console.WriteLine(i);\r\n            if (i &lt; 3) { list.Add(i + 1); }\r\n        });\r\n    }\r\n}<\/pre>\n<p>When run, the output of this application is <strong>1, 2, 3, 2, 3, 3<\/strong>. Now change the project to target .NET Framework 4.5, recompile, and run again. The output is <strong>1<\/strong>, followed by an exception: <em>System.InvalidOperationException: Collection was modified; enumeration operation may not execute.<\/em> What happened?<\/p>\n<p>The contract of <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.collections.ienumerator.movenext.aspx\">IEnumerator.MoveNext()<\/a> specifies that the method shall throw an InvalidOperationException if the underlying collection changes while an enumeration is currently taking place. Indeed, if you use the <em><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ttw7t8t6.aspx\">foreach<\/a><\/em> keyword instead of the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bwabdf9z.aspx\">List&lt;T&gt;.ForEach()<\/a> method in the above sample, you will see the exception thrown regardless of target framework. This discrepancy between the <em>foreach<\/em> keyword and the ForEach() method is one example of a quirk. The feature team wanted to bring the ForEach() method behavior in line with the foreach keyword behavior, but doing so for all applications would have been a breaking change. So they require the application to opt in to the new 4.5 behavior by switching the target framework.<\/p>\n<p>Given that the .NET Framework 4.5 is an in-place update to .NET Framework 4, how is this pulled off? If you look closely at the console application project, you&#8217;ll see that it also contains one additional file <em>App.config<\/em>:<\/p>\n<pre class=\"code\">&lt;configuration &gt;\r\n    &lt; startup &gt; \r\n        &lt; supportedRuntime version = \"v4.0\" sku<\/span><span>=<\/span><span>\"<\/span><span>.NETFramework,Version=v4.0<\/span><span>\"<\/span><span>\/&gt;\r\n    &lt;\/<\/span>startup<span>&gt;\r\n&lt;\/<\/span>configuration<span>&gt;<\/span><\/pre>\n<p>When the application is targeted to 4.5, Visual Studio modifies the configuration file. There are two related concepts in the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/w4atty68.aspx\">&lt;supportedRuntime&gt;<\/a> element: runtime version and target SKU. The .NET Framework 4.5 SKU rides on top of version 4.0 of the CLR, much like how the .NET Framework 3.0 and 3.5 SKUs ride on top of version 2.0 of the CLR.<\/p>\n<pre class=\"code\"><span>&lt;<\/span>configuration<span>&gt;\r\n    &lt;<\/span>startup<span>&gt; \r\n        &lt;<\/span>supportedRuntime <span>version<\/span><span>=<\/span><span>\"<\/span><span >v4.0<\/span><span>\" <\/span><span >sku<\/span><span>=<\/span><span>\"<\/span><span>.NETFramework,Version=v4.5<\/span><span>\"<\/span><span >\/&gt;\r\n    &lt;\/<\/span>startup<span >&gt;\r\n&lt;\/<\/span>configuration<span >&gt;<\/span><\/pre>\n<p>This information is captured into an attribute and compiled into the executable:<\/p>\n<pre class=\"code\"><span>[<\/span><span >assembly<\/span><span>: <\/span>TargetFramework<span>(<\/span>\".NETFramework,Version=v4.5\"<span>, FrameworkDisplayName = <\/span>\".NET Framework 4.5\"<span>)]<\/span><\/pre>\n<p>When a component in the .NET Framework needs to decide whether to apply quirks behavior to a particular code path or whether it should use new 4.5-standards logic, it consults the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.runtime.versioning.targetframeworkattribute.aspx\">[TargetFramework] attribute<\/a> to see what framework version the application targets, hence what logic it expects to take place. (If the attribute is not present, the runtime assumes 4.0 quirks behavior. There is additional fallback and resolution logic, but it&#8217;s not important to the topic at hand.)<\/p>\n<h3>&lt;httpRuntime targetFramework&gt;<\/h3>\n<p>But what if ASP.NET applications want to opt in to the new 4.5 behaviors? ASP.NET developers can&#8217;t use the &lt;supportedRuntime&gt; element since there&#8217;s no .exe the [TargetFramework] attribute can be compiled into. However, we do control the &lt;httpRuntime&gt; element, and we can use its values to make decisions on how we should configure the CLR before loading your application into memory.<\/p>\n<p>To this effect, we introduced the <em><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.web.configuration.httpruntimesection.targetframework.aspx\">targetFramework attribute<\/a><\/em> on the &lt;httpRuntime&gt; element. When you create a new ASP.NET application using the 4.5 project templates, the following line will be present in Web.config:<\/p>\n<pre class=\"code\"><span >&lt;<\/span>httpRuntime <span>targetFramework<\/span><span >=<\/span><span>\"<\/span><span >4.5<\/span><span>\" <\/span><span >\/&gt;<\/span><\/pre>\n<p>The effect of this attribute is twofold. First, it controls the CLR&#8217;s quirks mode behavior, just like the &lt;supportedRuntime&gt; element does in a console application. Consider a handler <em>~\/MyHandler.ashx<\/em> whose contents are similar to the console application above.<\/p>\n<pre class=\"code\"><span>&lt;%<\/span><span >@ <\/span><span>WebHandler <\/span><span>Language<\/span><span >=\"C#\" <\/span><span>Class<\/span><span >=\"MyHandler\" <\/span><span>%&gt;\r\n\r\n<\/span><span >using <\/span><span>System.Collections.Generic;\r\n<\/span><span >using <\/span><span>System.Web;\r\n<\/span><span >public class <\/span>MyHandler <span>: <\/span>IHttpHandler\r\n<span>{\r\n\r\n    <\/span><span >public void <\/span><span>ProcessRequest(<\/span>HttpContext <span>context)\r\n    {\r\n        context.Response.ContentType = <\/span>\"text\/plain\"<span>;\r\n        <\/span>List<span>&lt;<\/span><span >int<\/span><span>&gt; list = <\/span><span >new <\/span>List<span>&lt;<\/span><span >int<\/span><span>&gt;() { 1, 2, 3 };\r\n        list.ForEach(i =&gt;\r\n        {\r\n            context.Response.Write(i + <\/span>\" \"<span>);\r\n            <\/span><span >if <\/span><span>(i &lt; 3) { list.Add(i + 1); }\r\n        });\r\n    }\r\n\r\n    <\/span><span >public bool <\/span><span>IsReusable\r\n    {\r\n        <\/span><span >get <\/span><span>{ <\/span><span >return false<\/span><span>; }\r\n    }\r\n}\r\n<\/span><\/pre>\n<p>If the <em>targetFramework<\/em> attribute reads &#8220;4.0&#8221;, the output will be <strong>1 2 3 2 3 3<\/strong>. If the <em>targetFramework<\/em> attribute reads &#8220;4.5&#8221;, an InvalidOperationException will be thrown due to the collection having been modified during the ForEach() operation.<\/p>\n<p>Second, &lt;httpRuntime targetFramework=&#8221;4.5&#8243; \/&gt; is a shortcut that allows the ASP.NET runtime to infer a wide array of configuration settings. If the runtime sees this setting, it will expand it out just as if you had written the following:<\/p>\n<pre class=\"code\"><span >&lt;<\/span>configuration<span >&gt;\r\n  &lt;<\/span>appSettings<span >&gt;\r\n    &lt;<\/span>add <span>key<\/span><span >=<\/span><span>\"<\/span><span >aspnet:UseTaskFriendlySynchronizationContext<\/span><span>\" <\/span><span>value<\/span><span >=<\/span><span>\"<\/span><span >true<\/span><span>\" <\/span><span >\/&gt;\r\n    &lt;<\/span>add <span>key<\/span><span >=<\/span><span>\"<\/span><span >ValidationSettings:UnobtrusiveValidationMode<\/span><span>\" <\/span><span>value<\/span><span >=<\/span><span>\"<\/span><span >WebForms<\/span><span>\" <\/span><span >\/&gt;\r\n  &lt;\/<\/span>appSettings<span >&gt;\r\n    &lt;<\/span>system.web<span >&gt;\r\n      &lt;<\/span>compilation <span>targetFramework<\/span><span >=<\/span><span>\"<\/span><span >4.5<\/span><span>\" <\/span><span >\/&gt;\r\n      &lt;<\/span>machineKey <span>compatibilityMode<\/span><span >=<\/span><span>\"<\/span><span >Framework45<\/span><span>\" <\/span><span >\/&gt;\r\n      &lt;<\/span>pages <span>controlRenderingCompatibilityVersion<\/span><span >=<\/span><span>\"<\/span><span >4.5<\/span><span>\" <\/span><span >\/&gt;\r\n    &lt;\/<\/span>system.web<span >&gt;\r\n&lt;\/<\/span>configuration<span >&gt;<\/span><\/pre>\n<p>By inferring all of these settings from a single line, we help shrink the size of Web.config. Thus the file contains less runtime configuration and more application-specific configuration, such as connection strings.<\/p>\n<p>I&#8217;ll go over each of these in turn, explaining what they do.<\/p>\n<h4>&lt;add key=&#8221;aspnet:UseTaskFriendlySynchronizationContext&#8221; value=&#8221;true&#8221; \/&gt;<\/h4>\n<p>Enables the new <em>await<\/em>-friendly asynchronous pipeline that was introduced in 4.5. Many of our synchronization primitives in earlier versions of ASP.NET had bad behaviors, such as taking locks on public objects or violating API contracts. In fact, ASP.NET 4&#8217;s implementation of <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.threading.synchronizationcontext.post.aspx\">SynchronizationContext.Post<\/a> is a blocking synchronous call! The new asynchronous pipeline strives to be more efficient while also following the expected contracts for its APIs. The new pipeline also performs a small amount of error checking on behalf of the developer, such as detecting unanticipated calls to <em>async void<\/em> methods.<\/p>\n<p>Certain features like WebSockets require that this switch be set. Importantly, the behavior of <em>async<\/em> \/ <em>await<\/em> is undefined in ASP.NET unless this switch has been set. (Remember: setting &lt;httpRuntime targetFramework=&#8221;4.5&#8243; \/&gt; is also sufficient.)<\/p>\n<h4>&lt;add key=&#8221;ValidationSettings:UnobtrusiveValidationMode&#8221; value=&#8221;WebForms&#8221; \/&gt;<\/h4>\n<p>Causes server controls to render <em>data-val<\/em> attributes in markup rather than send a snippet of JavaScript for each input element which requires validation. This provides a better extensibility story for customizing how client-side validation is performed. Depending on the complexity of the page, it can also significantly reduce the size of the generated markup.<\/p>\n<h4>&lt;compilation targetFramework=&#8221;4.5&#8243; \/&gt;<\/h4>\n<p>Selects which version of the .NET Framework&#8217;s reference assemblies are used when performing compilation. (Note: Visual Studio requires that this element be present in Web.config, even though we auto-infer it.)<\/p>\n<h4>&lt;machineKey compatibilityMode=&#8221;Framework45&#8243; \/&gt;<\/h4>\n<p>Causes ASP.NET to use an enhanced pipeline when performing cryptographic operations. More information on the new pipeline can be found <a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2012\/10\/22\/cryptographic-improvements-in-asp-net-4-5-pt-1.aspx\">here<\/a> (links to the first part of a three-part blog series).<\/p>\n<h4>&lt;pages controlRenderingCompatibilityVersion=&#8221;4.5&#8243; \/&gt;<\/h4>\n<p>Similar to quirks mode, but instead of affecting core runtime behavior it affects how controls render markup. For example, consider the control <tt>&lt;img runat=\"server\" src=\"...\" alt=\"\" \/&gt;<\/tt> (note the empty alt tag). In earlier versions of ASP.NET, this stripped the empty alt tag and output <tt>&lt;img src=\"...\" \/&gt;<\/tt>, which fails HTML validation. When the rendering compatibility version is set to &#8220;4.5&#8221;, the empty alt tag is preserved, and the output is <tt>&lt;img src=\"...\" alt=\"\" \/&gt;<\/tt>.<\/p>\n<p>&lt;pages controlRenderingCompatibilityVersion&gt; defines the default value of the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.web.ui.control.renderingcompatibility.aspx\">Control.RenderingCompatibility<\/a> property. The value can still be overridden on a per-control basis if desired.<\/p>\n<h3>Miscellaneous questions<\/h3>\n<h4>Can I detect the target framework programmatically?<\/h4>\n<p>Yes! Take a look at the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.web.httpruntime.targetframework.aspx\">HttpRuntime.TargetFramework<\/a> static property. Keep in mind that this property should only be queried from within an ASP.NET application. Any other access (such as via a console application) could result in an undefined return value.<\/p>\n<h4>But what if I don&#8217;t want the runtime to infer all of those configuration settings?<\/h4>\n<p>No problem! You can always explicitly change any setting. For example, you could put this in Web.config:<\/p>\n<pre class=\"code\"><span >&lt;<\/span>httpRuntime <span>targetFramework<\/span><span >=<\/span><span>\"<\/span><span >4.5<\/span><span>\" <\/span><span >\/&gt;\r\n&lt;<\/span>pages <span>controlRenderingCompatibilityVersion<\/span><span >=<\/span><span>\"<\/span><span >4.0<\/span><span>\" <\/span><span >\/&gt;<\/span><\/pre>\n<p>Even though &lt;httpRuntime targetFramework=&#8221;4.5&#8243; \/&gt; would normally imply &lt;pages controlRenderingCompatibilityVersion=&#8221;4.5&#8243; \/&gt;, the runtime will notice that you have already explicitly set <em>controlRenderingCompatibilityVersion<\/em> and will respect your setting.<\/p>\n<h4>My hoster is displaying &#8220;Unrecognized attribute &#8216;targetFramework'&#8221; errors!<\/h4>\n<p>This error means that you have created an ASP.NET 4.5 application but are trying to deploy it to a server that only has the .NET Framework 4 (not 4.5) installed. Many hosters offer ASP.NET 4.5 as an option. They may require you to contact them first so that they can enable 4.5 for your account.<\/p>\n<h4>How does this affect existing ASP.NET 4 applications?<\/h4>\n<p>There was no &lt;httpRuntime targetFramework&gt; attribute in .NET 4, hence existing ASP.NET 4 applications won&#8217;t have this setting in Web.config. If the <em>targetFramework<\/em> attribute is not present, we assume a default value of &#8220;4.0&#8221; and run the application in quirks mode. Web developers can manually set &lt;httpRuntime targetFramework=&#8221;4.5&#8243; \/&gt; to opt-in to the new behaviors.<\/p>\n<p>If there is no &lt;httpRuntime targetFramework&gt; attribute present in Web.config, we assume that the application wanted 4.0 quirks behavior.<\/p>\n<h3>Wrapping Up<\/h3>\n<p>I hope I have conveyed the intent and the utility of the &lt;httpRuntime targetFramework&gt; setting. In the future, we envision that this can be a useful mechanism for moving applications forward, as application developers can simply set <em>targetFramework<\/em> to &#8220;5.0&#8221; or &#8220;6.0&#8221; to opt-in wholesale to whatever new behaviors those framework versions may bring.<\/p>\n<p>As always, please feel free to leave feedback in the comments!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Background \u2013 on quirks and compatibility The .NET Framework (including ASP.NET) strives to maintain near-100% compatibility when an existing framework is updated on a machine. We try to ensure as much as possible that if an application was developed and deployed against .NET Framework 4, it will just continue to work on 4.5. This normally [&hellip;]<\/p>\n","protected":false},"author":413,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[52],"class_list":["post-2014","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-compatibility"],"acf":[],"blog_post_summary":"<p>Background \u2013 on quirks and compatibility The .NET Framework (including ASP.NET) strives to maintain near-100% compatibility when an existing framework is updated on a machine. We try to ensure as much as possible that if an application was developed and deployed against .NET Framework 4, it will just continue to work on 4.5. This normally [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/2014","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/413"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=2014"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/2014\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=2014"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=2014"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=2014"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}