探索 ASP.NET MVC4 Developer Preview
在 Visual Studio 11 Developer Preview 里,并没有集成 ASP.NET MVC4 Developer Preview,事实上,它根本没有带任何版本的 ASP.NET MVC 框架。不过不要紧,VS11 提供了一个 Web Installer 的链接,通过它就可以下载到 ASP.NET MVC4 的开发者预览版。如果你的电脑上网不便,或者连接官方的服务器太慢,也可以从这里下载离线安装程序:http://download.csdn.net/detail/caozhy/3619212。注意,只有Visual Studio 2010 SP1和
Visual Studio 11 Developer Preview支持MVC4 Preview。安装对应的安装包即可。
安装之后,我初步体验了下这个新框架的一些新特性,分享给大家。
这张图表明 MVC4 的2个新特性,一个是支持移动应用,另一个是支持 HTML5,而 HTML5 的支持,来自基于 ASP.NET 4.5 的新特性。
在新建一个带用户帐户支持的新程序,可以看到如下运行效果:
ASP.NET MVC 4默认的模板有了更新,改变了自MVC1以来的面孔。而且登录、注册也换成了jQueryUI的AJAX的风格。
然而不止于此,默认的视图模板也增加了对Ajax风格的支持:
虽然在实际开发中,这些脚手架代码很少被实际使用。也许你也这么认为,不错,微软也想到了,现在 MVC4 新增了一个叫 Recipe 的东西。
看下图:
那么什么是 Recipe 呢?按照微软的解释,它是一种智能的代码生成插件,当你需要一个功能的时候,一个 Recipe 组件就可以通过 API 和 Visual Studio 交互,并且正确插入和更新代码,使得程序支持这个功能,插入的代码可能分散在程序的多个地方。
而且 Recipe 是可以扩展的,因此和那些一次性的脚手架相比,这个就实用多了。用过 VC++ 6 的人可能感觉它和 Component Gallery 有点像,呵呵。
MVC4 还改进了异步控制器调用,其实这个特性是 MVC2 新增的。但是因为缺少异步语法的支持,以前写一个异步 Action 需要2个方法才能实现。现在借助 async/await,只需要一个方法就行了。
我还体验了下用 MVC4 开发的过程。我们的目标是设计一个简易的 RSS 阅读器,它从我们预先选定的几个网站获取数据,并且按照时间排序后呈现出来,当数据很多的时候,我们只显示前100条。
为此,首先创建模型:
public class NewsItem{ public DateTime PostDate { get; set; } public string Title { get; set; } public string SourceURL { get; set; } public string Content { get; set; }}
public class NewsModels{ public static async Task<List<NewsItem>> GetNews(string RssURI) { var x = XElement.Load(RssURI); DateTime _out = default(DateTime); return x.Element("channel").Elements("item") .Select(y => new NewsItem() { Content = (y.Element("description") ?? new XElement("description")).Value, PostDate = DateTime.TryParse((y.Element("pubDate") ?? new XElement("pubDate", default (DateTime))).Value, out _out) ? DateTime.Parse((y.Element("pubDate") ?? new XElement("pubDate", default (DateTime))).Value) : default(DateTime), SourceURL = (y.Element("link") ?? new XElement("link")).Value, Title = (y.Element("title") ?? new XElement("title")).Value }).ToList(); }}
@model IEnumerable<MvcApplication1.Models.NewsItem>@{ ViewBag.Title = "News";}用时 @ViewBag.TimeCost@foreach (var item in Model) { <h2>@item.Title</h2> <p>@item.PostDate</p> <p><a href="@item.SourceURL" target="_blank">@item.SourceURL</a></p> <p>@MvcHtmlString.Create(item.Content)</p> <p />}
public class HomeController : AsyncController
public async Task<ActionResult> NewsAsyncAsync(){ DateTime dt1 = DateTime.Now; var rss = new string[] { "http://articles.csdn.net/api/rss.php?tid=1008", "http://aspnet.codeplex.com/project/feeds/rss", "http://solidot.org.feedsportal.com/c/33236/f/556826/index.rss", "http://www.codeguru.com/icom_includes/feeds/codeguru/rss-csharp.xml", "http://feed.google.org.cn/" }; List<List<NewsItem>> list = new List<List<NewsItem>>(); foreach (var item in rss) { List<NewsItem> news = await (NewsModels.GetNews(item)); list.Add(news); } var model = list.SelectMany(x => x) .ToList() .OrderByDescending(x => x.PostDate) .Take(100); DateTime dt2 = DateTime.Now; ViewBag.TimeCost = new TimeSpan(dt2.Ticks - dt1.Ticks).ToString(); return View("News", model);}
[AsyncTimeout(2500)]
public ActionResult NewsSync() { DateTime dt1 = DateTime.Now; var rss = new string[] { "http://articles.csdn.net/api/rss.php?tid=1008", "http://aspnet.codeplex.com/project/feeds/rss", "http://solidot.org.feedsportal.com/c/33236/f/556826/index.rss", "http://www.codeguru.com/icom_includes/feeds/codeguru/rss-csharp.xml", "http://feed.google.org.cn/" }; var model = rss.SelectMany(x => NewsModels.GetNews(x).Result) .ToList() .OrderByDescending(x => x.PostDate) .Take(100); DateTime dt2 = DateTime.Now; ViewBag.TimeCost = new TimeSpan(dt2.Ticks - dt1.Ticks).ToString(); return View("News", model); }