载入中,请稍候……

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

Admin 于 2008-08-26 04:15:08 发表转载

订阅: http://www.miniboke.com/Feed/Article_10.aspx
引用: http://www.miniboke.com/Trackback/dsLsmpKOjvCTrOiAVTjc.aspx (UTF-8)
Asp.Net MVC实践 (基于ASP.NET MVC Preview 2) < Asp.Net MVC实践 - 自定义ActionResult实现Rss输出 (基于ASP.NET MVC Preview 3) > Asp.Net MVC实践 - 探索UrlRouting并分析UrlHelper (基于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的代码如下:

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


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


        
public static string 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();
        }


        
public static 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;
        }


        
private static string 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));
                }

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

                
else if (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; }

        
public RssResult()
        
{
        }


        
public RssResult(Encoding encode)
        
{
            ContentEncoding 
= encode;
        }


        
public RssResult(RssEntity data, Encoding encode)
        
{
            Data 
= data;
            ContentEncoding 
= encode;
        }


        
public override void ExecuteResult(ControllerContext context)
        
{
            
if (context == null)
            
{
                
throw new ArgumentNullException("context");
            }

            HttpResponseBase response 
= context.HttpContext.Response;
            response.ContentType 
= "text/xml";
            
if (ContentEncoding != null)
            
{
                response.ContentEncoding 
= ContentEncoding;
            }

            
if (Data != null)
            
{
                response.Write(Data.ToXmlString());
            }

        }

 

为了更方便使用这个RssResult,我们可以对Controller进行进一步的改写,这儿我参照了Json方法的方式实现了DemoController,代码如下:

public abstract class DemoController : Controller
    
{
        [NonAction]
        
public ActionResult Rss(RssEntity rss, Encoding encode)
        
{
            RssResult result 
= new RssResult(rss, encode);
            
return result;
        }


        [NonAction]
        
public ActionResult Rss(RssEntity rss)
        
{
            RssResult result 
= new RssResult();
            result.Data 
= rss;
            
return result;
        }

}

 

由于这两个Rss方法并非Action,因此加上了[NonAction]Attubite.

现在我们再使用就非常方便了,ArticleController,实现一个Rss方法

public ActionResult Rss()
        
{
            RssEntity rss 
= ArticleModel.GetList().ToDefaultRss();
            
return Rss(rss);
        }

 

一部直接输出了rss.最后修改web.config,添加route等完成之后,执行图如下:

 

说明一下,priview3的官方说明中,为了使得默认首页可用,可以添加一个default.aspx文件,然后在页面中加入一行

<% Response.Redirect("article/rss")%>

我看到有朋友质疑说这个语法错误了,没有加分号,其实这是.net默认语言的问题,如果你不修改.net的配置,默认aspx的语言是vb.net,因此这行是没有任何问题的.

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

点击下载该工程文件 
个人Blog同步更新:http://blog.leven.com.cn/Article_28.aspx

Tag标签: asp.net,c#,mvc,rss
 posted on 2008-05-29 19:02 Leven 阅读(1588) 评论(8)  编辑 收藏 所属分类: Asp.Net MVC

#1楼     回复  引用  查看    
 tiray       | 2008-05-29 19:17
呵呵,多谢楼主!最近一直在研究博客技术,楼主的文章真是让我茅塞顿开啊!希望多多交流.我的个人网站:http://www.tiray.net
#2楼     回复  引用  查看    
 Q.Lee.lulu       | 2008-05-29 20:59
学习了!!!
PS: LS有广告嫌疑!!
#3楼     回复  引用  查看    
 第一控制.NET       | 2008-05-30 09:05
文章不错。嘿嘿。
在mvc中似乎所有文件夹里的cs文件都可以进行编译,所以没必要把不相关的cs都挤到那几个默认文件夹里。
生成rss的方式可以参考一下这篇文章。
http://www.cnblogs.com/ziie/archive/2008/05/28/1208817.html
#4楼 [楼主]    回复  引用  查看    
 Leven       | 2008-05-30 09:42
受教了,果然是好方法,转向.net3.5还不久,看来还要好好学习.
#5楼     回复  引用  查看    
 SZW       | 2008-05-30 10:15
这次ResultAction真是一个很大的进步,返回一个ResultAction类型的思路,对于MVC中Ajax的实现也有很大的意义,不知道以后能不能再来一个ResultActionCollection,嘿嘿~
#6楼     回复  引用    
 MIC [未注册用户] | 2008-05-30 15:46
.net3,5有自带的RSS类库
#7楼     回复  引用    
 king2003 [未注册用户] | 2008-06-08 00:16
rticleModel.GetList().ToDefaultRss()
那个ToDefaultRss哪里来的?
#8楼 [楼主]    回复  引用  查看    
 Leven       | 2008-06-08 09:50

@king2003


请查看EntityExtersions.cs中的对应扩展方法

被阅699次, 0投一票Asp.Net MVC
  • 看完了要说点啥么?
  • 昵称 (不填说不了话)
  • 信箱地址 (不会被公开,但是不填也说不了话)
  • 网址 (这个不填也成)

Powered by MiniBoke v2.0.0.8 Build 0828

Copyright © 2008 迷你博客. All rights reserved.

粤ICP备07500939号