MVC4 移动友好型 Web 应用程序






4.92/5 (35投票s)
为您的 ASP.NET MVC4 Web 应用程序启用移动功能
引言
几年前,对于许多开发人员来说,移动网站更多的是一种事后考虑,除非您参与开发专门针对移动设备的应用。令我惊讶的是,我在维基百科上读到,苹果直到 2010 年 3 月才开始接受 iPad 的预订。此后,我们看到了多么不同的格局。桌面、平板电脑和移动设备支持现在是任何需要广泛覆盖的网站的主要设计目标,而且这一趋势只会不断增加。
本文将演示 MVC4 如何几乎开箱即用地允许我们交付满足特定移动设备需求的视图,并尽可能共享代码库,从而创建移动友好型 Web 应用程序。
示例应用
本文的示例 Web 应用程序使用了 MVC 4,即微软最新的 Web 开发平台和 Visual Studio 2012。
本文将通过一些相当简单的步骤来为“Internet 应用程序”模板启用移动功能。通过运行应用程序,您可以发送请求以获取针对桌面、iPad 和 iPhone 的主页,这可以通过使用不同的设备来查看应用程序,或通过发送不同的用户代理字符串(如本文所述)来实现。该代码支持桌面、iPad 和 iPhone 作为支持移动设备的示例。
背景
设计移动网站有几种流行的方法,包括专用网站和响应式设计,而在 MVC4 中,则有“移动网站”模板。
移动设备专用网站和桌面设备专用网站。这种模式的一个问题是需要维护两个(甚至三个)不同的网站。
响应式设计,即网站使用适应屏幕尺寸和可用屏幕空间的样式表进行设计。在决定响应式设计模型时,需要选择是先从移动网站开始然后进行渐进增强,还是从桌面设计开始然后进行渐进降级,每种方法都有其自身的设计挑战。此外,还需要考虑移动设备通常带宽较低且可见内容较少,这可能经常导致通过有限的下载流量下载不满意的页面。
MVC4 移动网站模板:当我第一次安装 MVC4 的预览版时,就被新的“移动”模板所吸引。我印象深刻,因为它内置了 JQuery 和 JQuery mobile,并且性能相当不错。但很快就发现,这完全是一个面向移动设备的网站,不适合桌面。
考虑布局
在为移动平台设计时,可用空间方面存在一些明显的差异。这通常导致移动设备采用单列布局,桌面设备采用多列布局,平板电脑则采用介于两者之间的布局。当您开始设计移动友好型网站时,很快就会发现我们正在处理小型、中型和大型布局。
创建 Web 应用程序
选择“Internet 应用程序”模板会给我们一个主要针对桌面优化的网站。我们将从这里开始创建我们的移动友好型网站,如下所示。
在构建并运行此样板网站后,下面可以看到桌面和移动设备的结果。
调整浏览器窗口大小后,页面会根据响应式容器重新排列。
之所以能实现这一点,是因为布局文件 _Layout.cshtml 中有以下代码片段。
<meta name="viewport" content="width=device-width" />
大多数手机上的基于 Webkit 的浏览器如果存在此标记,会自动尝试重新排列页面。尽管工作量不大,但效果相当令人印象深刻。不过,要实现真正的移动体验,还有一段路要走。
检测移动设备
是时候让我们的网站能够检测到来自不同移动设备的请求了。我们将通过检查用户代理字符串并根据此理解做出决策来实现。
我们将向 Global.asax.cs 文件添加一个新方法,该方法将在 Application_Start()
方法中被调用,并将其命名为 EvaluateDisplayMode
。
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
/* Boilerplate code above... */
EvaluateDisplayMode(); //Evaluate incoming request and update Display Mode table
}
EvaluateDisplayMode() 方法本身。
/// <summary>
/// Evaluates incoming request and determines and adds an entry into the Display mode table
/// </summary>
private static void EvaluateDisplayMode()
{
DisplayModeProvider.Instance.Modes.Insert(0,
new DefaultDisplayMode("Phone")
{ //...modify file (view that is served)
//Query condition
ContextCondition = (ctx => (
//look at user agent
(ctx.GetOverriddenUserAgent() != null) &&
(//...either iPhone or iPad
(ctx.GetOverriddenUserAgent().IndexOf("iPhone", StringComparison.OrdinalIgnoreCase) >= 0) ||
(ctx.GetOverriddenUserAgent().IndexOf("iPod", StringComparison.OrdinalIgnoreCase) >= 0)
)
))
});
DisplayModeProvider.Instance.Modes.Insert(0,
new DefaultDisplayMode("Tablet")
{
ContextCondition = (ctx => (
(ctx.GetOverriddenUserAgent() != null) &&
(
(ctx.GetOverriddenUserAgent().IndexOf("iPad", StringComparison.OrdinalIgnoreCase) >= 0) ||
(ctx.GetOverriddenUserAgent().IndexOf("Playbook", StringComparison.OrdinalIgnoreCase) >= 0)
)
))
});
}
该代码会评估用户代理字符串,如果找到与“iPad”或“Playbook”匹配的项,则会向 DisplayModes 表中添加一个“Tablet”条目。它还会检查 iPhone 或 iPod,并分别设置“Phone”DisplayMode。对于桌面设备,目前这是默认设置,因此无需再添加其他内容。您可以看到添加其他设备是多么容易,并且可以进一步重构代码。
注意* 显然还有其他框架专门用于识别请求以确定客户端设备,但此方法适用于我遇到的所有常见设备类型,以实现大众市场覆盖。您在这里有一个可以执行必要检查的管道点。
提供特定于设备的视图
由于 Display Modes 表已根据上述检测进行了更新,MVC 引擎将修改它将要提供的视图,以匹配移动设备请求(如果可用)。
下表显示了基于用户代理可用的视图示例。
Device | 客户端请求 | 视图 |
PC | /YourMVCApp/Home (控制器) | Index.cshtml |
iPad | /YourMVCApp/Home (控制器) | Index.Tablet.cshtml |
iPhone | /YourMVCApp/Home (控制器) | Index.Phone.cshtml |
这是一个巨大的进步,我们现在可以轻松地为不同设备创建唯一的视图了!
下面是 Visual Studio 2012 的解决方案资源管理器屏幕截图,显示了我们为支持新设备而创建的视图。
测试到目前为止的工作...
虽然没有什么能替代在硬件移动设备上进行测试,但在初始开发过程中,Safari 可以轻松地发送带有特定用户代理的请求到服务器。您还可以使用 Safari 添加自己的用户代理字符串,用于 Safari 默认未提供的设备。
您可以通过菜单 -> 开发 -> 用户代理设置新的用户代理字符串。下面的 Safari 屏幕截图显示了为请求设置用户代理字符串。
注意**
如果看不到“开发”菜单,请通过设置 -> 偏好设置 -> 高级并勾选“在菜单栏中显示开发菜单”来启用它。
看到这一点正在起作用是相当令人欣慰的,而且在这一点上,我们已经对可以呈现/返回给客户端的视图有了一些合理的控制。
增强我们的移动视图
尽管我们已经取得了很大进展,但我们的移动视图仍然不尽如人意。此时,我们也可以直接修改移动视图,在某些情况下这是合适的。我们将更进一步,为每种设备类型创建布局页面,如下所示。
现在布局页面已就位,我们需要更新我们的视图以使用它们。
@{
ViewBag.Title = "Tablet";
Layout = "../Shared/_Layout.Tablet.cshtml";
}
您可以看到我们还设置了标题,以便在浏览器标题栏中轻松识别当前视图。
添加移动脚本
微软已全面拥抱 jQuery 和 jQuery Mobile,这非常好。由于我们从“Internet 应用程序”模板开始,因此不包含 jQuery Mobile,因此我们将通过“程序包管理器”来包含它。右键单击解决方案并选择“程序包管理器”(如果您愿意,也可以通过命令行进行)。
下面的屏幕截图显示了我们在输入并选择 JQuery Mobile 后的程序包管理器。
添加此项后,我们将在“脚本”和“内容”下看到相应的脚本和样式表,如下面的解决方案资源管理器所示。
启用移动脚本
尽管我们现在拥有了移动脚本,但仍需要在移动视图中引用它们。MVC4 Bundles 的发布现在似乎对脚本和样式表效果很好。我们将通过在“App_Start”解决方案文件夹中的“BundleConfig.cs”文件中找到的“RegisterBundles”方法中的以下条目来将我们的新移动脚本和样式表添加到捆绑表中。
bundles.Add(new StyleBundle("~/Content/mobilecss").Include("~/Content/jquery.mobile*"));
bundles.Add(new ScriptBundle("~/bundles/jquerymobile").Include("~/Scripts/jquery.mobile*"));
现在脚本和样式表已添加到捆绑表中,我们可以在视图中使用它们,方法是在 _Layout.Mobile.cshtml 的 head 部分添加一个渲染调用,如下所示。
<head>
@Styles.Render("~/Content/mobileCss", "~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
使用 jQuery mobile 为移动视图设置样式
尽管使用 JQuery Mobile 为移动视图设置样式超出了本文的范围,但我还是继续添加了一些内容,以使我们的视图看起来有所不同。
遵循约定(略微重构)
由于我们在 Global.asax 的“Application_Start()”中添加了代码,因此将当前的“EvaluateDisplayMode()”提取到其自己的设备配置中是有意义的,这样随着其增长,它就不会使启动视图臃肿,并且更易于维护。其他配置类位于“App_Start”解决方案文件夹中,我们将使用相同的约定并创建一个静态的“DeviceConfig”类,如下所示。
这样,我们在“Application_Start()”中的设备评估可以简化为一行,如下所示。
DeviceConfig.EvaluateDisplayMode(); //Evaluate incoming request and update Display Mode table
这样就符合了其他配置类的约定。(也许我们会在下一版 MVC 中看到类似的内容)
新的 DeviceConfig 类如下所示。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.WebPages; namespace MvcDesktop { /// <summary> /// Device specific startup configuration /// </summary> public static class DeviceConfig { const string DeviceTypePhone = "Phone"; const string DeviceTypeTablet = "Tablet"; /// <summary> /// Evaluates incoming request and determines device. /// Adds an entry into the Display mode table /// </summary> public static void EvaluateDisplayMode() { //... refactored code here, similar to before... } } }
限制
- 我们没有添加任何 Web 应用程序标记或媒体查询来增强我们渲染视图时的决策。
- 在实际项目中,我们将利用更多的部分视图和共享视图来确保内容可以集中管理。
- 示例项目仅影响三个设备的“主页”。
最终结果
下面是请求我们主页的移动、平板电脑或桌面设备的视图。
移动视图
平板电脑视图
桌面视图
结论
为不同设备场景分离视图无疑是一种模式,它与我这样的 MVC 开发人员非常契合,如果处理得当,可以为移动设备提供非常轻量级的视图。
如果您已经具备 MVC 技能,并且大部分时间都在为微软平台开发,那么 MVC 内置的对移动设备的支持是我们迄今为止最好的。当然,您也可以在 MVC3 中实现相同的功能,但需要做更多的工作。
我们研究的领域
1. 为所有设备开发单个站点
2. 评估发出请求的客户端设备
3. 根据设备提供不同的视图
4. 能够利用 jQuery、jQuery Mobile 和脚本管理以及布局。
希望您喜欢这篇文章!
修订历史
2012 年 9 月 10 日 - 新源代码删除了不必要的向导生成的数据库并证明代码可以构建...
2012 年 9 月 11 日 - 添加了针对 codeproject 的本地图像,方便下载。
2012 年 9 月 13 日 - 重构,添加了 DeviceConfig 约定类,新的构建。