32
votes

I'm trying out the new ASP.NET MVC 4 Mobile Features. I made a simple app with just one controller (HomeController) and one view (Index). I also added a mobile version of the index view.

Views/Home/Index.cshtml
Views/Home/Index.Mobile.cshtml

When launching the application in a desktop browser the regular view is shown as expected, however when I launch the application in the Opera Mobile Emulator as a Samsung Galaxy S, I still get the regular view and not the mobile version.

the user agent string sent from the emulator looks like this:

Opera/9.80 (Windows NT 6.1; Opera Mobi/23731; U; en) Presto/2.9.201 Version/11.50

Any ideas on why this is not working?

Update Thanks to @nemesv I was able to solve the problem, here is my current solution, hopefully it will cover most mobile scenarios.

public class MobileDisplayMode : DefaultDisplayMode
{
    private readonly StringCollection _useragenStringPartialIdentifiers = new StringCollection
    {
        "Android",
        "Mobile",
        "Opera Mobi",
        "Samsung",
        "HTC",
        "Nokia",
        "Ericsson",
        "SonyEricsson",
        "iPhone"
    };

    public MobileDisplayMode() : base("Mobile")
    {
        ContextCondition = (context => IsMobile(context.GetOverriddenUserAgent()));
    }

    private bool IsMobile(string useragentString)
    {
        return _useragenStringPartialIdentifiers.Cast<string>()
                    .Any(val => useragentString.IndexOf(val, StringComparison.InvariantCultureIgnoreCase) >= 0);
    }
}

And i Global.asax

DisplayModeProvider.Instance.Modes.Insert(0, new MobileDisplayMode());
2
life saver. its actually stupid that the tutorial does not say this. It just feels so half ass from microsofts side. They usually are on point with their tutorials.Dejan.S
Thanks, though StringCollection does seem to be one of the most useless classes ever. Not only does it offer nothing in this code sample, nor performance, you have to write extra code (Cast<string>) for the pleasure of using it. Replace it with List<string> and live happily ever afterPandaWood

2 Answers

29
votes

ASP.Net (actually the HttpBrowserCapabilitiesBase class) doesn't recognize the Opera Mobile Emulator as a Mobile browser.

You can check this in any controller action: HttpContext.Request.Browser.IsMobileDevice will return false for the Opera Mobile browser.

Because the built in DefaultDisplayMode uses the following method to check mobile browsers you need to register your custom DisplayMode which correctly recognizes Opera Mobile.

To do this you need to add this to the Global.asax Application_Start:

DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("Mobile")
{
    ContextCondition = (context => context.GetOverriddenUserAgent()
        .IndexOf("Opera Mobi", StringComparison.OrdinalIgnoreCase) >= 0)
});
0
votes

a solution for all mobiles without a need to specify all browser names will be like this...

  protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();

        DisplayModeProvider.Instance.Modes.Insert(0,
             new DefaultDisplayMode("Mobile")
             {
                 ContextCondition = (ctx => (
                     (ctx.GetOverriddenUserAgent() != null) && ctx.Request.Browser.IsMobileDevice
             ))
             });  
    }