我正在尝试让我的 Action 针对不同的平台返回不同的视图,同时尊重路由配置。如果我创建自定义 ViewResult,我会覆盖 FindView 方法吗?如果是这样,我该如何修改自动找到的视图?
例如:HomeController.About 动作将在计算机上显示 View\Home\About.cshtml,在平板电脑上显示 View\Home\AboutTablet.cshtml,在手机上显示 View\Home\AboutMobile.cshtml
我正在尝试让我的 Action 针对不同的平台返回不同的视图,同时尊重路由配置。如果我创建自定义 ViewResult,我会覆盖 FindView 方法吗?如果是这样,我该如何修改自动找到的视图?
例如:HomeController.About 动作将在计算机上显示 View\Home\About.cshtml,在平板电脑上显示 View\Home\AboutTablet.cshtml,在手机上显示 View\Home\AboutMobile.cshtml
有一个 NuGet 适合您:MobileViewEngines。ScottHa 在一篇博文中介绍了它。它的规范与 ASP.NET MVC 4 兼容,您可以轻松摆脱它,因为此功能是内置的。
你可以像这样定义一个 Actionfilter:
public class SetDeviceDependantView : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
// Only works on ViewResults...
ViewResultBase viewResult = filterContext.Result as ViewResultBase;
if (viewResult != null)
{
if (filterContext == null)
throw new ArgumentNullException("context");
// Default the viewname to the action name
if (String.IsNullOrEmpty(viewResult.ViewName))
viewResult.ViewName = filterContext.RouteData.GetRequiredString("action");
// Add suffix according to device type
if (IsTablet(filterContext.HttpContext))
viewResult.ViewName += "Tablet";
else if (IsMobile(filterContext.HttpContext))
viewResult.ViewName += "Mobile";
}
base.OnResultExecuting(filterContext);
}
private static bool IsMobile(HttpContextBase httpContext)
{
return httpContext.Request.Browser.IsMobileDevice;
}
private static bool IsTablet(HttpContextBase httpContext)
{
// this requires the 51degrees "Device Data" package: http://51degrees.mobi/Products/DeviceData/PropertyDictionary.aspx
var isTablet = httpContext.Request.Browser["IsTablet"];
return isTablet != null && isTablet.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase);
}
}
然后您可以像这样注释所需的操作/控制器:
[SetDeviceDependantView]
public ActionResult About()
{
return View();
}
或者在 global.asax 中全局设置:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new SetDeviceDependantView());
}
请注意,我在这里依靠 51degrees 库来检测平板电脑,您可以考虑使用不同的技术。然而,这是一个不同的话题。
如果您想在 MVC4 之前执行此操作,请查看 Christopher Bennage 的这篇博文
http://dev.bennage.com/blog/2012/04/27/render-action/
我对 ContentTypeAwareResult 类特别感兴趣,它看起来可能就是您正在寻找的。
您必须创建自己的ViewEngine
(可能是从您正在使用的那个派生的)并覆盖FindView
and FindPartialView
。您可以提供备用方案(即,如果没有找到平板电脑,则使用通用视图)。
最麻烦的是定义区分不同“模式”的标准。
构建自定义 ViewEngine 是 MVC3 中满足此要求的首选方法。供您参考 - MVC4 开箱即用地支持此功能。
有关设备特定视图的更多信息,在 StackOverflow 上发布了类似的答案https://stackoverflow.com/a/1387555/125651