2

We have an issue that we cannot solve: how to push code during the day with no end user interruption. I'm a developer, and I'm working in tandem with my Systems department.

Setup: 3 Windows 2008 IIS 7 boxes - 1 is down node, the 2 others are live (with shared config), and all 3 are behind BigIP. My site is setup as 1 web application with multiple webapplications underneath, all .NET 2.0. We are using stateserver with a set machinekey for viewstate. This setup is relatively new for us, as we previously only had one live machine, and it was not behind BigIP. One reason to migrate to this setup was for seamless pushes.

What I'm doing: making a code change to one of the webapplications. I do this by making changes to the down node, and then testing the changes, and then replicating to the up nodes.

What I'm experiencing depends on what part of the code that changes. For example, I change a value in the webconfig. When the end user posts back, everything works nicely in that they use the new value in the webconfig. We like this very much! I'm also able to change dll code in certain ways that also is seamless (changing logic on the backend).

However, the problem that's really plaguing us is this: I add a new label to the form. Once I do that, .Net acts like it's the first time a user is loading the form, but all their viewstate is kept. I've specifically traced this down to the Page.IsPostBack property, and further, via reflection, traced it to _fPageLayoutChanged. _fPageLayoutChanged = true when I add the new content to the form via a push. The end user's experience is that their content is still there b/c viewstate is still there, but the actions that I do on first load all fired, and the event that they were trying to perform didn't get hooked up. For example, if they pressed a button to save their notes, the notes are still on the screen but the button-click event didn't get fired, and thus their notes aren't saved. Depending on page architecture, sometimes this is as mild as the user needing to click save again, but can be as bad as the code wiping out what they've done b/c it depends on IsPostBack to fire code that loads notes from the database.

Here's the code from IsPostBack from the web (it's the last part that's hurting us):

public bool IsPostBack {
    get {
        if (_requestValueCollection == null)
            return false; 

        // Treat it as postback if the page is created thru cross page postback. 
        if (_isCrossPagePostBack) 
            return true;

        // Don't treat it as a postback if the page is posted from cross page
        if (_pageFlags[isCrossPagePostRequest])
            return false;

        // If we're in a Transfer/Execute, never treat as postback (ASURT 121000)
        // Unless we are being transfered back to the original page, in which case 
        // it is ok to treat it as a postback (VSWhidbey 117747) 
        // Note that Context.Handler could be null (VSWhidbey 159775)
        if (Context.ServerExecuteDepth > 0 && 
            (Context.Handler == null || GetType() != Context.Handler.GetType())) {
            return false;
        }

        // If the page control layout has changed, pretend that we are in
        // a non-postback situation. 
        return !_fPageLayoutChanged; 
    }
} 

The comment on the last line is killing me, b/c it doesn't explain why they made that decision.

Furthermore, I can't believe that we're the only ones who have tried to push code during the day without interruption to our end users and been thwarted by this. We're at a loss of what to do. Do we need to change an IIS setting? Re-architect our code to not depend on the IsPostBack property (but then events still won't fire since .NET doesn't seem to hook them up correctly when IsPostBack is false)? Is getting around this even possible?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
archangel76
  • 1,544
  • 2
  • 11
  • 18

1 Answers1

0

A lot of large sites do deploy updates constantly. Amazon is one of most known for it. Check this slide deck out Continuous deployment.

One approach is to allow all versions of code to run at the same time and decide what version should handle request by routing requests based on some information like "should be handled by version1.2.3.4" cookie.

Another approach is to built in backward compatibility into code. Hard to maintain, but significantly less infrastructure needed - OK for one-time cases.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • I appreciate the help (I explored all the slides), but I need something along the lines of how to solve this in .NET. It's not that the code is necessarily not backwards compatible... it's that IMHO .NET is treating the POST wrongly by marking the property incorrectly. – archangel76 Mar 21 '12 at 20:13