代码改变世界

Asp.NET MVC Widget开发 - Mobile支持

2011-03-02 15:49  Creative dream  阅读(2491)  评论(4编辑  收藏  举报

在Asp.NET开发博客类系统,我们经常都会用到Widget,像在线好友、最近访问好友、最新留言等,关于Asp.NET MVC与Asp.NET视图的差异,这里不再说了,大家可去查一下,接下来我以“我的好友”列表来要介绍在Asp.NET MVC实现这一功能以及结构设计。

  • 开发工具:VS 2010 EN
  • 开发语言:Visual C#
  • ASP.NET MVC 3
  • Windows Phone 7 Emulator
  1. Asp.NET MVC Widget - 设计
  2. Asp.NET MVC Widget - Controller控制器
  3. Asp.NET MVC Widget - ViewEngine
  4. Asp.NET MVC Widget - Mobile支持
  5. Asp.NET MVC Widget - Html.Widget扩展方法

前3篇中已经讲了Widget实现方法,并用“我的好友”实例做了演示,接下来将要支持Mobile了。

1. 先来贴下"widgets"的目录结构

/Mobile                                                存放Mobile支持的页面文件

/Mobile/Widget.cshtml                          通用的Mobile显示页面,即任何手机客户端未找到情况下,调用此显示

/Mobile/iPhone/                                    存放针对iPhone类型文件

/Mobile/iPhone/Widget.cshtml                iPhone主页面文件

/Mobile/WindowsMobile                         存放针对WindowsMobile类型文件

/Mobile/WindowsMobile/Widget.cshtml    WindowsMobile主页面文件

2. 修改视图引擎以支持Mobile

打开我们之前添加的WidgetViewEngine.cs,添加对Mobile支持

  • 添加public StringDictionary Devices { get; set; },存储设备对应的目录
  • 重载FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Collections.Specialized;

namespace Widgets
{
public class WidgetViewEngine : BuildManagerViewEngine
{
internal static readonly string ViewStartFileName = "_ViewStart";

public StringDictionary Devices { get; set; }

public WidgetViewEngine()
:
this(null)
{
}

public WidgetViewEngine(IViewPageActivator viewPageActivator)
:
base(viewPageActivator)
{
AreaViewLocationFormats
= new[] {
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml"
};
AreaMasterLocationFormats
= new[] {
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml"
};
AreaPartialViewLocationFormats
= new[] {
"~/Areas/{2}/Views/{1}/{0}.cshtml",
"~/Areas/{2}/Views/Shared/{0}.cshtml"
};

ViewLocationFormats
= new[] {
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml"

};
MasterLocationFormats
= new[] {
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml"
};
PartialViewLocationFormats
= new[] {
"~/{1}s/{0}/Widget.cshtml",
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml"
};

// 初使化Mobile对应文件目录
Devices = new StringDictionary
{
{
"IEMobile","WindowsMobile"},
{
"Pocket IE","WindowsMobile"},
{
"AppleMAC-Safari","iPhone"}
};

FileExtensions
= new[] {
"cshtml"
};
}

protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
return new RazorView(controllerContext, partialPath,
layoutPath:
null, runViewStartPages: false, viewStartFileExtensions: FileExtensions, viewPageActivator: ViewPageActivator);
}

protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
var view
= new RazorView(controllerContext, viewPath,
layoutPath: masterPath, runViewStartPages:
true, viewStartFileExtensions: FileExtensions, viewPageActivator: ViewPageActivator);
return view;
}

public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
ViewEngineResult result
= null;
var request
= controllerContext.HttpContext.Request;
var isMobile
= request.Browser.IsMobileDevice;

if (isMobile && controllerContext.IsChildAction)
{
var device
= request.Browser.Browser;

result
= base.FindPartialView(
controllerContext,
string.Format("{1}/Mobile/{0}", Devices[device], partialViewName),
useCache);
if ((result == null || result.View == null) && isMobile)
result
= base.FindPartialView(
controllerContext,
string.Format("{0}/Mobile", partialViewName),
useCache);
}

if (result == null || result.View == null)
result
= base.FindPartialView(controllerContext, partialViewName, useCache);

return result;
}

public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
ViewEngineResult result
= null;
var request
= controllerContext.HttpContext.Request;
var isMobile
= request.Browser.IsMobileDevice;

if (isMobile)
{
var device
= request.Browser.Browser;

result
= base.FindView(
controllerContext,
string.Format("Mobile/{0}/{1}", Devices[device], viewName),
masterName,
useCache);
if ((result == null || result.View == null) && isMobile)
result
= base.FindView(
controllerContext,
string.Format("Mobile/{0}", viewName),
masterName,
useCache);
}

if (result == null || result.View == null)
result
= base.FindView(controllerContext, viewName, masterName, useCache);

return result;
}
}
}

3. 更改显示页面

/Mobile/Widget.cshtml

@model IEnumerable<Widgets.Models.Friend>
@{
Layout = "~/widgets/_Layout.cshtml";
ViewBag.Title = "My friends";
}
<div class="newsletter">
<ul>
@foreach (var item in Model)
{
<li>@item.Name</li>
}
</ul>
</div>

/Mobile/iPhone/Widget.cshtml

@model IEnumerable<Widgets.Models.Friend>
@{
Layout = "~/widgets/_Layout.cshtml";
ViewBag.Title = "My friends";
}
<div class="newsletter">
<ul>
@foreach (var item in Model)
{
<li>@item.Name</li>
}
</ul>
<span>来自iPhone手机客户端</span>
</div>

/Mobile/WindowsMobile/Widget.cshtml

@model IEnumerable<Widgets.Models.Friend>
@{
Layout = "~/widgets/_Layout.cshtml";
ViewBag.Title = "My friends";
}
<div class="newsletter">
<ul>
@foreach (var item in Model)
{
<li>@item.Name</li>
}
</ul>
<span>来自windows mobile手机客户端</span>
</div>

4. 使用Windows Phone 7 Emulator打开页面