ASP.NET MVC 4移动显示模式停止工作

时间:2012-02-19 23:03:03

标签: asp.net-mvc browser mobile override asp.net-mvc-4

ASP.NET MVC 4中的移动显示模式在正常运行一小时后停止提供正确的视图,尽管浏览器覆盖正确检测到被覆盖的移动设备。

回收应用程序池暂时解决了这个问题。

新的浏览器覆盖功能正确地允许移动设备查看网站的桌面版本,反之亦然。但经过大约一个小时的正常运行时间后,移动设备不再呈现移动视图;仅呈现默认桌面Razor模板。唯一的解决方法是回收应用程序池。

奇怪的是,浏览器覆盖cookie继续运行。主_Layout.cshtml模板正确显示“移动”或“桌面”文本,具体取决于ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice的值,但仍会呈现错误的视图。这让我相信问题在于DisplayModes。

有问题的行动没有被缓存:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]

我正在使用51Degrees进行移动侦测,但我认为这不会影响被覆盖的移动侦测。这是ASP.NET MVC 4 Beta&的DisplayModes功能中的错误吗?开发者预览版,还是我做错了什么?


以下是DisplayModes中的Application_Start设置:

DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone")
{
    ContextCondition = context =>
        context.GetOverriddenBrowser().IsMobileDevice
        && (context.Request.UserAgent.IndexOf("iPhone", StringComparison.OrdinalIgnoreCase) >= 0
        || context.Request.UserAgent.IndexOf("Android", StringComparison.OrdinalIgnoreCase) >= 0
        || !context.Request.Browser.IsMobileDevice)
    });

/*  Looks complicated, but renders Home.iPhone.cshtml if the overriding browser is
    mobile or if the "real" browser is on an iPhone or Android. This falls through
    to the next instance Home.Mobile.cshtml for more basic phones like BlackBerry.
*/

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

7 个答案:

答案 0 :(得分:21)

这是MVC 4中的一个已知问题(Codeplex:#280: Multiple DisplayModes - Caching error, will show wrong View)。这将在下一版本的MVC中修复。

与此同时,您可以在此处安装解决方案包:http://nuget.org/packages/Microsoft.AspNet.Mvc.FixedDisplayModes

对于大多数应用程序,只需安装此程序包即可解决此问题。

对于某些自定义已注册视图引擎集合的应用程序,您应该确保引用 Microsoft.Web.Mvc.FixedRazorViewEngine Microsoft.Web.Mvc.FixedWebFormViewEngine而不是默认的视图引擎实现。

答案 1 :(得分:1)

我遇到了类似的问题,当基于桌面视图的基于网页的视图与基于剃刀的移动视图混合时,结果就是一个错误。

有关详细信息,请参阅http://aspnetwebstack.codeplex.com/workitem/276

答案 2 :(得分:1)

可能是ASP.NET MVC 4中与缓存视图相关的错误,请参阅:

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

答案 3 :(得分:0)

我不能代表这个特定的堆栈(我仍然在MVC2中),但检查输出缓存设置(在您的控制器或视图中 - 以及在您的应用程序和机器级别的web.config中)。我已经看到它最初为前几个用户工作,然后桌面浏览器在ASP决定缓存的时候出现,然后每个人都获得相同的视图。我们已经避免了输出缓存,希望以后能够解决这个问题。

答案 4 :(得分:0)

如果您希望所有移动设备都使用相同的移动设备,您可以使用

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

当然,你需要在名为_Layout.Mobile.cshtml的共享布局文件夹中创建一个视图

如果您想为每种类型的设备或浏览器设置单独的布局,则需要执行此操作;

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)
            });

当然,您需要在共享布局文件夹中为每个命名的

创建一个视图

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

答案 5 :(得分:0)

你能不能这样做吗?

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.
}

答案 6 :(得分:0)

所以这里的家伙是你所有担忧的答案..... :)

为避免此问题,您可以指示ASP.NET根据访问者是否使用移动设备来更改缓存条目。将VaryByCustom参数添加到页面的OutputCache声明中,如下所示:

<%@ 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);
}

这将确保页面的移动访问者不会收到以前由桌面访问者放入缓存的输出。

请参阅microsoft发布的这份白皮书。 :)

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

谢谢并保持编码.....