Compatibility Testing with ASP.NET 2.0

My team has been cranking hard on our RTM milestone, and we are driving to hit our final ASP.NET + Visual Web Developer ZBB (Zero Bug Bounce) on June 3rd.  Shortly after this we’ll enter lock-down and enter a phase where we’ll be responding to last minute bugs, customer reported issues, and driving long-haul stress results.

 

One of the things we’ve been doing the last few weeks has been getting customer applications upgraded to ASP.NET 2.0, and in identifying and fixing any compatibility issues we find.  Compatibility is always one of those really hard problems that requires a lot of focus. One of the big challenges with server applications in particular is that it is hard to replicate customer applications within our lab (since every non-trivial web app has a database and usually requires a lot of work to setup).  In addition to the deployment problems with getting customer applications working in our labs, there is also the bigger legal hurdle of getting permission to run and look at code in order to identify what a problem is when it is found.

 

In general we have seen three types of compatibility issues with ASP.NET 2.0 Beta2:

 

1)      Deliberate model changes we made between versions to more optimize the web experience.  Some specific examples of these are our move to be XHTML compliant by default at runtime, as well as the project and code-behind model changes we made between VS 2003 and VS 2005.  These sometimes break existing code because they introduce new rules and semantics.

 

2)      Bugs where we inadvertently changed the public defined behavior without meaning to.  These are usually the most straight-forward to find and fix.

 

3)      Subtle issues where a customer application was relying on the internal private implementation of an ASP.NET feature, instead of using just public APIs or documented behavior.  These are the hardest to track down and the most interesting philosophically on what the appropriate way is to resolve (for example: if you changed code to fix a bug or make a performance optimization, but someone was inadvertently relying on the old behavior – do you back out the fix or not?).  We spend a lot of time considering each of these on a case-by-case basis.

 

