1. 程式人生 > >自定義ActionResult實現Rss輸出 (基於ASP.NET MVC Preview 3)

自定義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的程式碼如下:

publicstaticstring ToXmlString(this RssItem item)
        
{
            StringBuilder sb 
=new StringBuilder();
            sb.AppendLine(
"<item>");
            sb.Append(ToXmlItem
<RssItem>(item));
            sb.AppendLine(
"</item>");
            
return sb.ToString();
        }


        
publicstaticstring ToXmlString(this RssImage image)
        
{
            StringBuilder sb 
=new StringBuilder();
            sb.AppendLine(
"<image>");
            sb.Append(ToXmlItem
<RssImage>(image));
            sb.AppendLine(
"</image>");
            
return sb.ToString();
        }


        
publicstaticstring ToXmlString(this RssEntity rss)
        
{
            StringBuilder sb 
=new StringBuilder();
            sb.AppendLine(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            sb.AppendLine(
"<rss version=\"2.0\">");
            sb.AppendLine(
"<channel>");
            sb.AppendLine(ToXmlItem
<RssEntity>(rss));
            sb.AppendLine(
"</channel>");
            sb.AppendLine(
"</rss>");
            
return sb.ToString();
        }


        
publicstatic RssEntity ToDefaultRss(this IList<ArticleEntity> articleList)
        
{
            RssEntity rss 
=new RssEntity()
            
{
                Title 
="ArticleResult Demo Rss.",
                Copyright 
="Copyright 2008 Leven",
                Generator 
="ArticleResult Demo",
                Link 
="http://blog.leven.com.cn/",
                Description 
="ArticleResult Demo Rss - a demo of asp.net mvc priview3.",
                WebMaster 
="leven",
                Image 
=new RssImage()
                
{
                    Link 
="http://blog.leven.com.cn/images/logo.jpg",
                    Title 
="ArticleResult Demo",
                    Url 
="http://blog.leven.com.cn/",
                    Description 
="ArticleResult Demo Image."
                }

            }
;
            
foreach (ArticleEntity article in articleList)
            
{
                rss.Items.Add(
new RssItem()
                
{
                    Title 
= article.Title,
                    Author 
= article.PostUser,
                    Category 
="Default Category",
                    Link 
="http://blog.leven.com.cn/",
                    Guid 
="http://blog.leven.com.cn/",
                    PubData 
= article.PostTime,
                    Description 
= article.Content
                }
);
            }

            
return rss;
        }


        
privatestaticstring ToXmlItem<DType>(DType data)
            
where DType : class
        
{
            StringBuilder sb 
=new StringBuilder();
            Type type 
= data.GetType();
            PropertyInfo[] pis 
= type.GetProperties();
            
foreach (PropertyInfo p in pis)
            
{
                
if (p.PropertyType ==typeof(DateTime))
                
{
                    sb.AppendFormat(
"<{0}>{1:R}</{0}>\r\n", p.Name.ToLower(), p.GetValue(data, null));
                }

                
elseif (p.PropertyType ==typeof(RssImage))
                
{
                    sb.AppendLine(((RssImage)p.GetValue(data, 
null)).ToXmlString());
                }

                
elseif (p.PropertyType ==typeof(IList<RssItem>))
                
{
                    IList
<RssItem> rssItems = p.GetValue(data, nullas IList<RssItem>;
                    
foreach (RssItem item in rssItems)
                    
{
                        sb.AppendLine(item.ToXmlString());
                    }

                }

                
else
                
{
                    sb.AppendFormat(
"<{0}><![CDATA[{1}]]></{0}>\r\n", p.Name.ToLower(), p.GetValue(data, null));
                }

            }

            
return sb.ToString();
        }

 

通過這些方法,我們可以方便生成rss資料.

再看RssResult.該類繼承自ActionResult,實現了ExecuteResult方法.該方法為: ExecuteResult(ControllerContext context)我們可以在其中直接將rss資料輸出.這便是ActionResult的魅力了,我們通過RssEntity+RssAction完全對實體-xml輸出進行了封裝,使得程式可以非常方便的實現rss輸出.現給出RssResult的程式碼:

public Encoding ContentEncoding getset; }

        
public RssEntity Data getset; }