mobileasp.net-mvc-5wurfl

MVC5 DisplayModeProvider registration problems


so I have an mvc 5 application with 3 display modes, desktop (default), mobile, and tablet. I'm using WURFL to figure out devices. Here's the code called from global.cs to register:

public static void RegisterDisplayModes(IList<IDisplayMode> displayModes){
        var datafile = HttpContext.Current.Server.MapPath(WurflDataFilePath);
        var configurer = new InMemoryConfigurer().MainFile(datafile);
        var manager = WURFLManagerBuilder.Build(configurer);
        HttpContext.Current.Cache[WURFLMANAGER_CACHE_KEY] = manager;

        bool mobileEnabled = ConfigurationManager.AppSettings["EnableMobileSite"] == "true";
        bool tabletEnabled = ConfigurationManager.AppSettings["EnableTabletSite"] == "true";

        var modeDesktop = new DefaultDisplayMode("") {
                                                        ContextCondition = (c => c.Request.IsDesktop())
                                                    };
        var modeMobile = new DefaultDisplayMode("mobile"){
                                                             ContextCondition = (c => c.Request.IsMobile())
                                                         };
        var modeTablet = new DefaultDisplayMode("tablet"){
                                                             ContextCondition = (c => c.Request.IsTablet())
                                                         };

        displayModes.Clear();
        if (mobileEnabled) displayModes.Add(modeMobile);
        if (tabletEnabled) displayModes.Add(modeTablet);
        displayModes.Add(modeDesktop);
    }

I'm using some extension methods to HttpRequestBase, as discussed in http://msdn.microsoft.com/en-us/magazine/dn296507.aspx:

public static bool IsDesktop(this HttpRequestBase request){
        return true;
    }
    public static bool IsMobile(this HttpRequestBase request) {
        return IsMobileInternal(request.UserAgent) && !IsForcedDesktop(request);
    }
    public static bool IsTablet(this HttpRequestBase request) {
        return IsTabletInternal(request.UserAgent) && !IsForcedDesktop(request);
    }

    public static void OverrideBrowser(this HttpRequestBase request, bool forceDesktop){
        request.RequestContext.HttpContext.Cache[OVERRIDE_BROWSER_CACHE_KEY] = forceDesktop;
    }

    public static bool IsForcedDesktop(this HttpRequestBase request){
        var isForced = request.RequestContext.HttpContext.Cache[OVERRIDE_BROWSER_CACHE_KEY];
        return isForced != null ? isForced.ToString().ToBool() : false;
    }

    private static bool IsMobileInternal(string userAgent) {
        var device = WURFLManagerBuilder.Instance.GetDeviceForRequest(userAgent);
        if (device.IsTablet() == true) {
            return false;
        } else {
            return device.IsMobile();
        }
    }

    private static bool IsTabletInternal(string userAgent) {
        var device = WURFLManagerBuilder.Instance.GetDeviceForRequest(userAgent);
        return device.IsTablet();
    }

It all works fine for a while, but then after an hour or so, mobile and tablet devices start displaying the desktop views, and the desktop view starts showing the ViewSwitcher shared view (I assume most people are familiar with it, it just allows you to show the desktop view from a mobile device). It's almost like that caching bug in mvc4. I have tried removing my code to register the display modes, and just went with the default mvc mobile support, and it works fine it has the same issue! So clearly there's a problem in here somewhere... can anyone see anything obvious? Almost impossible to debug cause problems only start coming up after a long time, and even then only on the live system really! Any ideas?

Thanks heaps... been on this issue for way too long now... Cheers Andy

EDIT: even stripping it right back to the default implementations creates the issue. I added some debugging code to make sure I'm actually running mvc5, but it appears I am. I've also tried the initially recommended workaround for the issue on mvc4 by disabling the cache, still no joy. Is there really no one with info on this?


Solution

  • So I finally figured it out. Very simple as usual. For some reason I used RequestContext.HttpContext.Cache to save the status when someone wants the full view as opposed to the mobile view. I've never used HttpContext.Cache, I'm pretty sure I would have taken that from a blog somewhere - can't find it anymore though. So all that happened was that it would switch the view for everyone, not just the one person. Can't believe it took weeks to figure that out. Hope it helps someone else at some point.