ASP.NET MVC 4 Mobile Display Modes Stop Working

喜欢而已 提交于 2019-11-28 17:15:05
marcind

This is a known issue in MVC 4 (Codeplex: #280: Multiple DisplayModes - Caching error, will show wrong View). This will be fixed in the next version of MVC.

In the meantime you can install a workaround package available here: http://nuget.org/packages/Microsoft.AspNet.Mvc.FixedDisplayModes.

For most applications simply installing this package should resolve the issue.

For some applications that customize the collection of registered view engines, you should make sure that you reference Microsoft.Web.Mvc.FixedRazorViewEngine or Microsoft.Web.Mvc.FixedWebFormViewEngine, instead of the default view engine implementations.

I had a similar issue and it turned out to be a bug when mixing webforms based desktop views with razor based mobile views.

See http://aspnetwebstack.codeplex.com/workitem/276 for more info

Possibly a bug in ASP.NET MVC 4 related to caching of views, see:

http://forums.asp.net/p/1824033/5066368.aspx/1?Re+MVC+4+RC+Mobile+View+Cache+bug+

I can't speak for this particular stack (I'm still in MVC2) but check your output caching setup (either in your controllers or views - and in your web.config in your app and at the machine level). I've seen it work initially for the first few users and then a desktop browser comes in right around the time ASP decides to cache, then everyone gets the same view. We've avoided output caching as a result, hoping this would get addressed later.

If you want all mobile devices to use the same mobile layout you can use

DisplayModeProvider.Instance.Modes.Insert(1, new DefaultDisplayMode("Mobile") 
{ 
    ContextCondition = context => 
        context.GetOverriddenBrowser().IsMobileDevice 
}); 

And of course you need to make a view in the shared layout folder named _Layout.Mobile.cshtml

If you want to have a separate layout for each type of device or browser you need to do this;

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

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

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

And of course you need to make a view in the shared layout folder for each named

_Layout.Android.cshtml _Layout.iPhone.cshtml _Layout.Mobile.cshtml

Can you not just do this?

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    // Code removed for clarity.

    // Cache never expires. You must restart application pool
    // when you add/delete a view. A non-expiring cache can lead to
    // heavy server memory load.

    ViewEngines.Engines.OfType<RazorViewEngine>().First().ViewLocationCache =
        new DefaultViewLocationCache(Cache.NoSlidingExpiration);

    // Add or Replace RazorViewEngine with WebFormViewEngine
    // if you are using the Web Forms View Engine.
}

So guys here is the answer to all of your worries..... :)

To avoid the problem, you can instruct ASP.NET to vary the cache entry according to whether the visitor is using a mobile device. Add a VaryByCustom parameter to your page’s OutputCache declaration as follows:

<%@ OutputCache VaryByParam="*" Duration="60" VaryByCustom="isMobileDevice" %>
Next, define isMobileDevice as a custom cache parameter by adding the following method override to your Global.asax.cs file:

public override string GetVaryByCustomString(HttpContext context, string custom)
{
    if (string.Equals(custom, "isMobileDevice", StringComparison.OrdinalIgnoreCase))
        return context.Request.Browser.IsMobileDevice.ToString();

    return base.GetVaryByCustomString(context, custom);
}

This will ensure that mobile visitors to the page don’t receive output previously put into the cache by a desktop visitor.

please see this white paper published by microsoft. :)

http://www.asp.net/whitepapers/add-mobile-pages-to-your-aspnet-web-forms-mvc-application

Thanks and Keep coding.....

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!