MVC3: handling site updates
Once in a while one needs to update his/her MVC web application, but during this update you do not want that users get error messages because your code model does not match your database model.
You also want to be sure that the user can't change any data while you are running your database update scripts. So during this update you need to catch all actions and respond with a page that shows that your site is currently not available.
You probably want to be able to switch between offline/online mode without too much effort. There are many ways to solve this problem.

In my solution I added two key value pairs two the appsettings part of the web.config.
  • one that determines the state of the web application: ""
  • one for the url of the offline page: "application.offline.url"

<?xml version="1.0" encoding="utf-8"?> <configuration> <!-- ... --> <appSettings> <!-- ... --> <add key="" value="true" /> <add key="application.offline.url" value="~/503.html"/> </appSettings> <!-- ... --> </configuration>

The next step is to prevent any database initialization in offline mode. My application uses Entity Framework (code first) which I initialize in the Application_Start of the global.asax.
So all I have to do is put the initialization within an "if"-statement.

protected void Application_Start() { InitializeDepencencyInjection(); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); bool applicationIsOnline = Convert.ToBoolean(ConfigurationManager.AppSettings[""]); if (applicationIsOnline) { FSaysContext context = new FSaysContext(); context.Database.Initialize(true); } }

To assure that every action is redirected to the offline page, I created a class derived from "System.Web.Mvc.Controller" and I derived all my Controllers from this class.
In my new base controller class, I've overriden the "OnActionExecuting".

In my first approach I redirected all actions to a dedicated controller and action. But after I dug more into the subject "site maintenance", I found out that it is much better to respond with a HTTP 503 status.

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Configuration; namespace nl.eeuwevandijk.fsayseu.ui.Controllers { public class FSaysBaseController : Controller { public FSaysBaseController() { // ... } protected override void OnActionExecuting(ActionExecutingContext filterContext) { bool applicationIsOnline = Convert.ToBoolean(ConfigurationManager.AppSettings[""]); string offlineUrl = ConfigurationManager.AppSettings["application.offline.url"]; if (applicationIsOnline || filterContext.RequestContext.HttpContext.Request.AppRelativeCurrentExecutionFilePath.Equals(offlineUrl)) { base.OnActionExecuting(filterContext); } else { HttpResponseBase response = filterContext.RequestContext.HttpContext.Response; string file503path = System.Web.Hosting.HostingEnvironment.MapPath(offlineUrl); response.Clear(); response.TrySkipIisCustomErrors = true; response.StatusCode = (int)HttpStatusCode.ServiceUnavailable; response.StatusDescription = "Service unavailable due to maintenance."; response.WriteFile(file503path); response.End(); return; } } } }

The "TrySkipIisCustomErrors" is importent on some IIS servers. Localy everything worked fine for me, but after deploying I got the default 503 page of IIS. Setting this property to "true" fixed that problem.

Before you copy any files to your server, it's best to change the defaultRedirect in the customErrors section of your web.config. Because when you are copying your dlls at the moment that someone tries to visit your site, he/she will get redirected to the default redirect. If you haven't specified one, one of those red-yellow pages will be returned.

<customErrors mode="On" defaultRedirect=""> <!-- ... --> </customErrors>

The last step is to create your offline page. In my case the 503.html. Plain HTML is probably best if you don't want to waste resources on the server.
But I won't discuss the content of such a file, because it will result in a war on taste. You can visit mine anyway.
N.B. my 503-page will return an HTTP status 200 when my site is up and running.

After your site is updated: don't forget to change your "defaultRedirect" to whatever you prefer and set the "" to "true"
offline page
offline page

Back to List

All form fields are required.
A confirmation mail for the comments will be send to you.