13

I used to develop websites in PHP and ASP classic and if something needed to be changed. You could just alter a single/several files and nobody would really notice. Perhaps if somebody would request the changed file during upload, but that's like half a second margin. For most smaller sites that's no problem.

But the latest sites are build with C# MVC and when you make changes to the code, you need to rebuild your website and upload the altered DLL files. But when you change your DLL files it will restart your website and reset all active sessions. It also has to reload everything and with large sites it can take a few minutes to load everything. Everybody that was browsing the site will notice and needs to log in again.

Major site updates aren't that common, so that's not a problem. But we do have regular "small" updates for promotions. Like 'Fill in this form and get three months free membership' or 'The first 10 to upload an image of ... will receive a price'. I think you'll get the drift. Some promotions are similar and could be handled with a module that shows the right info based on settings, but quite often it requires custom code.

I was thinking of a system where each promotion is it's own DLL file based on an interface, and then load the DLL dynamically using Type.GetType, Activator.CreateInstance and InvokeMember. Although that could work, I'm wondering if it's the right way to go.

So my question: How do you update a .NET site on the fly, without reloading the entire site and dropping session (like recycle application pool).

  • In response to your bounty comment: the large websites I work on handle small changes to code the same way they handle large changes to code: through load-balancers and out of process sessions - because all code that is deployed to live needs to go through a review/sign-off process and we can't just drop code on the servers. I guess our definitions of "large" may not match ;) – Zhaph - Ben Duguid Feb 26 '15 at 12:31
11
+100

Look into "Application Initialization" IIS 7.5, Windows 2008 R2 (harder to setup) IIS 8, Windows 2012

App Initialization allow any application (application pool not site) restart to overlap and use the old, still running the previous application while warming up the new application start. Once the new application is spun up (determined by URLs you can set), it will begin using the new application and shutdown the previous one. Using App Initialization in conjunction with methods to ensure session remains across application pool restarts can allow your site to reboot seamlessly. (Zhaph has a good note about the machine key.)

In addition to the above links for App Initialization configuration, you're going to want to look at what triggers a site restart - since the site restart doesn't use the Application Initiliazation the site restart will be not be seamless.

You can configure IIS so that a DLL update doesn't immediately trigger a site restart, nor changes to web.config (high ChangeNotification values on the httpRuntime and external config files, as relevant to your site).

The final result is that you can update the DLLs/code without a site restart, then force an app restart that will use the AppInitialization background warm up for the seamless change of code.

Doing these things in concert works quite well for seamless restarts.

  • A good set of steps there - certainly something to consider :) – Zhaph - Ben Duguid Feb 20 '15 at 23:33
  • This sounds like what I was looking for. Going to give it a try and set it up. Thanks – Hugo Delsing Feb 21 '15 at 6:31
  • @HugoDelsing Hope it works great for you. – jeffreypriebe Feb 22 '15 at 1:37
  • Thank you, this is what I ended up using and it works great. – Hugo Delsing Feb 27 '15 at 14:11
  • @HugoDelsing Glad to hear it worked for you as well. – jeffreypriebe Feb 27 '15 at 20:45
5

There are a number of ways to handle what you're asking for, and a few different aspects to your question:

Handle small updates for promotions

What you're really after here is a content management system or similar that allows you to edit the content on the fly (think Wordpress/Drupal or from a .NET point of view N2 CMS, Umbraco, Orchard, etc.), however there are some things you could try if you haven't gone down that route.

Because ASP.NET only really reloads if you touch certain types of file (web.config(s), the contents of the /bin/ and /app_code/ folders mostly) - and has a configurable limit for "other file changes" (basically once you've modified so many files within your site the application pool will restart - NumRecompilesBeforeAppRestart) you could look at doing something where you check a different folder for some static (i.e. .html) files that you pull in and display as needed, or utilise the LoadControl method that takes a string path to an .ascx user control and dynamically loads it - how you determine which to show is a different question more suited to StackOverflow - however I'd recommend a naming convention based solution.

You could also look into using something like the Managed Extensibility Framework (MEF - which has been a full part of the .NET framework since version 4) which allows you to write a plugin based architecture and specify a folder outside of your /bin/ directory to monitor for new .DLLs - although I've not tried this to see if it will avoid the app restart issue, I have used this to good effect in a web environment for adding common functionality to a site.

If that doesn't appeal, the only other option I can think of would be to add the controls as "code-in-front" as we did in classic ASP - i.e. with a <script runat="server"> block instead of a compiled "code-behind" class that contains the logic to run the control - this will remove the need for a DLL change, at the expense of some first-time performance loss as the control is compiled on the fly - again you'll need to balance this with the NumRecompilesBeforeAppRestart if you're doing lots of little changes.

How do I persist sessions across app restarts?

This is possibly an easier issue to solve and involves three key steps:

  1. Configure the MachineKey (IIS7, but still holds for 8) to be a constant value rather than AutoGenerate - this means that when the AppPool recycles it will use the same key, and so will be able to decrypt session cookies, viewstate, etc. from before the recycle.
  2. Either setup a State Server or configure a Database to hold Session State.
  3. Switch from using InProc to StateServer or SQLServer in the SessionState element in your web.config.

This way you will have persistent sessions that survive an app restart. However, these aren't "free" - everything you store in session must now be serializable, and you will incur a slight performance hit as each page load will now require additional network trips to get, and potentially release the session data.

However, if you're in a position where it takes "several minutes" for the application to restart after a deployment, you may want to consider moving to a load-balanced environment, or at the least a hot-swappable Staging/Live setup (such as that provided by Azure/AWS/etc.) - this way you can take a server offline while you update it or get it ready with the new code and then swap it in - provided you've taken the steps to address shared sessions (see above) this will work fine with no impact to your users.

  • Thank you for your long answer. Unfortunately a CMS not what I want. I don't want to alter content, I want to alter code. The part about the sessions was just an example. Changing it won't solve the problem of the site being down for a minute or two when it's reloading DLL files. The MEF part was interesting, but is a third party solution to the system I was thinking of. So +1 for the effort, but unfortunately it's not really an answer to my question. – Hugo Delsing Feb 20 '15 at 14:37
  • 1
    I've updated my answer to address a couple of those points: MEF was released by MS and has been a full part of the .NET framework since v4. You could try using code-in-front for your new controls, alternatively adopt a load-balanced/staging-live setup that would enable to get a server up and running and then swap it in. – Zhaph - Ben Duguid Feb 20 '15 at 17:53
  • 1
    I've outlined an alternative solution using Application Initialization. The benefit is that all the code and server setup is "normal" without special load-balancing or dynamically loading controls, keeping your running environment simpler. Of course, a load-balancing/staging-live setup might be useful for other reasons. – jeffreypriebe Feb 20 '15 at 23:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.