【问题标题】:MVC4 mobile to dynamically use _Layout.cshtml instead of _Layout.Phone.cshtmlMVC4 mobile 动态使用 _Layout.cshtml 而不是 _Layout.Phone.cshtml
【发布时间】:2013-04-04 21:49:38
【问题描述】:

请对我温柔,这是我潜伏多年后在 StackOverflow 上的第一个问题。

我有一个 MVC4 站点已经启动并正在运行。我正在为使用标准 MVC 功能的网站添加移动支持:

如果没有“.Phone”版本的视图,我需要一些代码来允许框架使用 Layout.cshtml

示例 1

我有以下文件:

Views/Home/HasBoth.cshtml
Views/Home/HasBoth.Phone.cshtml

Views/Shared/Layout.cshtml
Views/Shared/Layout.Phone.cshtml

用桌面调用

  1. 呼叫 /Home/HasBoth
  2. 获取的框架不是移动设备
  3. 框架调用 Layout.cshtml
  4. 框架调用 HasBoth.cshtml

这太棒了。

手机调用

  1. 呼叫 /Home/HasBoth
  2. 框架选择移动设备
  3. 框架调用 Layout.Phone.cshtml
  4. 框架调用 HasBoth.Phone.cshtml

再一次,这也很棒。

示例 2

我有以下文件:

Views/Home/HasNoPhone.cshtml

Views/Shared/Layout.cshtml
Views/Shared/Layout.Phone.cshtml

注意:没有 Views/Home/HasNoPhone.Phone.cshtml

用桌面调用

  1. 呼叫 /Home/HasNoPhone
  2. 获取的框架不是移动设备
  3. 框架调用 Layout.cshtml
  4. 框架调用 HasNoPhone.cshtml

这太棒了。

手机调用

  1. 呼叫 /Home/HasNoPhone
  2. 框架选择移动设备
  3. 这里的代码可以解决没有 HasNoPhone.Phone.cshtml 视图
  4. 框架调用Layout.cshtml
  5. 框架调用 HasNoPhone.cshtml

以上是我想要实现的。

编辑

使用的解决方案

感谢 Zoka,我现在正在为其他希望做类似事情的人使用以下内容:

辅助方法:

/// <summary>
/// Looks to see if the view the exists.
/// </summary>
/// <param name="viewName">The view name.</param>
/// <param name="controllerContext">The controller context.</param>
/// <returns>True if the view exists.</returns>
public static bool ViewExists(string viewName, ControllerContext controllerContext)
{
  ViewEngineResult result = ViewEngines.Engines.FindView(controllerContext, viewName, null);
  return result.View != null;
}

_ViewStart.cshtml:

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

  // If a mobile viewing and no <view>.Phone.cshtml file is found set the override to desktop.                 
  // This will ensure _Layout.Phone.cshtml and yyy.Phone.cshtml partials are not called.                       
  string action = (string)ViewContext.Controller.ValueProvider.GetValue("action").RawValue;                    
  string controller = (string)ViewContext.RouteData.Values["Controller"];                                      
  string viewPhoneName = "~/Views/" + controller + "/" + action + ".Phone.cshtml";                             
  if (ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice &&                                         
    MvcHelperAbove.ViewExists(viewPhoneName, ViewContext.Controller.ControllerContext) == false) 
  {                                                                                                            
    ViewContext.HttpContext.SetOverriddenBrowser(BrowserOverride.Desktop);                                     
  }                                                                                                            
}

_Layout.Phone.cshtml

...
@* Below is essential to allow css to work when going from Mobile to Desktop *@
<script>
  $(document).ready(function () {
    $.mobile.ajaxEnabled = false;
  });
</script>
...    

再次感谢大家。

【问题讨论】:

    标签: c# asp.net-mvc layout asp.net-mvc-4 overriding


    【解决方案1】:

    据我了解,您需要了解是否存在某些观点。我使用放置在可从视图访问的任何类中的此类函数:

    public static bool ViewExists(string _name, ControllerContext _controller_context)
    {
        ViewEngineResult result = ViewEngines.Engines.FindView(_controller_context, _name, null);
        return (result.View != null);
    }
    

    然后把这个放到_ViewStart.cshtml中:

    string action = (string)ViewContext.Controller.ValueProvider.GetValue("action").RawValue;
    string controller = (string)ViewContext.RouteData.Values["Controller"];
    var viewPhoneName = "~/Views/" + controller + "/" + action + ".Phone.cshtml";
    if (YourNamespaceAndClassForAboveHelper.ViewExists(viewPhoneName, ViewContext.Controller.ControllerContext)) {
        Layout = "~/Views/Shared/Layout.Phone.cshtml"
    } else {
        Layout = "~/Views/Shared/Layout.cshtml"
    }
    

    最后在 Layout.cshml 中(分别在 Layout.Phone.cshtml 中),而不是调用 RenderBody

    string action = (string)ViewContext.Controller.ValueProvider.GetValue("action").RawValue;
    string controller = (string)ViewContext.RouteData.Values["Controller"];
    @RenderPage("~/Views/" + controller + "/" + action + ".cshtml"); @* .Phone.cshtml in Layout.Phone.cshtml *@
    

    【讨论】:

    • 感谢 Zoka,已编辑解决方案并使用了您上面的部分内容。非常感谢
    【解决方案2】:

    您可以使用现有的 jquery 移动包:

    http://www.hanselman.com/blog/MakingASwitchableDesktopAndMobileSiteWithASPNETMVC4AndJQueryMobile.aspx

    编辑: 也许您可以使用页面安装程序并在容器中注册您的页面。这样你的控制器可以询问你的容器他应该返回哪个视图。

    Creating WindsorViewPageActivator

    【讨论】:

    • 谢谢伊恩。这是我已经在使用的,问题以我提到的方式表现出来。 Zoka 的答案很接近,将与它一起玩。
    • 抱歉我之前的回答,但也许您可以使用页面安装程序并将您的页面注册到容器中。这样你的控制器可以询问你的容器他应该返回哪个视图。 stackoverflow.com/questions/4433485/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 2021-05-03
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    • 2014-08-10
    相关资源
    最近更新 更多