11

I know we could simply use an app_offline.htm file to do this.

But I want to be able access the website if my IP is 1.2.3.4 (for example), so that I can do a final testing.

if( IpAddress != "1.2.3.4" )
{
    return Redirect( offlinePageUrl );
}

How can we implement this in ASP.NET MVC 3?

dbc
  • 104,963
  • 20
  • 228
  • 340
Anwar Chandra
  • 8,538
  • 9
  • 45
  • 61
  • You can still do this only using IIS. Set up a new site with a different host name binding that doesn't redirect. No need to taint your code with "deployment" stuff. :) – bzlm Sep 28 '11 at 10:56
  • @bzlm we already done testing with different host name. we need to do a final testing again with real host name. – Anwar Chandra Sep 28 '11 at 10:59
  • I can see that happening as well. – bzlm Sep 28 '11 at 11:15
  • I have an MVC app on Azure IIS and have realized app_offline.htm for MVC might not be the best option. I quickly used app_offline.htm but stylesheets, images, and script files that are referenced could break. For example, IE Edge forces the slash (/) after the end of the domain whereas google chrome does not include the slash. My references broke. For MVC, I think routes need to take charge and not the app_offline.htm – JoshYates1980 Mar 21 '18 at 13:40

5 Answers5

14

Per Max's suggestion here is an actual implementation.

public class MvcApplication : System.Web.HttpApplication
{

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new CheckForDownPage());

    }

    //the rest of your global asax
    //....
}
public sealed class CheckForDownPage : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var path = System.Web.Hosting.HostingEnvironment.MapPath("~/Down.htm");

        if (System.IO.File.Exists(path) && IpAddress != "1.2.3.4")
        {
            filterContext.HttpContext.Response.Clear();
            filterContext.HttpContext.Response.Redirect("~/Down.htm");
            return;
        }

        base.OnActionExecuting(filterContext);
    }


}
colemn615
  • 151
  • 1
  • 3
14

You can use a catch-all route with a RouteConstraint with the IP check:

Make sure you put the offline route first.

routes.MapRoute("Offline", "{controller}/{action}/{id}",
                new
                    {
                        action = "Offline",
                        controller = "Home",
                        id = UrlParameter.Optional
                    },
                new { constraint = new OfflineRouteConstraint() });

and the constraint code:

public class OfflineRouteConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        // return IpAddress != "1.2.3.4";
    }
}
Rickard
  • 2,325
  • 13
  • 22
  • Very clean solution. Does exactly what I needed. Thanks. – nrod Mar 03 '15 at 13:10
  • @Rickard, users on live shopping site get effected with error when i upload `.DLL` to update code changes in project, so will down for maintenance help ? or [statuspage.io](https://www.statuspage.io/) paid service ? here is discussion on similar [issue](http://programmers.stackexchange.com/questions/238767/asp-net-deployment-maintenance-best-practices) – Shaiju T Oct 08 '15 at 10:59
2

I got an infinite loop on colemn615's solution, so I added a check for the offline page.

Also, for later versions of ASP.NET this is split into a FilterConfig.cs file in the App_Start folder.

public class FilterConfig
{

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new CheckForDownPage());

    }

    public sealed class CheckForDownPage : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (HttpContext.Current.Request.RawUrl.Contains("Down.htm"))
            {
                return;
            }

            var path = System.Web.Hosting.HostingEnvironment.MapPath("~/Down.htm");

            if (System.IO.File.Exists(path) && IpAddress != "1.2.3.4")
            {
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.Redirect("~/Down.htm");
                return;
            }

        base.OnActionExecuting(filterContext);
    }
}
Darren Alfonso
  • 1,370
  • 2
  • 15
  • 14
2

You can define a global filter that stop all the requests if they don't come from your IP. you can enable the filter by configuration.

Massimo Zerbini
  • 3,125
  • 22
  • 22
1

I add an AppSetting in the Web.Config file:

<add key="MaintenanceMsg" value="We are currently performing some routine maintenance. We expect to be back up at around 01:00." />

I then update the global.asax file's Application_BeginRequest method to check if the appsetting has a value, if it does, I redirect everything to the maintenance page:

private void Application_BeginRequest(object sender, EventArgs e)
{
        if(!string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings["MaintenanceMsg"]) && !Request.Url.ToString().Contains("UndergoingMaintenance"))
            Response.Redirect("~/Home/UndergoingMaintenance");

 ** Do whatever you do when you don't want to show your maintenance page here**
}

Finally, create your view and controller action.

If you use Azure you can simply add and delete the value for the AppSetting in the portal so you can suspend your site in a matter of minutes without a deployment.

CodingCretin
  • 401
  • 4
  • 9