Back to Basics: Assert your assumptions and diff your source code
I've done a whole series of "Back to Basics" posts that I encourage you to check out. Sometimes I'll do a post as a result of a reader emailing me for help and this is one such post.
A person emailed me with an ASP.NET app was behaving differently on his computer vs. another developer's computer.
On his machine when he hit a protected page foo.aspx?returnurl=http://mymachine.domain.com
he would get a FORM element like this:
<form action="foo.aspx?returnurl=http://mymachine.domain.com">
but on everyone else's machines their HTML was:
<form action="foo.aspx">
They debugging and were frustrated and eventually reached out. They said:
1. there's nothing going on in the aspx of login.aspx that would append the querystring.
2. there's nothing going on in the code-behind of the aspx that manipulates Form.Action or messes with the Page.Render in any way.
So, I'm stumped, because the querystring is included on my machine, but not on others. I've tried comparing IIS components, web.config differences, application pool runtime type, machine.config differences, possible differences in Modules for IIS (IISrewrite), but nothing is giving me love.
I suggested that they assert assumptions and start diffing everything. You can see in the last paragraph that they're comparing stuff but I think you really have to diff everything.
When something "works here but not there" my answer is always, what has changed? What's different? If the answer is "nothing is different" I'm just gonna say it again:
"What's different?"
What are some things we can check?
- Code
- Do you know what's on disk?
- Do you know what ended up in memory? These are different things.
- Configuration
- There's local and machine-wide config to check
- Network Traffic
- This is often overlooked. The Internet is not a black box, but you'd be surprised how few people hook up a packet sniffer or even just Fiddler to look at HTTP traffic.
- I've talked to developers who have said "well, that's under SSL so I can't see it." Oh, my friend, if you only knew.
I had them do a sniff and see if there was a difference in HTTP traffic. My assumption was that the HTTP_REFERER HTTP header was different and there was some code that was causing the page to render differently.
We went back and forth over a few days and my reader became frustrated and just added this line in their app's Page_Load:
this.Form.Action = Request.Url.ToString();
Here they are basically reasserting the Form action by pulling it from the URL. It's gross and it's a hack. It's a Band-Aid on Cancer.
They then started looking at the source for ASP.NET proper and then decided to disassemble the code that was running on the other person's machine. They then started to assert their assumptions.
Is the code running what's on disk? For a compiled language, do the binaries reflect the source?
They looked in Temporary ASP.NET files at the compiled ASPX markup pages and found this.
//ExternalSource("D:\WebApplications\Foo\login.aspx",27)
__ctrl.Method = "post";
//ExternalSource("D:\WebApplications\Foo\login.aspx",27)
__ctrl.Action = "login.aspx";
What? Why is someone setting the FORM Action manually? And there's a line number.
They had diff compared all the source code but not the markup/views/html.
Their markup:
<form id="Form1" method="post" runat="server">
Other person's markup:
<form id="Form1" method="post" runat="server" action="Login.aspx">
The other person had hard-coded the action in their source markup. They'd been diffing everything but the markup.
When you are comparing two code-bases, make sure to compare everything or you might just lose a day or two like this person.
Thanks to my reader for sharing this and letting me in on this debugging adventure.
Related Links:
- Back To Basics: You aren't smarter than the compiler. (plus fun with Microbenchmarks)
- Back to Basics: Moving beyond for, if and switch
- Back to Basics: Dynamic Image Generation, ASP.NET Controllers, Routing, IHttpHandlers, and runAllManagedModulesForAllRequests
- Back to Basics: Daylight Savings Time bugs strike again with SetLastModified
- Good Exception Management Rules of Thumb - Back to Basics Edition
Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
- All computers are in theory digital.
- The compiler is right, your team is wrong. (Actually, one time it was the other way around. MT+Pascal compiled wrong, this was in 1982.)
- It helps to read Sherlock Holmes: When you have eliminated the impossible, whatever remains, however improbable, must be the truth.
It can be a little bit daunting at first, but it is amazing for finding bugs like this that are in your source control history.
I'm about to start a new winforms project that I know in my heart of hearts should be a web application running in Azure. I did some research and was overwhelmed with "useful" information. So much so that I just plain gave up - I don't have enough time to sort out good from bad and deal with the contradictions - I have software to deliver.
I have resisted web delopment for many years because, as fast as I started on one technology another one came along to 'enhance' it (can we all say dot-j-s?). So many times I went back to winforms because it produces good responsive code that just works. I think web is almost there now, but getting started with a real project that I know I have to deploy is a major wall to climb.
I can find loads of tutorials on ASP development (or should that be MVC now) and loads of descriptions of why Azure is brilliant. Nothing that walks me through getting from opening a new blank VS project to deploying it in a production Azure environment (including the web server management basics and security basics).
Sadly, as the only developer in the company, I don't have access to an IT department or an expert... I am the expert!
Now, this is what I call "back to basics".
It is powerful, intuitive and just plain works, which is why it's constantly being used on all of my machines. I paid for my own personal copy, then convinced everybody at the office to use it too - we wouldn't be without it now.
However this popped up in my RSS feed the other day, I'm going to try working through it http://msdn.microsoft.com/en-us/magazine/dn605877.aspx
I've actually done some ASP work in a previous job where the learning philosophy was "just get on with it and ask when you're stuck". I managed to impress a few people with what I produced but never felt satisfied with the results myself. Since then I've created a couple of test applications that ran fine on my local machine.
That's where a lot of developers seem to stop though. I want more. I want to know what I need to get from MS to get an Azure site (that's the easy bit - I think). I also want/need to know what I need to do to secure and administer the site, how to upload my application to it and get it running. What I need to do to administer any database I need. What I need to do to refresh my application when I find the inevitable "feature" that needs "enhancing".
A lot of people see these as operations issues, but I feel I will write better applications if I have to deal with these issues too. This tends to be where the "education" become thin on the ground for complete beginners.
All - thanks for the suggestions on what diff tools to use. I personally use BeyondCompare . Need a JSON compare for BeyondCompare? I wrote that... http://www.scootersoftware.com/vbulletin/showthread.php?t=11878&highlight=json.
The important point here is to *use* the diff tool first and use it *correctly*. Don't assume that there are no changes, because there most likely are.
I went too far into the deep end of "what's different" too quickly. The difference was in the surface level, in the aspx file, not in the bowels of the runtime.
The moral of this story is: Keep Calm and Diff.
Hindsight is of course 20/20, but I guess the example seems almost too basic. As a web developer, this makes me cringe to hear about other web developers missing something so seemingly trivial.
http://codeimo.com/2014/03/tale-of-forms-authentication-single-sign-on-and-the-mystery-of-differing-cookie-lengths/
I tried that once. Got in trouble with the ISO (Information Security Officer) - he thought it was a hacker tool.
I had a similar issue with our app.
<httpRuntime maxRequestLength="..." executionTimeout="..." /> in app A issuing cookie.
My application consuming the cookie was:
<httpRuntime targetFramework="4.5" />
Same server, so same version .net installed.
I was able to solve the incompatibility by adding this to the <system.web>/<machineKey> element
compatibilityMode="Framework20SP2"
Additional awesome insight here:
http://blogs.msdn.com/b/webdev/archive/2012/11/19/all-about-httpruntime-targetframework.aspx
Comments are closed.