One of the big changes we are making for RTM is to further enhance the migration wizard in Visual Studio 2005 to help handle a number of the common cases that we’ve seen when upgrading applications with Beta2.  In particular, we are spending time making sure that all of the model changes we made (item #1 above) are automated so that existing customer apps should for the most part “just work” without manual changes required.  A few of the cases of model change behavior that we’ve seen that have required manual developer changes in Beta2 but should now be automatic for RTM when first opening the project and running the migration wizard include:

 

-- Classes and types stored in code-behind files that are utility classes shared across the project.  In V1 all pages were compiled into a single assembly which enabled these classes to be directly referenced everywhere.  In V2 we compile page UI into more granular assemblies to allow updates and avoid resetting applications when changes occur.  With the RTM migration wizard we’ll now automatically move these utility classes under the App_Code directory (which is where shared code for the project now lives) so that they continues to work everywhere in the app (with B2 you need to manually move these).

 

-- Custom Page Base Classes that code-behind classes derive from that declare controls as field declarations.  Because of the changes to the code-behind model, users who have migrated apps to V2 sometimes see null reference exceptions when accessing these fields on the “grandparent” base-class because the .aspx compiler can’t correctly wire-up the control references to the fields.  We’ve now added support for this in V2, and the migration wizard will automatically configure code-behind classes that use custom base classes appropriately for you.

 

-- Referencing and then casting dynamically loaded user-controls or pages from non-code-behind classes.  With Beta2 you can add a <%@ Reference %> directive to a page or user control to allow the page to dynamically load and cast these classes.  What wasn’t available in Beta2 was the ability to load and cast these classes from non-code-behind code declared within the app_code directory.  This broke some apps that used a pure MVC pattern or had non-UI utility classes that were directly accessing pages.  We are updating the migration wizard to generate abstract class contracts in App_Code that will let these scenarios work with RTM without any developer changes required. 

 

-- When upgrading existing web projects built with VS 2003 we’ll now set the XHTML config switch to off to maximize rendering and scripting compatibility (we saw a lot of people run into problems caused by the lack of a “name” attribute on the <form> tag for XHTML strict compliance).  Note that it is just a configuration switch in your web.config file – so it is easy to switch to XHTML (either transitional or strict). 

 

There are lots of smaller compatibility changes that we are then in the process of finding and fixing as well.  As I mentioned above, one of the challenges with finding all these issues is getting lots and lots of different apps to upgrade to V2 and identify anything that we’ve missed or seems to have cause problems with the app.  One of the ways you can help is if you have existing ASP.NET V1.1 applications, please try upgrading them to V2 and run through your tests to verify that everything still works.  If you run into a problem, please enter a bug on the MSDN Feedback center (http://lab.msdn.microsoft.com/productfeedback/) with repro steps so that we can investigate and fix it. 

 

We are also looking to work with a small group of volunteers in about a month’s time who have existing ASP.NET V1.1 applications and are interested in trying out the latest migration wizard and RTM bits to verify clean upgrades.  If you are interested in being in this program, and can commit to running your existing V1 or V1.1 applications through our migration wizard and then verifying the functionality, please send me mail at: scottgu@microsoft.com.  I’ll add your name to the list and we can then get back to you in about a month’s time with details on how to get and run a more recent drop.

 

 

6 Comments

  • Scott,



    Only problem I had when tryinig to run my 1.1 app on 2.0 Beta 2 was that I was removing some Http Modules in my web.config and got an error when trying to remove the ErrorHandlerModule. I checked machine.config and here is the definition:



    add name=&quot;ErrorHandlerModule&quot; type=&quot;System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&quot;



    So it looks like that module was not shipped in V2.



    So in my web.config I had a &quot;remove name='ErrorHandlerModule'&quot; line, and to fix this issue I just had to remove that line from web.config.



  • I've held off on posting about this because I haven't had an opportunity to actually test it, but I know that time is running out and by the time I do get around to being able to test, it might be too late to get it actually fixed.



    I understand that the concept of a project file for a web project has been removed entirely. (Full disclosure: that decision annoys the heck out of me in general, but I'm sure that battle is lost already).



    I haven't done any testing of web projects in whidbey yet to ascertain exactly what features were lost as a result of this. I read one posting about Bin directories ending up in source control due to this, which would obviously be a huge problem and I'm assuming it will be fixed because it would affect *everyone* doing web projects.



    But one feature that we make use of extensively in our product is the ability to mark files as &quot;Build action: None&quot; or &quot;Build action: Embedded Resource&quot; and guarantee that these files will NOT be copied to the server, even though they live in the same folders as files that *will* be copied, and are of file types that would otherwise be pushed.



    For example, we have some third-party licensed code that uses a javascript compactor/obfuscator. For ease of development, we keep the original files as well as the obfuscated output within the project folder. However, licensing obligations require us NOT to distribute the source files when we deploy our sites, so we mark them as &quot;Build action: none&quot; to ensure that they're treated just like the source code: part of the project, and in source control, but never deployed.



    Similarly, we have a bunch of XML and XSD files that are expected to be compiled into the project assembly rather than deployed.



    Furthermore, we have a push script we wrote ourselves that uses the &quot;Build action: Content&quot; status in the project file to decide what to push. I'm sure I'll have to rewrite that script, but I have no idea where it can pull its information from in the absence of a project file.



    I'm also anticipating problems if the names or relationships of assemblies have changed: I do have a bunch of code that does Type.GetType(&quot;NS.ClassName, AssemblyName&quot;) which will fail if the codebehind assembly's name has changed from the one in the project file pre-migration. I'm less worried about that, because it's relatively easy to identify all the problematic chunks of code by just searching for GetType. We also use server controls that are defined in the codebehind assembly, so the same issue exists for the Assembly attribute in &lt;%@Register %&gt; directives.

  • Hi Simon,



    The \bin directory problem with assemblies and source control was unfortunately a bug that shipped in Beta2. It has been fixed since then and won't be a problem in RTM. I think you should find that overall the new project model should actually make working under source control easier than before since there won't be contention on updating a single .proj file.



    The GetType() issue is a change that will need to be made to code that assumes a static assembly -- although as part of migration the migration wizard should update those references in your web-project that use GetType() to use a new API that provides the same semantic but integrates with the new project system.



    You will still be able to define controls as part of your web-project -- this should continue to work just fine.



    There is a new IgnoreFileBuildProvider in V2 that you can use to ignore certain file types in your project. Typically you do this by extension mapping (so for example: you could ignore all .txt files and not have them be processed or published as part of a build-step). You could also in theory use this to override an entire directory and have it apply to everything within it.



    Alternatively, after you run the publish web step which will pre-compile your site, you would need to run a script to remove those files that you don't want to ultimately deploy. Unfortunately we don't have a built-in way to automate creation of this script -- although I think you should be able to configure it to run as a post-build action for your solution.



    The new project model does support adding .resx resources to your project (very easily actually). We don't have a built-in provider to burn in XML/XSD files as embedded resources -- although we are looking at possibly building one as a sample you could use based on your scenario. Alternatively, you could partition these files into a separate class library project that you then referenced as part of your web project.



    Hope this helps,



    Scott

  • Scott,



    Thanks for your comments :) I sincerely appreciate the great responsiveness I get from people at MS, even if I don't always like the answers ;)



    Unfortunately your answers provided only limited help to me here. There are glimmers of hope, but it certainly doesn't seem like it will be possible to do all the things I'd hope to do.



    (I'm intentionally being fairly forceful in my comments here and I hope that doesn't come off as rude. It doesn't mean I'm unaware that there are legitimate points on the other side, just that it would make this post even longer than it already is to try to enumerate them, and of course you already know what they are because they're the reasons you did what you did.)



    First off, I disagree that removing the csproj file was necessary to fix the contention problem. All it takes is allowing concurrent checkouts on that specific file and a source control provider that's not completely retarded about merging (that is to say, pretty much any provider except SourceSafe).



    An alternative approach would have been using a named fork or separate hidden file to store the metadata about each file separately.



    Removing the per-file metadata entirely leads to unfortunate regressions in useful functionality.



    I'm not sure whether the build-provider approach covers all the cases I need. It might, especially if I can say things like &quot;Ignore all .js files in this folder but publish .js files everywhere else&quot; or &quot;.xml and .xsd files in this folder should be treated as embedded resources but other .xml files are content&quot;. In the worst case I may be able to workaround it by using some customized doubled-up file extensions like &quot;.emb.xml&quot; and using a different build provider for &quot;.emb.xml&quot; versus &quot;.xml&quot;. (Would that work, by the way? Would it be possible to ensure that the .emb.xml provider takes precedence?) Doing that would be undesirable as it would require further changes to the third-party code that we imported, but if it's necessary it's necessary.



    Of course my opinion is that the ideal would be to be able to override the build provider on a per-file level, but...



    It would be nice to at least give us built-in build providers equivalent to the three options in VS2003's Build Action dropdown: Content, None and Embedded Resource. Sounds like Embedded Resource is missing...



    The other thing is that I can guarantee that the migration wizard will *not* be able to catch all my code that uses GetType in this way. Some of the instances are constructing the string dynamically, as in Type.GetType(dbObject.ClassName + &quot;, AssemblyName&quot;), and getting that right in the general case is halting-problem-equivalent. Hopefully the migration wizard will at least be smart enough not to mess with code it can't understand and let me fix it myself. Other instances occur in files of a type that's only recognized by my DAL that later get converted into generated C# files, so there's no way you'd catch those either. I don't mind fixing them by hand as long as the fix is easy enough. Can you let me know what the new API is for this?



    Thanks again,

    Stuart.

  • Hi Scott, Regarding your notes on "-- Custom Page Base Classes that code-behind classes derive from that declare controls as field declarations..." We have exactly the problem you have described in this section: &nbsp;We are migrating our solution from .NET 1.1 to 2.0. &nbsp;We have pages that inherit from a custom "PageBase" class. &nbsp;The controls for these pages are defined as protected properties in the "PageBase". &nbsp;After converting to .NET 2.0 these pages have stopped working. &nbsp;We get null reference exceptions on these controls in the "PageBase" class. You eluded to the fact this was fixed in "V2". &nbsp;Precisely what version of Visual Studio is this fixed in? &nbsp;We have VS 2005, version 8.0.50727.42, .NET Framework 2.0.50727 (according to Help -&gt; About). &nbsp;Is this out of date? Thanks in advance.

  • Hi Philip,

    Have you tried upgrading using the VS 2005 Web Application Project option? You can find more details about it here: http://webproject.scottgu.com

    It compiles everything into a single assembly (just like VS 2003) and makes upgrading really easy. I'd recommend installing it and using it to migrate your solution -- you will avoid the PageBase issue you mention above completely.

    Hope this helps,

    Scott

Comments have been disabled for this content.