Log in

No account? Create an account
21 April 2017 @ 07:37 pm
.NET targetFramework mess  
Couple of weeks ago we noticed that the same C# code executes differently under MSTest and in Visual Studio 2017.
In particular, Uri constructor crashed on invalid input in Visual Studio, but did not crash in MSTest.

Then, several days later, we found that ASP.NET allows to modify collection that we iterate through, but the same code crashes in a unit test with "System.InvalidOperationException: Collection was modified; enumeration operation may not execute".

We decided to investigate and found that the culprit is in a different value of "httpRuntime targetFramework" attribute.

Bad naming and documentation
Microsoft .NET Framework team chose a bad name for that attribute and wrote a misleading documentation:
The version of the .NET Framework that the current web application targets.

When most developers (including me) read that - they think that "targetFramework" attribute defines what version of .NET framework would execute.

But actually that attribute has a very different meaning and should have been named either compatibilityTargetFramework or quirksTargetFramework.

What httpruntime targetframework actually means
Fortunately, levibroderick wrote a clarifying blog post, that now is the first result for httpRuntime targetFramework search:

With new versions of .NET framework, Microsoft .NET team introduced some breaking changes (especially for .NET Framework 4.5).
So then they created "quirks" to fix these breaking changes.

So, "targetFramework" attribute pretty much defines what set of quirks to use (the older the targetFramework version is - the more quirks you would get).
The total number of quirks seems to be around 10 (could be a little bit more or less, but not by a lot).

Practical impact
In the past, our Web.Config did not contain any mentioning of targetFramework in <httpRuntime> element.
That meant that we got all the quirks, so postjobfree.com did not break.
Then yesterday we turned off "legacy compatibility mode" by setting
<httpRuntime targetFramework="4.6.2" />
We lost all the quirks that way and, as a result, got two bugs:
1) "WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for 'jquery'. Please add a ScriptResourceMapping named jquery(case-sensitive)." crash on every page that contains <form> element.
2) Encrypted validationKey in <machineKey> element changed its meaning, so all users authentication cookies expired.
Several hours of research and development later - we fixed these issues and now our web site runs in a quirks-free mode.

What was your experience in converting legacy .NET app to the new .NET Framework version?

Originally posted at: http://dennisgorelik.dreamwidth.org/130665.html
Yaturkenzhensirhiv - a handheld spyyatur on April 23rd, 2017 01:16 am (UTC)
Well, in Visual Studio "target framework" is the framework the application is compiled against. It does not mean you'd get exactly the same version when running on a user machine. It was like that for a long time.

Having said that, ASP.NET guys could probably have reused name and syntax for "supportedRuntime" instead of inventing a new attribute.
Dennis Gorelikdennisgorelik on April 23rd, 2017 05:24 am (UTC)
> in Visual Studio "target framework" is the framework the application is compiled against

That makes "httpRuntime targetFramework" naming even worse, because the same naming should mean the same thing.
Currently the meaning is definitely NOT the same in case of Target Framework (<TargetFrameworkVersion>) in *.cproj file vs targetFramework in <httpRuntime> element.

> could probably have reused name and syntax for "supportedRuntime"

ASP.NET developers can’t use the element since there’s no .exe the [TargetFramework] attribute can be compiled into.

I guess it was possible to reuse "supportedRuntime" in ASP.NET configuration anyway, but such reuse would cause a confusion too.
It is much better to use unique name for unique features.

Edited at 2018-05-25 06:53 pm (UTC)