47

The following is a Mobile device detection code which encompasses three different conditions

if (Request.Browser.IsMobileDevice)
{
   //Do Something
}
else if (((System.Web.Configuration.HttpCapabilitiesBase)myBrowserCaps).IsMobileDevice)
{
  //Do Something
}
else if (IsMobileDevice(mobileDevices))
{
  //Do Something
}

public bool IsMobileDevice()
{
     private static string[] mobileDevices = new string[] {"iphone","ppc"
                                                   "windows ce","blackberry",
                                                   "opera mini","mobile","palm"
                                                   "portable","opera mobi" };

         string userAgent = Request.UserAgent.ToString().ToLower();
         return mobileDevices.Any(x => userAgent.Contains(x));
 }

I was forced to write three conditions as they were failing for some devices.

Can anyone suggest a better approach?

Kiquenet
  • 13,271
  • 31
  • 133
  • 232
Bisileesh
  • 1,922
  • 2
  • 16
  • 28
  • 1
    Possible duplicate of [Detecting Requests from Mobile Browsers in ASP.NET](http://stackoverflow.com/questions/2653765/detecting-requests-from-mobile-browsers-in-asp-net) – Dijkgraaf Jun 21 '16 at 02:51
  • Detect a device from an user agent string it's not easy as it seems because browsers uses to lie. I am working to port a true parser bases on Antlr runtime for .NET, you can take a look there: https://github.com/OrbintSoft/yauaa.netstandard – Stefano Balzarotti Nov 20 '18 at 10:53

8 Answers8

71

taking and change a bit the code from : http://detectmobilebrowsers.com/

public static class Utils
{    
    // update : 5/April/2018
    static Regex MobileCheck = new Regex(@"(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled);
    static Regex MobileVersionCheck = new Regex(@"1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled);

    public static bool fBrowserIsMobile()
    {
        Debug.Assert(HttpContext.Current != null);

        if (HttpContext.Current.Request != null && HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"] != null)
        {
            var u = HttpContext.Current.Request.ServerVariables["HTTP_USER_AGENT"].ToString();

            if (u.Length < 4)
                return false;

            if (MobileCheck.IsMatch(u) || MobileVersionCheck.IsMatch(u.Substring(0, 4)))
                return true;
        }

        return false;
    }
}

and this is how you call it.

if (Utils.fBrowserIsMobile())
{
    // go to mobile pages
}

What I have change to the code from http://detectmobilebrowsers.com/

  • Make static compile the Regex for faster check.
  • Fix a bug in the case that u is less than 4 characters.
  • Other checks.

Using Cache

This code is fast, and the one trick is that we have made static and pre compile the regex. How ever i suggest after the first check to save the result on user session and use that session variable that is a lot faster.

Aristos
  • 63,580
  • 14
  • 112
  • 146
  • @Aristos: I tried it twice, recompiled everything; deleted out all old stuff. Same problem (and in fact i did that already yesterday, since i was really astonished about the poor performance - otherwise i wouldn't have posted). – johngrinder Dec 05 '14 at 18:57
  • @johngrinder I believe you, but you may have some other issues... my sites, that use this routine and other are extreme fast... how ever because I cache the results, if I find time I will timing it and come back with results. – Aristos Dec 06 '14 at 07:47
  • @Aristos Doesnt Detect Andriod Version 2.3.5HTC 3.0 Softwae Number 3.13.661.4 As mobile – clamchoda Jun 17 '15 at 18:18
  • @Apollo On first call of home page, or on each page of your site when first called - there you check if this is a mobile and you redirect them on the "same" mobile page if you can - The home page is the easy one, because you have only one check, and you know where to send them... I make only one check per user, then I store the results on session and not check again ! Also I have place that code on a dll library that I use on the site, on a global static class. – Aristos Oct 13 '16 at 18:09
  • Was very helpful for me. Just can you please tell me why they should be static? Is static make problems here if I have more than 1000 request per second or not? Can you please tell me about static usage here? Thanks. –  Feb 27 '17 at 11:01
  • @user5032790 Yes - if you do it static, then the regedit is compile the request and keep that in memory - if not make it static, the regedit is compile it in every call and this is slow. All that you place it inside a class (static class) and you easy call it. I have update the code to full working class . You dont need to make it static, but its a lot faster. – Aristos Feb 27 '17 at 21:16
  • @BradyMoritz Thank you for this note, I need to fist check it out first because this code is working years now correct. Now I check the source code, in the System.dll the source inside is the same - from system.web is complicate – Aristos Apr 04 '18 at 13:56
5

This code works in my case.

public void IsMobileBrowser()
{
    String labelText = "";
    System.Web.HttpBrowserCapabilities myBrowserCaps = Request.Browser;
    if (((System.Web.Configuration.HttpCapabilitiesBase)myBrowserCaps).IsMobileDevice)
    {
        labelText = "Browser is a mobile device.";
    }
    else
    {
        labelText = "Browser is not a mobile device.";
    }
    ScriptManager.RegisterStartupScript(this, this.GetType(), "", "alert('"+ labelText + "');", true);
}

Reference: HttpCapabilitiesBase.IsMobileDevice Property

Manjunath Bilwar
  • 1,507
  • 14
  • 14
  • 1
    why `Request.Browser.IsMobileDevice` vs `((System.Web.Configuration.HttpCapabilitiesBase)myBrowserCaps).IsMobileDevice` ? – Kiquenet Dec 12 '18 at 14:19
  • Because of Request.Browser.IsMobileDevice was failed to detect some devices that's why I recommend this option @Kiquenet – Manjunath Bilwar Dec 27 '18 at 14:11
5

I'm using DeviceDetector.NET since I often also need to separate smartphones and tablets

Install it Install-Package DeviceDetector.NET

Then use it like this

DeviceDetectorSettings.RegexesDirectory = "C:\\DeviceDetector.NET.3.11.4\\";
var dd = new DeviceDetector(Request.UserAgent);
dd.Parse();

var device = dd.GetDeviceName();

if(device == "tablet") {}
if(device == "smartphone") {}
if(device == "desktop") {}

/**
Possible returns
--
desktop
smartphone
tablet
feature phone
console
tv
car browser
smart display
camera
portable media player
phablet
**/

The regexes can be found in the packages directory

Eric Herlitz
  • 22,490
  • 25
  • 106
  • 149
4

Scott Hanselman has a great blog post on the subject. He refers to a 3rd party solution called 51Degrees.

Daniel A. White
  • 174,715
  • 42
  • 343
  • 413
3

The existing browser definitions are terrible. Ideally you want to use the WURFL database to augment those definitions.

Luckily this is pretty easy using the 51 Degrees.mobi library.

There is also a Nuget package:

Install-Package 51Degrees.mobi
Josh
  • 43,774
  • 7
  • 97
  • 123
1

I would suggest storing the list of user agents in the web.config to make it easier to configure. IsMobileDevice is not actively updated with new browsers therefore it does have it's limitations which is why you need the further check.

The 51Degrees.mobi package would be a more reliable alternative.

James
  • 75,060
  • 17
  • 154
  • 220
1

Check the UserAgent in codebehind for "Mobi" similar to javascript referenced here.

                if (Request.UserAgent.Contains("Mobi") == true)
                {
                    DivToShowWhenMobileDevice.Style.Add("display", "");
                }
                else
                {
                    DivToShowWhenMobileDevice.Style.Add("display", "none");
                }
Community
  • 1
  • 1
Al Belmondo
  • 654
  • 7
  • 24
0

Well yes, if you want to be sure the useragent is probably the best way. You can also look at this method:

http://msdn.microsoft.com/en-us/library/system.web.configuration.httpcapabilitiesbase.ismobiledevice.aspx

It should have some issues with new browsers and such. But it's this one of as you currently do.

Lars Holdgaard
  • 8,386
  • 20
  • 85
  • 170