As I’m working on some of my demos for DevConnections next week I decided that some older demos I’ve had should be moved to Web Application Projects (WAP) rather than running on stock projects for consistency. I tend to use only WAP projects in production, but for demos I’ve often stuck with stock projects because they worked with Visual Web Developer Express. Now that SP1 has shipped though even VWD supports WAP projects (a big thanks for the ASP.NET team to making that happen!) and so there’s no need to use the stock project model any longer.
Other than consistency with other projects, there was also the issue of WCF Web Services behaving badly under stock projects. For whatever reason I still can’t figure out with stock projects WCF Services often simply stop working with a compilation error even though there have been no code changes. It appears the problem is related to the temporary file storage in the ASP.NET temp folder with copies of the App_Code assemblies getting out of sync with the service in some way. There’s a slight fix for this in stock projects by turning batch compilation off:
<compilation debug="true" batch="false">
This has helped make the problem less frequent, but it still occurs from time to time. Using Web Application Projects this is not an issue because the full compile causes everything to be compiled into the same assembly so there’s no real chance of a version mismatch.
Anyway, so I decided I need to move this rather large demo project that contains many diverse examples from a stock to WAP project and as it turns out it took quite a bit of work to do it.
Converting from Stock to WAP in VS 2008
Prior to VS 2008 stock projects had an option to allow you to convert projects to WAP projects via a menu option – Convert to Web Application Project. That option is no longer available so the process has become fully manual.
Here are the steps that you should go through followed by a few gotchas you need to watch out for:
- Open your Stock project in a Visual Studio Solution
- Add a new Web Application Project to the Solution
- Drag and Drop all files from the Stock project into the WAP Project
- Remove the BIN folder (or don’t copy it in the first place)
- Manually add back ALL assembly/project references to the WAP Project
It’s best to do this first to make sure that related files are found and any auto-compiled components (like Linq to SQL models or Web References) get properly properly translated when files are converted in the next step.
- Right click on the root node of the project and Convert To Web Application
- Rename APP_Code to something else if the conversion didn’t do it for you. I use Classes as my ‘code only’ folder
APP_Code is an illegal folder name for a WAP project – if you don’t rename you’d end up with duplicate compiled classes which will cause problems. Ideally you shouldn’t have much code here – it’s best to put this sort of stuff into a separate project. Note that you can move any CodeBehind files (like Web Service, Handler or other ‘known ASP.NET files’) back into the actual content folders – no need to keep them in the App_Code/Classes folder since they’re easier to find with the actual content files.
Note that Convert to Web Application should rename the APP_CODE folder and it did the first time I did this. Just now when I walked through this one more time to verify for writing it up however it didn’t create an OLD_APP_CODE folder. Further I couldn’t rename the folder at first. I ended up explicitly running Convert to Web Application on the old APP_CODE folder. After that I was able to rename it.
- IMPORTANT: Select all files that were in the old APP_CODE folder and set their Build Action to Compile.
Files in the APP_CODE folder in stock projects are compiled by ASP.NET rather than Visual Studio so the default action for APP_CODE files in stock projects is content which doesn’t compile. When moved to a WAP project that same action is passed forward which means that Visual Studio is not compiling APP_CODE files by default. Make sure you switch the Build Action to Compile or else you’ll end up not finding the classes when compiling your project. This one threw me for a loop because I got compiler errors pointing at classes that I knew were in the project.
- Compile your WAP Project – rinse wash and retry
There are bound to be a few compilation errors in your project when you do this. Pay especial attention to missing classes (check that the classes in question are set to Compile not as Content) or missing namespaces (make sure that classes other than pages have a namespace). Also make sure that you have all necessary assemblies referenced. You’ll likely get a bunch of errors and go through this cycle of compiling fixing and a host of errors until all references and classes are properly added. Read the next two bullets for a few more hints on possible compilation issues.
- Remove and Reattach Web and Service References
The Conversion imports Web and Service references but it attaches them into a separate folder. For me the Web References didn’t work correctly so instead I ended up removing them and re-adding them using the standard Web Reference/Service Reference tools. Note that in WAP this will cause Namespace changes – from only the name you assigned in Stock projects to the Project’s default namespace + the name you assigned. IOW, you’ll have a little bit of refactoring to do to fix these services.
- Linq To Sql Models
My project had two Linq to SQL models and while both of the models transferred, they didn’t immediately compile. The problem is that the old designer file is detached and a new attached and somewhere in that process the actual class is not visible so that any reference to the model fails.
The solution for me was to go delete both of the code behind files (the .designer files) both in the project and from disk. Then going into the model and resaving it. You’ll end up with the TimeTrakker1.designer.cs file which is odd, but works properly. The key is to make sure that the original file is deleted and removed.
So as you can see doing a WAP conversion is by no means a trivial task. I ended up spending a good two hours converting this project by the time I had everything back up and running as it did before. And that’s having done this before and having some idea what to look out for. The hardest part for me were the auto-building files – Web Services and the LINQ to SQL Models that just didn’t want to work after initial conversion.
Part of the problem was that the compiler wasn’t being helpful. I had the L2S model in the project for example with proper namespaces set on the model, yet the compiler failed to see the actual model’s classes. No error during model generation – I could see the classes in the model’s codebehind but the compiler failed to see the classes. When this happens the thing to check is to make sure that the Build Action is set properly and/or that there isn’t another file that is interfering with the namespace resolution.
The good news is that the issues are all related to file location/switch settings and once those were resolved the project just kicked right in and worked as expected. No further tweaking required. Personally I much prefer WAP’s more formal compilation approach and the reliability that comes from having a single code behind assembly that knows where are code behind code lives in one place instead of scattered through multiple temp assemblies as is the case with Stock projects.
I have a couple of other projects that I should do this to as well – not sure if I’m willing to put in the time again though. <shrug>