C# 当控制器操作包含视图路径时,显示模式不会更改为移动视图

C# 当控制器操作包含视图路径时,显示模式不会更改为移动视图,c#,asp.net-mvc,razor,asp.net-mvc-5.2,device-detection,C#,Asp.net Mvc,Razor,Asp.net Mvc 5.2,Device Detection,我正在尝试在ASP.NET MVC应用程序中实现特定于设备的视图,如以下所述: 或在此: 尽管上面的文章是针对ASP.NET MVC4的,但它们的内容与我的应用程序使用ASP.NET MVC 5.2的框架的更高版本相关 我偶然发现了一个问题。我有以下控制器: public class TestController: Controller { public ActionResult Test() { return View(new TestModel());

我正在尝试在ASP.NET MVC应用程序中实现特定于设备的视图,如以下所述: 或在此:

尽管上面的文章是针对ASP.NET MVC4的,但它们的内容与我的应用程序使用ASP.NET MVC 5.2的框架的更高版本相关

我偶然发现了一个问题。我有以下控制器:

public class TestController: Controller
{
    public ActionResult Test()
    {
        return View(new TestModel());
    }
    public ActionResult Test2()
    {
        return View("~/Views/Test/Test.cshtml", new TestModel());
    }
}
测试模型非常基本:

public class TestModel
{
    public string TheDate
    {
        get
        {
            return DateTime.Now.ToString();
        }
    }
}
我在~/views/Test文件夹中有两个视图:

Test.cshtml

@model MyNamespace.Models.TestModel
<!DOCTYPE html>
<html>
<head><title></title></head>
<body>
<h1>This is the desktop view</h1>
<p>model data: @Model.TheDate</p>
</body>
</html>
Test.Mobile.cshtml

@model MyNamespace.Models.TestModel
<!DOCTYPE html>
<html>
<head><title></title></head>
<body>
<h1>This is the mobile view</h1>
<p>model data: @Model.TheDate</p>
</body>
</html>
我已经实现了上面链接中描述的解决方案

当请求/test/test时,通过桌面浏览器请求时,我会获得正确的视图test.cshtml;从移动仿真器请求时,我会获得正确的视图test.Mobile.cshtml。然而,当请求/test/test2时,我总是得到桌面视图

我一直在寻找问题的解决方案,但每个人似乎都在一次又一次地重复相同的场景,即/test/test场景,似乎没有人尝试过/test/test2场景。甚至可以覆盖该功能吗?我不怕用覆盖默认razor/MVC功能弄脏我的手,但我真的不知道从哪里开始


非常感谢您的帮助。

我不确定是否要覆盖此功能,但您可以使用自定义RazorViewEngine类和覆盖方法,并在其中使用Request.Browser.IsMobileDevice检测移动设备,作为如下解决方法:

public class CustomViewEngine : RazorViewEngine
{
      public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
      {
           var viewPath = controllerContext.HttpContext.Request.Browser.IsMobileDevice ? "MobilePath" : "defaultPath";

           return base.FindView(controllerContext, viewPath, "MasterName", useCache);
      }
}
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine())
请不要忘记在应用程序中注册自定义视图引擎,如下所示:

public class CustomViewEngine : RazorViewEngine
{
      public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
      {
           var viewPath = controllerContext.HttpContext.Request.Browser.IsMobileDevice ? "MobilePath" : "defaultPath";

           return base.FindView(controllerContext, viewPath, "MasterName", useCache);
      }
}
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine())

我希望有些东西不会触动控制器的代码库。另外,它并不像DisplayMode解决方案那样通用——如果我想采用平板电脑模式,然后是LegacyPhone模式,等等,该怎么办?这些类型操作的return语句很快就会变得相当麻烦。对于更通用的解决方案,您可以通过继承RazorViewEngine类创建自己的自定义视图引擎,并使用base.FindView方法设置指向特定视图的路径。这样的话,你所有的设备检查都会在一个地方进行,这听起来也不对。我的问题是当返回的视图对象已经在构造函数参数中声明了viewpath时。据我所知,在这种情况下不会调用FindView方法-引擎已经知道在哪里搜索视图。不过,我会尝试看看它是否被调用,如果是的话,我也会在其中填充一些设备检测逻辑。我会让你知道结果的,尽管我现在有点悲观。嗯,它似乎起作用了,但需要做很多工作,尽管我没有抱怨。FindView方法是为每个基于视图的结果调用的,但是有很多警告:该方法接受一个字符串,该字符串可能是视图虚拟路径,也可能不是我必须检查的视图虚拟路径,还有另一个名为Master的字符串。我假设后者是@Layout指令的内容(如果有)。我需要调查,但这似乎是一条路要走。如果你把你的评论变成正确的答案,我会接受的。编辑答案。我很高兴我能够提供帮助: