MVC4 mobile动态使用_Layout.cshtml而不是_Layout.Phone.cshtml

时间:2013-04-12 11:27:07

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

请温柔地对待我,这是我在潜伏多年后第一个关于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. 致电/主页/ HasBoth
  2. 框架提取移动设备
  3. 框架调用Layout.cshtml
  4. 框架调用HasBoth.cshtml
  5. 这很棒。

    使用Mobile

    调用
    1. 致电/主页/ HasBoth
    2. 框架选择 移动设备
    3. 框架调用Layout.Phone.cshtml
    4. 框架调用HasBoth.Phone.cshtml
    5. 同样,这也很棒。

      示例2

      我有以下文件:

      Views/Home/HasNoPhone.cshtml
      
      Views/Shared/Layout.cshtml
      Views/Shared/Layout.Phone.cshtml
      

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

      使用桌面

      调用
      1. 致电/主页/ HasNoPhone
      2. 框架提取移动设备
      3. 框架调用Layout.cshtml
      4. 框架调用HasNoPhone.cshtml
      5. 这很棒。

        使用Mobile

        调用
        1. 致电/主页/ HasNoPhone
        2. 框架选择 移动设备
        3. 此处的代码没有HasNoPhone.Phone.cshtml视图
        4. 框架调用 Layout.cshtml
        5. 框架调用 HasNoPhone.cshtml
        6. 以上是我想要实现的目标。

          修改

          使用的解决方案

          感谢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>
          ...    
          

          再次感谢所有人。

2 个答案:

答案 0 :(得分:0)

据我了解你的问题,你需要找出是否存在某种观点。我使用这样的函数放在任何可从视图访问的类中:

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 *@

答案 1 :(得分:0)

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

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

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

Creating WindsorViewPageActivator