MVC 即时更改 ViewName
MVC Change ViewName on the fly
我有一个项目,我想向桌面和移动用户显示不同的视图,主要是为了获得更好的体验和速度。现在我正在使用 51degrees 来告诉我请求是来自移动用户还是桌面用户,然后在我的 Action Filter 中我将更改视图名称从 "Index" 到 "Index.Mobile",问题是我在视图中遇到了一些问题,我根本不想使用布局。
这是我的方法:
public override void OnActionExecuted( ActionExecutedContext filterContext )
{
var result = filterContext.Result as ViewResult;
var view = filterContext.ActionDescriptor.ActionName;
//IsMobile is filled on my OnActionExecuting method
var IsMobile = filterContext.Controller.ViewBag.IsMobile;
if( result == null ) return;
string viewName;
string masterName;
if( IsMobile )
{
viewName = view + ".Mobile";
masterName = "_Layout.Mobile";
//Check if view exists
var viewResult = ViewEngines.Engines.FindView( filterContext.Controller.ControllerContext, viewName, null );
if( viewResult.View == null )
{
viewName = view;
}
}
else
{
viewName = view;
masterName = "_Layout";
}
result.ViewName = viewName;
result.MasterName = masterName;
}
发生的事情是,我在这里为 MasterName 或 Layout 和两个特定的 Controllers 我需要将它设置为 null 但它仍然获取我之前设置的 Layout。
我需要的是,此方法将设置视图和布局名称,如果需要,我将在加载的视图中将布局设置为 null。
可以吗?
编辑
我尝试实现另一种方法,Link,但我找不到更改布局视图的方法,只能更改操作。
您可以像 "Areas/Mobile" 一样在您的项目中创建一个文件夹,并将您的视图、控制器甚至模型(移动视图模型)保存在其中。您只需创建一个路由规则,将来自移动设备的请求传递到 "Area/Mobile" 内的控制器。管理和构建网站的移动版本会容易得多。
经过一些调试后,我发现在 View
中设置值不起作用,因为 ViewEngine
会忽略这个新值并保持在 OnActionExecuted
方法中设置的值.
我设法使用相同的方法解决了我的问题,但添加了一个 ViewBag 来告诉我这个特定视图是否需要布局。由于 OnActionExecuted
将在 Controller
之后和 View
之前执行,因此可以在 Controller
处将值设置为 true/false,然后在 OnActionExecuted
.
这是工作示例:
public override void OnActionExecuted( ActionExecutedContext filterContext )
{
var result = filterContext.Result as ViewResult;
var IsMobile = filterContext.Controller.ViewBag.IsMobile;
var view = filterContext.ActionDescriptor.ActionName;
if( result == null ) return;
string viewName;
string masterName;
bool hasLayout = filterContext.Controller.ViewBag.HasLayout ?? true;
if( IsMobile )
{
viewName = view + ".Mobile";
masterName = hasLayout ? "_Layout.Mobile" : null;
//Check if new view exists
var viewResult = ViewEngines.Engines.FindView( filterContext.Controller.ControllerContext, viewName, null );
if( viewResult.View == null )
{
viewName = view;
}
}
else
{
viewName = view;
masterName = hasLayout ? "_Layout" : null;
}
result.ViewName = viewName;
result.MasterName = masterName;
}
如果有人有更好的选择,请分享,这个解决方法看起来不错,但感觉有点不对。
好吧,要动态更改视图名称,您也可以使用它,这很简单
public void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.HttpContext.Request.IsLocal)
{
filterContext.Result = new ViewResult { ViewName = "Index" };
}
}
这对我有用:)
我有一个项目,我想向桌面和移动用户显示不同的视图,主要是为了获得更好的体验和速度。现在我正在使用 51degrees 来告诉我请求是来自移动用户还是桌面用户,然后在我的 Action Filter 中我将更改视图名称从 "Index" 到 "Index.Mobile",问题是我在视图中遇到了一些问题,我根本不想使用布局。
这是我的方法:
public override void OnActionExecuted( ActionExecutedContext filterContext )
{
var result = filterContext.Result as ViewResult;
var view = filterContext.ActionDescriptor.ActionName;
//IsMobile is filled on my OnActionExecuting method
var IsMobile = filterContext.Controller.ViewBag.IsMobile;
if( result == null ) return;
string viewName;
string masterName;
if( IsMobile )
{
viewName = view + ".Mobile";
masterName = "_Layout.Mobile";
//Check if view exists
var viewResult = ViewEngines.Engines.FindView( filterContext.Controller.ControllerContext, viewName, null );
if( viewResult.View == null )
{
viewName = view;
}
}
else
{
viewName = view;
masterName = "_Layout";
}
result.ViewName = viewName;
result.MasterName = masterName;
}
发生的事情是,我在这里为 MasterName 或 Layout 和两个特定的 Controllers 我需要将它设置为 null 但它仍然获取我之前设置的 Layout。
我需要的是,此方法将设置视图和布局名称,如果需要,我将在加载的视图中将布局设置为 null。
可以吗?
编辑
我尝试实现另一种方法,Link,但我找不到更改布局视图的方法,只能更改操作。
您可以像 "Areas/Mobile" 一样在您的项目中创建一个文件夹,并将您的视图、控制器甚至模型(移动视图模型)保存在其中。您只需创建一个路由规则,将来自移动设备的请求传递到 "Area/Mobile" 内的控制器。管理和构建网站的移动版本会容易得多。
经过一些调试后,我发现在 View
中设置值不起作用,因为 ViewEngine
会忽略这个新值并保持在 OnActionExecuted
方法中设置的值.
我设法使用相同的方法解决了我的问题,但添加了一个 ViewBag 来告诉我这个特定视图是否需要布局。由于 OnActionExecuted
将在 Controller
之后和 View
之前执行,因此可以在 Controller
处将值设置为 true/false,然后在 OnActionExecuted
.
这是工作示例:
public override void OnActionExecuted( ActionExecutedContext filterContext )
{
var result = filterContext.Result as ViewResult;
var IsMobile = filterContext.Controller.ViewBag.IsMobile;
var view = filterContext.ActionDescriptor.ActionName;
if( result == null ) return;
string viewName;
string masterName;
bool hasLayout = filterContext.Controller.ViewBag.HasLayout ?? true;
if( IsMobile )
{
viewName = view + ".Mobile";
masterName = hasLayout ? "_Layout.Mobile" : null;
//Check if new view exists
var viewResult = ViewEngines.Engines.FindView( filterContext.Controller.ControllerContext, viewName, null );
if( viewResult.View == null )
{
viewName = view;
}
}
else
{
viewName = view;
masterName = hasLayout ? "_Layout" : null;
}
result.ViewName = viewName;
result.MasterName = masterName;
}
如果有人有更好的选择,请分享,这个解决方法看起来不错,但感觉有点不对。
好吧,要动态更改视图名称,您也可以使用它,这很简单
public void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.HttpContext.Request.IsLocal)
{
filterContext.Result = new ViewResult { ViewName = "Index" };
}
}
这对我有用:)