Problem
I want to check client’s browser version, and if it’s too old, display a message that the user should update their browser in order to use the website. The website is built using ASP.NET MVC.
I have implemented 2 different solutions:
Solution 1 – Server side checking:
I have created an ActionFilter
which checks if the browser is supported? If not it redirects to a static page: NotSupportedBrowser.aspx
public class BrowserSupportFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
string browserInfo;
if (BrowserHelper.IsOutdatedBrowser(out browserInfo))
{
filterContext.Result = new RedirectResult("/ErrorPages/NotSupportedBrowser.aspx?browserInfo=" + browserInfo);
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
}
And this is my BrowserHelper
class which checks if the browser is supported:
public static class BrowserHelper
{
public static bool IsOutdatedBrowser(out string browserInfo)
{
bool isOutdated = false;
var browser = HttpContext.Current.Request.Browser;
if (!string.IsNullOrEmpty(browser.Browser) && float.TryParse(browser.Version, out float browserVersion))
{
switch (browser.Browser)
{
case "Chrome":
if (browserVersion < 57) { isOutdated = true; }
break;
case "Edge":
if (browserVersion < 15) { isOutdated = true; }
break;
case "Safari":
if (browserVersion < 12) { isOutdated = true; }
break;
case "Mobile Safari":
if (browserVersion < 12) { isOutdated = true; }
break;
case "Firefox":
if (browserVersion < 50) { isOutdated = true; }
break;
case "Opera":
if (browserVersion < 50) { isOutdated = true; }
break;
case "Vivaldi":
if (browserVersion < 1) { isOutdated = true; }
break;
case "Yandex":
if (browserVersion < 17) { isOutdated = false; }
break;
case "InternetExplorer":
isOutdated = true;
break;
default:
isOutdated = false;
break;
}
}
browserInfo = $"{browser.Browser}{browser.Version}";
return isOutdated;
}
}
Solution 2 – Client side checking
In the second solution, I check the browser in the client side and show a popup, letting the user know that their browse is not supported:
I have created _BrowserSupport.cshtml PartialView:
I got the code for testing the browser from this stackoverflow question.
<script>
navigator.browserInfo = (function () {
alert(navigator.userAgent);
var ua = navigator.userAgent, tem,
M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=/))/?s*(d+)/i) || [];
if (/trident/i.test(M[1])) {
tem = /brv[ :]+(d+)/g.exec(ua) || [];
return 'IE ' + (tem[1] || '');
}
if (M[1] === 'Chrome') {
tem = ua.match(/b(OPR|Edge)/(d+)/);
if (tem != null) return tem.slice(1).join(' ').replace('OPR', 'Opera');
}
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
if ((tem = ua.match(/version/(d+)/i)) != null) M.splice(1, 1, tem[1]);
return M.join(' ');
})();
//document.getElementById('printVer').innerHTML=navigator.browserInfo
var str = navigator.browserInfo;
var browser = str.substring(0, str.indexOf(" "));
var version = str.substring(str.indexOf(" "));
version = version.trim();
version = parseFloat(version);
var isOutdated = false;
switch (browser) {
case "Chrome":
if (version < 57) { isOutdated = true; }
break;
case "Edge":
if (version < 16) { isOutdated = true; }
break;
case "Safari":
if (version < 12) { isOutdated = true; }
break;
case "Mobile Safari":
if (version < 11) { isOutdated = true; }
break;
case "Firefox":
if (version < 62) { isOutdated = true; }
break;
case "Opera":
if (version < 50) { isOutdated = true; }
break;
case "Vivaldi":
if (version < 1) { isOutdated = true; }
break;
case "Yandex":
if (version < 17) { isOutdated = false; }
break;
case "IE":
isOutdated = true;
break;
}
if (isOutdated) {
alert("Your browser is not supported:" + browser + version);
}
</script>
I include the above partial view in the head
section of all of my page Layouts, e.g.
samplePageLayout:
<head>
@Html.Partial("Common/_BrowserSupport")
</head>
Trade-offs
Both solutions works… I am not sure which one would be better.
-
The advantage of doing the check on the Server side is that my html
document becomes smaller and there will be less data to download on
every single request. -
The advantage of doing the check on the client side is that I am
using the client’s processing power to do the check and therefore
there is less task for the Server.
I am asking for recommendation to choose the better option.
Solution
I always go with the version that would be a best fit to the project.
This means, you need to consider the overall project coding syntax, and how much code in the client side, to know where to focus more.
Some projects focuses on server side more than using the client side handling, so in this case using the server side would be better to keep the code in harmony.
For the switch
part, it would be more maintainable if you just use Dictionary
in the server side, or object
in client side.
Server-Side :
public static class BrowserHelper
{
private static readonly IReadOnlyDictionary<string , int> _browserMinimumSupportedVersions = new Dictionary<string, int>
{
{"Chrome", 57},
{"Edge", 15},
{"Safari", 12},
{"Mobile Safari", 12},
{"Firefox", 50},
{"Opera", 50},
{"Vivaldi", 1},
{"Yandex", 17}
};
public static bool IsOutdatedBrowser(out string browserInfo)
{
browserInfo = null;
var browser = HttpContext.Current.Request.Browser;
if(browser.Browser == "InternetExplorer") { return true; }
browserInfo = $"{browser.Browser}{browser.Version}";
return _browserMinimumSupportedVersions.TryGetValue(browser.Browser , out int minVersion) && float.TryParse(browser.Version , out float browserVersion) && browserVersion < minVersion;
}
}
you can achieve the same in the client side by doing this :
function isOutdatedBrowser(name, version) {
if(name == 'IE') { return true; }
const minimumVersions =
{
"Chrome": 57,
"Edge": 15,
"Safari": 12,
"Mobile Safari": 12,
"Firefox": 50,
"Opera": 50,
"Vivaldi": 1,
"Yandex": 17
};
var browserVersion = minimumVersions[browser];
return browserVersion && version < browserVersion;
}