上一篇文章我 向大家展示了BlogEngine.Net中Theme的原理和一些开发规范,里面有很多内容和这篇文章有着联系,建议大家这两篇文章结合在一起看,这样 效果会更好。在这篇文章中我主要向大家说明BlogBasePage,PostViewBase,CommentViewBase这三个类的内部实现上的 一些技巧以及它们与页面,文章和评论之间是如何组织在一起的,希望对大家阅读这部分代码有帮助。
认识一下它们
BlogBasePage,PostViewBase,CommentViewBase它们都是一些元素的基类,首先把这些元素定义成基类,然后使用继承的方式实现我认为主要有以下好处:
1.代码复用会得到提升,对于一些大量的同样操作都可以放在基类中,子类直接可以继承使用。
2.职责清晰,例如在Theme中的CommentView.ascx直接继承CommentViewBase就行了,CommentView.ascx只是来处理将Comment如何展现的问题。
3.规范化,这是继承带来的一个很重要的好处,因为子类就是一个父类,只要它是就可以使用。
BlogBasePage:Web站点的根目录下的每一个页面都是从它继承而来,BlogBasePage继承自Page。而页面不是直接从Page继承而来。
PostViewBase:是一个Post显示功能部分的基类,themes中每个主题的PostView.ascx都是直接从它继承而来,PostViewBase继承自UserControl。
CommentViewBase:是一个Comment显示功能部分的基类,themes中每个主题的CommentView.ascx都是直接从它继承而来,CommentViewBase继承自UserControl。
实现分析
BlogBasePage到底都做了些什么?
OnPreInit中主要完成根据BlogSetting中的Theme找到相应的页面的Master文件(包括主题选择时的预览判断),此外还处理了Post的删除。
OnLoad中做得事情很多,主要是在head中加入一些资源引用(包括SIOC,APML,FOAF等),实际上就是当我们打开页面查看源代码看到 head中多如牛毛的link。还有增加一些脚本的全局变量,增加BlogSetting中的自定义Head的html,增加track脚本,增加脚本引 用(通过JavaScriptHandler来实现),增加样式(注意css的压缩是通过CssHandler实现的)。
OnPreRenderComplete中完成了标题的设置。
OnError中还对使用Comment的恶意攻击做了处理。
{
HttpContext ctx = HttpContext.Current;
Exception exception = ctx.Server.GetLastError();
if (exception != null && exception.Message.Contains("callback"))
{
// This is a robot spam attack so we send it a 404 status to make it go away.
ctx.Response.StatusCode = 404;
ctx.Server.ClearError();
Comment.OnSpamAttack();
}
base.OnError(e);
}
PostViewBase到底都做了些什么?
PostViewBase是一个用户控件,主要是显示一个Post,内部除了一些Post属性 外,还有CommentFeed(通过SyndicationHandler处理),增加分类链接,增加Tag链接,增加管理链接,增加评分的脚本来给文 章评分等。此外在Page_Load还对加入内容中的一个自定义的控件标签进行了特殊的处理,这种格式如:[UserControl:~/path /usercontrol.ascx],使用一个正则来判断,如果内容中有这种标签,那么内容显示时使用加载的控件来代替。
CommentViewBase到底都做了些什么?
CommentViewBase是一个用户控件,主要是显示一个Comment,内部除了Comment和Post属性外,还有内容,管理链接,国旗显示,Gravatar显示等。请大家留意一下后面的两个图片的显示处理。
了解了这些,上一篇文章中讲述的Theme中的几个必要文件的数据显示问题就清晰多了吧。
页面的继承与组织关系
这部分没有什么原理性的东西,只是帮助大家快速阅读代码而做的一个文件的介绍。
login.aspx:继承BlogBasePage,完成登录,注销,修改密码等与登录有关的用户接口。
default.aspx:继承BlogBasePage,内部使用PostList.ascx用户控件完成文章的列表显示接口。
search.aspx:继承BlogBasePage,用一个repeater显示搜索结果,这个以前提及过。
archive.aspx:继承BlogBasePage,对文章的归档显示,注意它的归档的处理过程。
contact.aspx:继承BlogBasePage,主要是完成阅读者给文章的发布者发送邮件。注意它还实现了ICallbackEventHandler,来完成ajax回调提交。
error404.aspx:继承BlogBasePage,404错误转向。
page.aspx:继承BlogBasePage,完成删除Page,显示Page(注意对注入控件显示的处理和与Post区别)。
post.aspx:继承BlogBasePage,完成文章的显示,使用User controls/CommentView.ascx来完成评论列表的显示和评论的提交。Page_Init中动态加载PostViewBase,处理了 “上一篇”和“下一篇”等导航链接(需要Post类本身的支持),phRDF完成了Trackback的接收(以前文章提及过)。
对于Theme中的文件上文已经讲过,这里就不再多说。
对于admin/Pages中的这些管理页面都是直接继承自Page,Master为admin1.master,在Web.config中定义了访问权限等,这主要是实现了前端页面和后台管理的分开处理。
blog.js是BlogEngine.Net的所有脚本文件,里面封装Ajax处理(例如回调,评论的在线浏览等)。
总结
像BlogEngine.Net这种将几乎所有页面的Page再进行一下自定义的封 装的处理方式在很多项目中都会得到应用,这一点我觉得很好。对于注入控件的处理方式也值得我们去学习。这种注入控件我想主要是完成一些外部资源的引入问题 的,把文章或Page的显示交给这个用户控件来处理会很灵活。
麻雀虽小,五脏俱全
上一篇:BlogEngine.Net架构与源代码分析系列part11:开发扩展(下)——自定义Theme