MVC has kept me busy lately. While I like MVC overall, the "newcomer" doesn't always stack up all that well against WebForms, but does offer a great new approach to web programming. I'll add occasional comments as I run into curious things with MVC.
For years, I always hated updating my sites. Even with DotNetNuke, making changes always meant either making them on my development system first, backing up the database, restoring it to the live site or making changes to the live site little by little - always hoping no one would notice my "work in progress".
With my current MVC project, I found a trivially simple way to do major and even minor updates without letting anyone see a partial update. First off, I have no problem shutting down my site for a few minutes (displaying a suitable status page to visitors) while I update the site. The obstacle was that with a feature like ASP.NET's app_offline.htm page, it locks me out too!
For my MVC projects, I can define a simple action filter that only allows access to the site from my IP address. Anyone else will be redirected to a web page (/App_NOTOffline.htm). That's an odd name, I admit, but it's the name of my App_Offline.htm page while the site is NOT offline (for me).
At the same time, the same action filter happens to redirect all IE6 users (and other older browsers) to a "friendly" page that lets them know that my sites don't support their browser.
This gives me the ability to fine-tune the live website without having visitors potentially exposed to my less than perfect final work. They'll get redirected to my "Sorry, the site is not available" page. Maybe, down the road I'll use a simple website staging mechanism, so visitors get the original site, while I'm working on the new site.
Here is the partial source for the action filter:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpBrowserCapabilitiesBase caps = HttpContext.Request.Browser;
if (caps != null && !SupportedBrowser(caps)) {
filterContext.Result = Redirect("/App_UnsupportedBrowser.htm");
return;
}
if (!string.IsNullOrEmpty(SiteProperties.Properties.LockedIP) && HttpContext.Request.UserHostAddress != SiteProperties.Properties.LockedIP) {
filterContext.Result = Redirect("/App_NOTOffline.htm");
return;
}
base.OnActionExecuting(filterContext);
}
private bool SupportedBrowser(HttpBrowserCapabilitiesBase caps)
{
switch (caps.Browser.ToLower()) {
case "safari":
if (caps.MajorVersion < 4) return false;
break;
case "chrome":
if (caps.MajorVersion < 5) return false;
break;
case "firefox":
if (caps.MajorVersion < 3) return false;
if (caps.MajorVersion == 3 && caps.MinorVersion < 5) return false;
break;
case "ie":
if (caps.MajorVersion < 7) return false;
break;
}
return true;
}
SiteProperties.Properties.LockedIP is an external data source which holds my IP address which is saved by other UI code (you'll have to adapt this for your use). I have simple controllers, with which I can turn this on and off by saving my IP address.
Granted, with an action filter you would have to define the action filter for each controller. In my case, I actually derive all controller classes from my base class, which automatically provides this processing, so I don't have to add it to each controller.
Loading