Asp.Net MVC实践 - 自定义ActionResult实现Rss输出 (基于ASP.NET MVC Preview 3)

前两天才做了一个Asp.Net MVC Preview2的实践,没想到这就升级到了Asp.Net Preview3了,Preview3确实比2好上不少,特别有两个地方值得注意,一是Route新增了MapRoute方法,可以更方便添加Url路由规则,二是修改了View的部分,使得Action统一返回ActionResult,更方便我们定制View.
今天我要实践的就是使用Priview3提供的新特性,通过自定义ActionResult实现Rss输出.
Rssweb系统中相当常见,主要用于快速浏览站点更新的文章等内容,web2.0的主要特性之一,以前我们是如何来实现Rss输入的呢?aspx中输出?自定义HttpHandle?自然是可以,但是到了MVC框架中,我们可以选中更好的方式,自定义ActionResult.
根据官方资料,每个Action都要返回一个ActionResult来执行View,ActionResult是一个抽象类,我们现在必须的就是自定义一个RssAction.

首先根据需要建立一个ArticleResultDemoAsp.Net Web Application.然后根据mvc约定建立相关文件夹和文件,为了实现rss输出,我添加以下文件,如图:



 

Models,ArticleEntityArticle对应实体,ArticleModel有一个测试方法供返回一组ArticleEntity,EntityExtensions是对Entity提供一组扩展方法,进行比如生成rss等功能,RssEntity是提供rss数据实体.Controllers,RssResult就是我们扩展的ActionResult,DemoController是扩展的Controller,提供快捷的Rss输出方法,这是一个抽象类,ArticleController是当前Demo的主控制类.
关于这几个Entity类要说明下,RssEntity文件中包含RssEntity,RssImage,RssItem3个类,对整个rss数据进行了封装.EntityExtersions类提供一组扩展方法来实现实体-rss xml数据的转换,具体EntityExtersions的代码如下:
C#代码
  1. public static string ToXmlString(this RssItem item)   
  2.         {   
  3.             StringBuilder sb = new StringBuilder();   
  4.             sb.AppendLine("<item>");   
  1.  
  2.             sb.Append(ToXmlItem<RssItem>(item));   
  3.             sb.AppendLine("</item>");   
  4.             return sb.ToString();   
  5.         }   
  6.   
  7.         public static string ToXmlString(this RssImage image)   
  8.         {   
  9.             StringBuilder sb = new StringBuilder();   
  10.             sb.AppendLine("<image>");   
  11.             sb.Append(ToXmlItem<RssImage>(image));   
  12.             sb.AppendLine("</image>");   
  13.             return sb.ToString();   
  14.         }   
  15.   
  16.         public static string ToXmlString(this RssEntity rss)   
  17.         {   
  18.             StringBuilder sb = new StringBuilder();   
  19.             sb.AppendLine("<?xml version="1.0" encoding="UTF-8"?>");   
  20.             sb.AppendLine("<rss version="2.0">");   
  21.             sb.AppendLine("<channel>");   
  22.             sb.AppendLine(ToXmlItem<RssEntity>(rss));   
  23.             sb.AppendLine("</channel>");   
  24.             sb.AppendLine("</rss>");   
  25.             return sb.ToString();   
  26.         }   
  27.   
  28.         public static RssEntity ToDefaultRss(this IList<ArticleEntity> articleList)   
  29.         {   
  30.             RssEntity rss = new RssEntity()   
  31.             {   
  32.                 Title = "ArticleResult Demo Rss.",   
  33.                 Copyright = "Copyright 2008 Leven",   
  34.                 Generator = "ArticleResult Demo",   
  35.                 Link = "http://blog.leven.com.cn/",   
  36.                 Description = "ArticleResult Demo Rss - a demo of asp.net mvc priview3.",   
  37.                 WebMaster = "leven",   
  38.                 Image = new RssImage()   
  39.                 {   
  40.                     Link = "http://blog.leven.com.cn/images/logo.jpg",   
  41.                     Title = "ArticleResult Demo",   
  42.                     Url = "http://blog.leven.com.cn/",   
  43.                     Description = "ArticleResult Demo Image."  
  44.                 }   
  45.             };   
  46.             foreach (ArticleEntity article in articleList)   
  47.             {   
  48.                 rss.Items.Add(new RssItem()   
  49.                 {   
  50.                     Title = article.Title,   
  51.                     Author = article.PostUser,   
  52.                     Category = "Default Category",   
  53.                     Link = "http://blog.leven.com.cn/",   
  54.                     Guid = "http://blog.leven.com.cn/",   
  55.                     PubData = article.PostTime,   
  56.                     Description = article.Content   
  57.                 });   
  58.             }   
  59.             return rss;   
  60.         }   
  61.   
  62.         private static string ToXmlItem<DType>(DType data)   
  63.             where DType : class  
  64.         {   
  65.             StringBuilder sb = new StringBuilder();   
  66.             Type type = data.GetType();   
  67.             PropertyInfo[] pis = type.GetProperties();   
  68.             foreach (PropertyInfo p in pis)   
  69.             {   
  70.                 if (p.PropertyType == typeof(DateTime))   
  71.                 {   
  72.                     sb.AppendFormat("<{0}>{1:R}</{0}> ", p.Name.ToLower(), p.GetValue(data, null));   
  73.                 }   
  74.                 else if (p.PropertyType == typeof(RssImage))   
  75.                 {   
  76.                     sb.AppendLine(((RssImage)p.GetValue(data, null)).ToXmlString());   
  77.                 }   
  78.                 else if (p.PropertyType == typeof(IList<RssItem>))   
  79.                 {   
  80.                     IList<RssItem> rssItems = p.GetValue(data, nullas IList<RssItem>;   
  81.                     foreach (RssItem item in rssItems)   
  82.                     {   
  83.                         sb.AppendLine(item.ToXmlString());   
  84.                     }   
  85.                 }   
  86.                 else  
  87.                 {   
  88.                     sb.AppendFormat("<{0}><![CDATA[{1}]]></{0}> ", p.Name.ToLower(), p.GetValue(data, null));   
  89.                 }   
  90.             }   
  91.             return sb.ToString();   
  92.         }   

 

通过这些方法,我们可以方便生成rss数据.
再看RssResult.该类继承自ActionResult,实现了ExecuteResult方法.该方法为: ExecuteResult(ControllerContext context)我们可以在其中直接将rss数据输出.这便是ActionResult的魅力了,我们通过RssEntity+RssAction完全对实体-xml输出进行了封装,使得程序可以非常方便的实现rss输出.现给出RssResult的代码:
C#代码
  1. public Encoding ContentEncoding { getset; }   
  2.   
  3.         public RssEntity Data { getset; }   
  4.   
  5.         public RssResult()   
  6.         {   
  7.         }   
  8.   
  9.         public RssResult(Encoding encode)   
  10.         {   
  11.             ContentEncoding = encode;   
  12.         }   
  13.   
  14.         public RssResult(RssEntity data, Encoding encode)   
  15.         {   
  16.             Data = data;   
  17.             ContentEncoding = encode;   
  18.         }   
  19.   
  20.         public override void ExecuteResult(ControllerContext context)   
  21.         {   
  22.             if (context == null)   
  23.             {   
  24.                 throw new ArgumentNullException("context");   
  25.             }   
  26.             HttpResponseBase response = context.HttpContext.Response;   
  27.             response.ContentType = "text/xml";   
  28.             if (ContentEncoding != null)   
  29.             {   
  30.                 response.ContentEncoding = ContentEncoding;   
  31.             }   
  32.             if (Data != null)   
  33.             {   
  34.                 response.Write(Data.ToXmlString());   
  35.             }   
  36.         }   
为了更方便使用这个RssResult,我们可以对Controller进行进一步的改写,这儿我参照了Json方法的方式实现了DemoController,代码如下:
C#代码
  1. public abstract class DemoController : Controller   
  2.     {   
  3.         [NonAction]   
  4.         public ActionResult Rss(RssEntity rss, Encoding encode)   
  5.         {   
  6.             RssResult result = new RssResult(rss, encode);   
  7.             return result;   
  8.         }   
  9.   
  10.         [NonAction]   
  11.         public ActionResult Rss(RssEntity rss)   
  12.         {   
  13.             RssResult result = new RssResult();   
  14.             result.Data = rss;   
  15.             return result;   
  16.         }   
  17. }   
由于这两个Rss方法并非Action,因此加上了[NonAction]Attubite.
现在我们再使用就非常方便了,ArticleController,实现一个Rss方法
C#代码
  1. public ActionResult Rss()   
  2.         {   
  3.             RssEntity rss = ArticleModel.GetList().ToDefaultRss();   
  4.             return Rss(rss);   
  5.         }   
一部直接输出了rss.最后修改web.config,添加route等完成之后,执行图如下:


说明一下,priview3的官方说明中,为了使得默认首页可用,可以添加一个default.aspx文件,然后在页面中加入一行
<% Response.Redirect("article/rss")%>
我看到有朋友质疑说这个语法错误了,没有加分号,其实这是.net默认语言的问题,如果你不修改.net的配置,默认aspx的语言是vb.net,因此这行是没有任何问题的.

最后给出该Demo的全部工程文件下载.


下载文件点击下载此文件

 

文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: .net  asp.net  mvc  rss 
评论: 0 | 引用: 0 | 查看次数: 578
发表评论
用户名:
密 码: 游客发言不需要密码.
验证码: 验证码
内 容:
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 500 字 | HTML代码允许 关闭 | 评论可修改 关闭