ASP.NET MVC:在非移动视图中使用移动布局

4
我一直在使用这篇文章http://www.hanselman.com/blog/MakingASwitchableDesktopAndMobileSiteWithASPNETMVC4AndJQueryMobile.aspx作为指南,开发了网站主页的移动版本。
我有两个控制器:HomeController和EventController HomeController有一个Index视图,而EventController则有一个Detail视图
我成功创建了一个Index.mobile.cshtml视图,并且正确地使用了_Layout.mobile.cshtml。现在,当用户在手机上访问mysite.com/Home/Index时,它会正确地显示移动版本。
现在,如果同一用户访问mysite.com/Event/Detail/123,则默认的“桌面”视图应该显示(我没有一个Detail.mobile.cshtml视图)。
问题是Detail.cshtml视图确实被调用,但它尝试使用_Layout.mobile.cshtml布局,使页面看起来很糟糕。
有没有办法实现这个(对于那些我没有在移动设备上实现的视图,只渲染桌面视图与桌面布局)?
谢谢!

1
Stack Exchange的开发人员在这里编写了一篇关于在ASP .NET MVC中实现移动视图的好文章:http://kevinmontrose.com/2011/07/17/mobile-views-in-asp-net-mvc3/。 - Ben Smith
你使用的是MVC4还是MVC5? - stink
4个回答

3
请将以下代码添加到您的_ViewStart.cshtml文件末尾:
DisplayModeProvider.Instance.RequireConsistentDisplayMode = true;

这将防止应用程序在移动布局中显示非移动视图,反之亦然。

好的!有一个小错误,该属性的名称是RequireConsistentDisplayMode而不是RequiresConsistentDisplayMode。 - binard
@jbbi 好的,谢谢,我相信你的话;-) 根据指示进行了更新。 - Christopher King

1

我以前没有使用过这个 NUGET Pakage,但请注意它提到:

默认情况下,它只允许在移动设备上在桌面和移动设备之间切换。为什么?请查看以下代码的第一行: 代码首先检查移动设备如下:

@if (Request.Browser.IsMobileDevice && Request.HttpMethod == "GET")
{
    <div class="view-switcher ui-bar-a">
        @if (ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice)
        {
            @: Displaying mobile view
            @Html.ActionLink("Desktop view", "SwitchView", "ViewSwitcher", new { mobile = false, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" })
        } 
        else 
        {
            @: Displaying desktop view
            @Html.ActionLink("Mobile view", "SwitchView", "ViewSwitcher", new { mobile = true, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" })
        }
    </div>
}

根据MSDN:

一般而言,我们建议您避免在视图中编写逻辑。它很难发现,甚至更难测试。相反,视图中的逻辑应该移动到视图模型或控制器操作中。

问题解决:根据需要更改默认逻辑,也许通过跟踪视图(断点也适用于视图)以满足您的目的。

您需要查看此MSDN主题,了解MVC和命名包的结合情况。了解操作中发生的情况可以解决您的问题。


1
请注意,似乎您可以通过在控制器操作中放置这行代码来逐个解决此问题。

HttpContext.SetOverriddenBrowser(BrowserOverride.Desktop);

然而,我真正希望的解决方案基本上是这样说的:如果当前视图名称/路径中没有.Mobile,则不要将布局切换到.Mobile版本。

0

最简单的解决方案是在Detail.cshtml中明确地使用_Layout.cshtml来覆盖布局:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

如果您想要更通用的解决方案,可以尝试以下方法:
创建自定义的DisplayMode:
public class MobileDisplayMode : IDisplayMode
{
    private bool _mobileViewWasUsed = false;

    public override DisplayInfo GetDisplayInfo(HttpContextBase httpContext, string virtualPath, Func<string, bool> virtualPathExists)
    {
        string filePath = this.TransformPath(virtualPath, this._suffix);
        if (filePath != null && virtualPathExists(filePath))
        {
            if (!_mobileViewWasUsed)
            {
                if (virtualPath.IndexOf("layout", StringComparison.InvariantCultureIgnoreCase) != -1)
                    return (DisplayInfo) null;

                _mobileViewWasUsed = true;
            }
            return new DisplayInfo(filePath, (IDisplayMode) this);
        }
        else
            return (DisplayInfo) null;
    }
}

将其添加到 global.asax 文件中:

DisplayModeProvider.Instance.Modes.Insert(0, new MobileDisplayMode("mobile"));

很遗憾,由于基于一些未经批准的假设(例如每个请求创建DisplayMode等),我没有机会测试它。无论如何,如果您有兴趣并有机会测试它,那将是非常棒的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接