My Biggest C# Programming Mistake
C# Corner columnist Patrick Steele recounts an avoidable mistake he made during a transition from WebForms to ASP.NET MVC, and what he learned from his gaffe.
In early 2009, the company I work for was offered the job of rewriting an old Web site that used ASP.NET WebForms. The site integrated with a SQL Server database as well as a SharePoint installation. The people in charge of maintaining the site told us it was populated with old code developed by non-developers and we were free (and encouraged!) to start clean. We decided to use Microsoft's new ASP.NET MVC framework.
Starting a greenfield project is always fun. You start with a clean slate. Sure, we had SharePoint and an existing SQL Server schema to deal with, but all of the code that interacted with those components could be written from scratch.
Needless to say, I was pretty geeked. We started by working with a local design shop to redo the site's look and feel. It came out awesome! I then incorporated that into a Master Page and things were moving along nicely. The client loved the new work and it was time to start coding.
We got our unit tests written and brought in Linq2SQL for our persistence layer (along with a nice repository layer we could mock out in our unit tests). We used Castle Windsor for Inversion of Control and Dependency Injection and then abstracted the SharePoint access so we could plug in a replacement in the future. Things were going great!
All the tests are green. I'm doing some simple testing against the dev environment and everything looks like it's ready to be pushed to the client's beta test server. As I've always done in the past (WebForms), I just FTP'd the contents of the Web directory up to the clients Web server.
We started testing things in "dev" mode. While in "dev" mode, we didn't actually hit SharePoint or our live SMTP server. The SharePoint access returned mocked data and the emails were sent to the App_Data folder -- one file per email. This meant we could use real email addresses for the "from" and "to" fields, but nothing actually went out. We could review the generated files to make sure everything was working.
(Yes, I know -- I haven't explained exactly what was wrong in Mistake #1, but I'm getting to that...)
So now it's time to switch to "production" mode. In this mode, we'll be hitting the live SharePoint server as well as sending out live email. So I go in to the global.asax.cs file that's on the client's server and tweak a few settings so the IEmailSender interface I defined will resolve to the real SMTP server instead of the App_Data directory.
We do some tests and no emails are going through. In fact, they're still appearing in the App_Data folder. What's going on here? I double check my code in global.asax.cs to see if I made a typo, but still no email is going through.
Maybe the SMTP server isn't configured properly? I spend some time digging around to see if that could be the case, but nothing looks wrong. I hopped on the client's Web mail interface and sent a few emails out and everything worked fine. It wasn't the email server.
I double-checked and triple-checked my code and everything was correct. I was stumped. Not even a reboot would convince the Web site to use the new values.
Out of frustration, I started poking around the "Bin" directory. I saw the .dll file for the Web site project (along with the controllers DLL, data-layer DLL, etc...). I'd been playing around with this problem for close to an hour and the date on the file hadn't changed. I pulled up ILDASM and actually looked at the IL to see what crazy stuff was going on.
Lessons Learned, the Hard Way
I think it was at this point that I realized what I had done wrong.
First, I didn't actually "publish" my application using Visual Studio's Publish command. This would have pulled just the files I needed to deploy the Web site. ASP.NET MVC doesn't keep the global.asax.cs file around for dynamic compilation like WebForms did. It compiles into a DLL that is placed in the bin directory.
Second, not realizing what I had done with my first mistake, I wasted time tweaking a .cs file that was never being compiled! Not only was it frustrating, it looked bad to the client. They totally understood that computers sometimes get finicky and don't work -- but I was so frustrated!
Finally, I need to add one point as this really gets to the root of the problem. If something is supposed to be configurable, set it up in web.config -- not code!
It pays to make sure you have a thorough understanding of your platform -- from the first line of code all the way through to deployment and upgrades. And if you're developing Web applications, make sure you do your configuration in the proper place.
You can find an abbreviated version of this story on my blog back in August 2009
Have you suffered a coding faux pas that helped drive home an important lesson? Visual Studio Magazine would like to hear from you. Email VSM Editor-in-Chief Michael Desmond at [email protected].
Patrick Steele is a senior .NET developer with Billhighway in Troy, Mich. A recognized expert on the Microsoft .NET Framework, he’s a former Microsoft MVP award winner and a presenter at conferences and user group meetings.