tags:

views:

422

answers:

5

We have a requirement to have our ASP.NET MVC websites be automatically closed down by a remote notification (change in database value). Where would be the best place to implement this?

  • Base Controller Class
  • Global.asax
  • Custom attribute
  • Other

Update

Lots of suggestions to use app_offline but this scenario will be happening daily and will be purely initiated by the database so I would rather have the application take the initiative rather than something external push the file in.

Also, I will probably need to redirect the users to a holding page (preferably an MVC controller method to keep everything consistent). I'm leaning more towards catching it in my BaseController and having that handle it

+4  A: 

I would go with Global.asax Application_BeginRequest if you have to do it programmatically.

You could Response.Redirect the page to "Offline.aspx" which can retrieve a message from the database or whatever you need. Of course you'd have to look at the request to see if it was trying to get to "Offline.aspx" otherwise you'd end up in an infinite loop.

Or maybe all your applications can be redirected to a single website which would remove most the complication.

Garry Shutler
The request to shutdown the application comes directly from the database so app_offline isn't really an option. Application_BeginRequest sounds like a good idea but I will probably need to actually redirect the user to a controller page with a message so I'm not sure how I'll handle that scenario
James
Updated my answer with a suggestion of how to do it programmatically.
Garry Shutler
Is a DB round-trip call in Application_BeginRequest really a viable performant solution? Strikes me that on a busy site its an additional piece of overhead that 99% of the time has no value. Better to convey the change in state by some other means IMHO
Kristen
+13  A: 

There's a standard way of "gracefully" terminating ASP.NET 2.0 webapp - just drop a App_Offline.htm to the root directory of your application. See this.

Anton Gogolev
Not always graceful: http://stackoverflow.com/questions/373540/why-is-appoffline-failing-to-work-as-soon-as-you-it-starts-loading-dlls
Mauricio Scheffer
I wonder if Jeff (Atwood) has a comment on this as I know that SO does not use the app_offline.htm method (it contains an image).
Richard Szalay
A: 

Sorry, don't know about ASP.NET, but in case helpful:

We have a single APPLICATION.ASP page for our site (CMS / Database merge type stuff); this is possibly not common and therefore may therefore restrict usefulness, but could perhaps be implemented by an INCLUDE at the top of all ASPX files

We rename APPLICATION.ASP to TEST.ASP and copy HOLDING_PAGE.ASP to APPLICATION.ASP

The HOLDING_PAGE.ASP is present in the WWW folder, so always ready-and-available. It contains a "Site not available" message etc. and is self contained for all CSS (no include files, no DB access). Only exception is the company logo (which is external to that file, obviously)

This method prevents all access to the site, is not dependant on having a working DB connection, and allows us to change anything on the site without interfering with the holding page (apart from Company Logo, but changing that is likely to be benign)

We can still access the site, internally, using TEST.ASP - so we can test any new rollout features before removing the holding page and putting the site live. If you want to prevent anonymous use of TEST.ASP then deny anonymous permission.

Remove holding page is: Delete APPLICATION.ASP (i.e. the holding page) and Rename TEST.ASP to APPLICATION.ASP

We also have a database flag that causes the normal APPLICATION.ASP page to show a holding page - which we can use whilst doing more minor changes.

Kristen
No, that's not a pain in the ass or anything...
Josh Stodola
What's not a pain in the ass? As I said I'm not skilled in ASP.NET, strikes me this suggestion is similar to app_offline - just you have to do these steps by scheduled task, global.asax or somesuch. If folk down-vote it would be helpful if they left a comment as to why.
Kristen
+1  A: 

I'm going to answer this myself as I did it a different way but thanks to everyone for their responses.

What I ended up doing is overriding OnActionExecuting() in my BaseController class (which all my controllers derived from).

In this method I check the database (using a 1 minute cache) and if the website is closed I load up a view to display a closed message. Code shown below

Protected Overrides Sub OnActionExecuting(ByVal filterContext As System.Web.Mvc.ActionExecutingContext)
            MyBase.OnActionExecuting(filterContext)

            Dim _cfgService = ObjectFactory.GetInstance(Of IConfigService)()

            If _cfgService.DynamicConfig.WebSiteClosed Then
                filterContext.Result = ErrorHandler(_cfgService.DynamicConfig.WebSiteClosedTitle, _
                                                    _cfgService.DynamicConfig.WebSiteClosedMessage)
            End If
        End Sub
James
A: 

Handling this type of behavior in the Global.asax file sounds like the best solution and redirecting to a static "ofline/closed" page. Handle the request on the Application_BeginRequest method, check to see the the site is active, if it let it continue, if it is not online Response.Redirect the request to the static page.

protected void Application_BeginRequest(object sender, EventArgs e)
{
    string redirectURL = "~/Offline.aspx";  //some static page
    bool isOnline = false;  //SQL Call, config value

    if (!isOnline && !string.IsNullOrEmpty(redirectURL))
    {
        Response.RedirectLocation = redirectURL;
        Response.End();
    }
}
Kyle LeNeau