基于ASPNET的博客系统的设计与实现.doc
摘要基于Microsoft环境ASP技术,为开发功能强大动态网站提供了一种简单、高效途径。该博客系统以ASP为开发技术,使用C为开发语言,实现了博客网站动态管理,使得对博客信息管理更加及时、高效,提高了工作效率。同时对系统背景需求、系统功能特点与设计方案进行了介绍。该文还以随笔管理为例,对ASP环境下MVC开发模式进行了简单介绍。.关键字ASP;ADO;博客;系统;数据库引言博客,数字生活新时尚,通过文字、图片、声音、视频、无线等,尽情展示自我、分享感受、参及交流,美好你我生活。Show you, share me,人人都可以博客,人人都需要博客。1 项目背景“博客”一词是从英文单词Blog翻译而来。Blog是Weblog简称,而Weblog则是由Web与Log两个英文单词组合而成。Weblog就是在网络上发布与阅读流水记录,通常称为“网络日志”,简称为“网志”。它是继Email、BBS、IM之后出现第四种全新网络交流方式。它绝不仅仅是一种单向发布系统,而且有着极其出色交流功能。另外Blog也提供了非常方便实用个性化功能。简言之,Blog就是以网络作为载体,简易迅速便捷地发布自己心得,及时有效轻松地及他人进行交流,再集丰富多彩个性化展示于一体综合性平台。2 需求分析2.1需求调研任何一个系统开发,必然有其需求者,博客系统也不例外,本系统通过对互联网中各个博客系统分析,得出从以下几个方面进行调研:(1)、收益需求:描述系统商业需求与系统将带来收益。(2)、日常功能:亲身体验一个博客在系统中如何交互,然后记录下来。(3)、通过论坛来了解各博客用户需求:记录下各论坛中各博客用户对博客要求记录。(4)、制作邮件调查表:通过调查表形式得出一些具体书面信息,了解细节。2.2创建用例图博客系统参及者:如图1用户博客管理员博客访问者系统管理员图1 博客系统参及者博客系统用例:如图2用户博客访问者系统管理员博客管理员管理博客账号删除博客内容阅读博客内容用户登录修改账号信息浏览博客目录发表评论管理博客内容图2 博客系统用例图2.3、详细描述用例(举例)用户登录用例如表1所示表1 用户登录用例表用例名称用户登录用例IDUC_11参及者用户、管理员描述用户登录系统过程风险低优先级高难度低启动主动进入用户登录画面或会话超时转入用户登录画面前置条件用户需在登录状态后置条件将用户信息放入会话中将用户相关博客信息放入会话中显示博客阅读主画面主事件流用户系统1、进入或转入用户登录画面2、用户输入用户名与密码3、系统检查用户与密码是否合法4、系统检查用户是否存在,密码是否正确5、读取用户基本信息、博客基本信息放入会话中6、转到管理博客主画面异常流异常流系统中不存在该用户或用户名错误系统转入登录画面异常用户不存在或者密码错误用户登录用例图如图3所示:填写用户名、密码验证用户名、密码进入登录前的界面储存博客账号信息提示用户登录失败图3 用户登录用例图3系统分析3.1系统中对象面向对象开发基石是对象,那么分析一个系统开始就是从确定对象开始。那么这个系统重要实体对象有:博客账户信息、用户、标题、用户名、密码、分类、文章、链接、评论、随笔、图片。而必须对象有:文章,图片,随笔,链接,博客账号,分类,评论。3.2 开发技术分析本系统采用ASP开发技术进行开发。ASP不仅仅是ASP一个新版本,更是Web应用程序编程方面一个全新概念与方法。ASP中新功能并不是对ASP改进,设计它初衷是为用户入境提供最佳应用程序架构。它相比于ASP有着以下几个方面优点:(1) 多语言ASP曾在脚本引擎方面受到了限制,特别是VBScript与Jscript。而ASP则支持多种语言,默认情况下为Visual Basic、C#与Jscript,另外还支持一些第三方语言。(2) 服务器处理ASP在服务器处理上不管页面内容是纯HTML还是ASP生成HTML,它都是按照页面顺序显示。因此逻辑代码依赖于它在页面中位置,并且无法将HTML控件作为目标,除非将它们作为流一部分进行显示。而ASP就解决了这个问题,方法是为控件引入一个声明基于服务器模型,因为控件在服务器上有,可以在服务器上编程,也可以是客户端驱动事件。(3) Web Form控件将现有HTML控件转换为服务器端控件是比较容易,但是也存在一些不方便,例如比较难于区分HTML控件与服务器端控件。于是Microsoft公司就创建了一组专门服务器控件,它们都用asp:前缀标识。(4) 代码及内容分离一个网站设计及开发往往由不同人来实现,而ASP中就是存在着这样一个问题,代码(ASP脚本)与内容(HTML)混合在一起。这样就使得同时进行设计与开发变得很困难。而ASP则采用了代码内联与后台编码两种方法实现了代码及内容分离。3.2 健壮性分析(举例)下面以对博客系统用户登录用例为例进行健壮性分析:3.3.1事件流分析事件流分析主要是针对系统中用例描述中关于事件流部分进行分析,此外还必须综合考虑基本路径与扩展路径两方面。3.3.2边界对象分析边界对象:通常是用来完成参及者(用户、外部系统)及系统之间交互对象。在用户登录这个用例中,由于不存在外部系统,而且参及者也只有一个,就是“用户”,因此它边界对象有:(1)用户进入登录画面。(2)转到管理博客主画面。3.3.3实体对象分析实体对象:通常来自域模型,也就是现实世界,用来描述具体实体,通常映射到数据库表格及文件。这个用例实体对象包括用户与博客账号信息。3.3.4控制对象分析控制对象:主要用来表达应用程序执行逻辑,将其抽象出来,可以使得程序不影响用户画面与数据库中表。这个用例控制对象有:检测博客账号合法性。3.4交互设计3.4.1引入实体对象根据健壮性分析,可以把实体对象给罗列出来。这些对象通常也是每个类一个实例。由于是用来描述运行时状态情况,因此是对象,而非类。3.4.2引入边界对象与参及者将实体对象引入之后,再就是将边界对象找出来,在交互设计中引入参及者与边界对象。3.4.3引入控制对象将参及者、边界对象均引入之后,再就要结合健壮图中控制对象,以及用例描述中事件流来确定对象之间消息传递。3.4.4添加类属性及方法在交互设计中,将会发现类应该具有方法,也会在设计中找到一些新属性,而这些东西将近一步地完善交互设计。结合健壮分析、交互设计时引入设计类,并添加相应属性及方法。3.4.5引入基础类在着手开发之前,有一件很重要事,那就是引入基础类。不管用什么样开发工具进行代码编写,都将以各种库函数、框架作为开发基础。因此首先根据应用需要选择相应框架,然后再根据具体局部需要选择相应类库。这个系统中要进行数据库操作,可使用 FrameworkADO进行数据库操作。在进行文本编辑时使用文本编辑,引入第三方控件,使用FreeTextBox编辑器。在进行分页时,同样引入第三方控件,使用AspNetPager分页控件。由于这些第三方控件均是开放源码,所以我们自己可以在开发过程中对控件进行自己改动,既有效又方便。需要将这些类库、控件引入到工程中。4.代码实现4.1、编码之前工作4.1.1在Visual studio中,系统开发主要是以解决方案形式解决。所以我们在开发这个博客系统前,首先要先创建一个解决方案,命名为MyBlog。4.1.2文件夹规划在一个Web项目中,文件夹也需要进行规划,通常包括ASP页面、图片、样式文件、Flash动画等元素,需要把它们放置到不同文件夹,才能很好地管理文件。那么该系统文件夹规划方式为:(1)Core文件夹下存放工程类文件。(2)根目录下只存放Default.aspx文件,根目录下Images下存放及Default.aspx文件相关图片。(3)ASP页面需要按模块旋转到各文件夹,相关图片放置到模块文件夹下面Images文件夹下。(4)样式文件放置到根目录下Images文件夹下。4.2MVC模式4.2.1什么是MVC模式?MVC由Trygve Reenskaug提出,首先被应用在SmallTalk-80环境中,是许多交互与画面系统构成基础。MVC结构是为那些需要为同样数据提供多个视图应用程序而设计,它很好地实现了数据层及表示层分离。MVC作为一种开发模型,通常用于分布式应用系统设计与分析,以及用于确定系统各部分间组织关系。对于画面设计可变性需求,MVC(Model-View-Controller)把交互系统组成分解成模型、视图、控制器3种部件。(1)视图部件把表示模型数据及逻辑关系与状态信息以特定形式展示给用户。它从模型获得显示信息,对于相同信息可以有多个不同显示形式或视图。(2)控制器部件是处理用户及软件交互操作,其职责是控制提供模型中任何变化传播,确保用户画面及模型间对应联系;它接受用户输入,将输入反馈给模型,进而实现对模型计算控制,是使模型与视图协调工作部件。(3)模型部件保存由视图显示、由控制器控制数据;它封装了问题核心数据、逻辑与功能计算关系,它独立于具体画面表达与I/O操作。模型、视图及控制器分离,使得一个模型可以具有多个显示视图。如果用户通过某个视图控制器改变了模型数据,所有其他依赖于这些数据视图都应反映了这些变化。因此,无论何时发生了何种数据变化,控制器都会将变化通知所有视图,导致显示更新。这实际上是一种模型变化传播机制。4.2.2ASP模式下如何实现MVC?ASP提供了一个很好实现这种经典设计模式类似环境。开发者通过在ASPX页面中开发用户接口来实现视图;控制器功能在逻辑功能代码(.cs)中实现;模型通常对应应用系统业务部分。在ASP中实现这种设计而提供一个多层系统,对较经典ASP结构实现系统来说有明显优点。将用户显示(视图)从动作(控制器)中分离出来,提高了代码重用性。将数据(模型)从对其操作动作(控制器)分离出来,可以让用户设计一个及后台存储数据无关系统。就MVC结构本质而言,它是一种解决耦合系统问题方法。4.3用户组件与样式设计博客系统中存在很多相同或相似元素,这些元素可能是页面标题,可能是页面版权声明,也可能是文章列表或是登录信息框。需要寻找一种方式在整个系统中共享,而不需在变化时修改所有页面。所以就采用了样式文件进行管理以及用户自定义组件。4.3.1 使用统一样式表在样式文件中主要对以下五个内容进行定义:(1)博客标题:它是博客随笔、文章标题、图片名称样式定义。(2)博客内容:它是博客内容、文章内容样式定义。(3)博客版权信息:它是博客系统页面下方显示博客系统版权信息样式定义,在Footer用户控件中使用。(4)导航栏:它是博客系统上方导航栏样式定义,在Header用户控件中使用。(5)输入框:它是博客系统表单元素样式定义。 设计用户控件ASP为开发人员提供了用户控件这一新技术来实现Web元素共享,开发人员可以通过Visual Studio进行Web元素外面开发,同时可以通过Web元素后台代码方式进行表现层开发。在这个博客系统中,使用了Header、Footer等用户控件。4.4、数据库设计博客系统中数据管理形式采用数据库,根据系统需要及数据规范化分为博客账户信息表(blog),博客文章信息表(Article),博客随笔信息表(Essay),博客类别表(Category),博客评论表(FeedBack),博客链接表(Href),博客图片表(Picture)这七个表,表结构分别如下:表2博客账户信息表(blog)列名数据类型长度允许空备注BlogIDInt4没有实际意义,作为该表主键存在SubjectNvarchar50Null博客名称UsernameNvarchar50Null博客用户名PasswordNvarchar50Null博客密码DescriptionNvarchar100Null博客描述EmailNvarchar200Null博客电子邮箱EntrynumInt4Null博客每页文章显示数量NameNvarchar50Null角色名称RoleInt4Null角色EssaycountInt4Null随笔数ArticlecountInt4Null文章数FeedbackcountInt4Null评论数表3博客文章信息表(Article)列名数据类型长度允许空备注ArticleIDInt4文章表主键SubjectNvarchar50Null文章标题ContentNtext16Null文章内容CategoryIDInt4Null文章所属分类号BlogIDInt4Null文章所属博客号TimeNvarchar50Null发表时间ViewInt4Null查看次数FeedbackInt4Null评论数表4博客随笔信息表(Essay)列名数据类型长度允许空备注EssayIDInt4随笔表主键SubjectNvarchar50Null随笔标题ContentNtext16Null随笔内容CategoryIDInt4Null随笔所属分类号BlogIDInt4Null随笔所属博客号TimeNvarchar50Null发表时间ViewInt4Null查看次数FeedbackInt4Null评论数. 表5博客类别表(Category)列名数据类型长度允许空 备注CategoryIDInt4主键NameNvarchar50Null类别名称BlogIDInt4Null类别所属博客号TypeNvarchar10Null类别所属博客类型DescriptionNvarchar500Null该类别描述表6博客评论表(FeedBack)列名数据类型长度允许空备注FeedBackIDInt4评论号,主键SubjectNvarchar50Null评论标题ContentNtext16Null评论内容BlogIDInt4Null针对评论博客号CategoryIDInt4Null该评论博客类别号ContentIDInt4Null针对博客标题评论内容号CategoryNvarchar50Null评论所属类别TimeNvarchar50Null发表评论时间UsernameNvarchar50Null评论人姓名UrlNvarchar100Null评论人邮箱表7博客链接表(Href)列名数据类型长度允许空备注HrefIDInt4链接号,主键NameNvarchar50Null链接名字UrlNvarchar200Null链接CategoryIDInt4Null链接所属类别号BlogIDInt4Null链接所属博客号表8博客图片表(Picture)列名数据类型长度允许空备注PictureIDInt4图片号,主键ImageUrlNvarchar200Null图片链接SubjectNvarchar50Null图片标题CategoryIDInt4Null图册号BlogIDInt4Null图片所属博客号4.5系统实现4.5.1系统结构图根据前面需求分析可以得出以下系统结构图:博客系统后台管理阅读博客系统管理随笔管理文章管理评论管理链接管理图片管理账户管理密码管理密码管理图4系统结构图各界面如下:(1)、阅读博客:图5阅读博客界面(2)、随笔管理:(文章管理、评论管理、链接管理、图片管理均类似)图6随笔管理界面后台管理密码管理界面:图7后台管理密码管理界面系统管理主界面:图8系统管理主界面系统管理账户管理界面:图9账户管理界面系统管理密码管理界面同后台管理,如图七。4.5.2 代码实现整个系统代码实现均采用表现层、控制层、数据层来实现,并且定义了一个抽象类DBObject类,其它一些类均由这个类继承。具体实现过程是用户在页面(表现层)激发事件,那么页面后台代码(控制层)作出回应,根据事件不同来调用数据层对数据库进行操作。以下以随笔管理为例来说明ASP代码实现。(1)实现表现层图六所示即为随笔管理列表页面,它代码在BlogAdminEssayEssay.aspx中。这个页面由三大部分组成。标头及导航栏做成了用户控件,在左右功能区中,左下角分类列表是由一个列表控件Datalist捆绑数据后生成,用到了ItemTemplate模板。ItemTemplate模板代码如代码1:代码1ItemTemplate模板<asp:datalist id="essayCategory" Runat="server" Width="160"><ItemStyle Height="20"></ItemStyle><ItemTemplate> <%#DataBinder.Eval(Container.DataItem,"CategoryStr") %></ItemTemplate></asp:datalist>页面中右区为随笔信息列表,这也是由Datalist列表控件绑定数据后生成,这里不仅定义了ItemTemplate,还定义了HeaderTemplate模板、AlternatingItemTemplate模板、SeparatorTemplate模板与FooterTemlplate模板。如代码2所示:代码2DataList列表控件绑定数据<asp:datalist id="essayList" Width="780" Runat="server" CellSpacing="0" CellPadding="0" BorderWidth="0"><HeaderTemplate><table width="780" style="border:#CCCCCC 1px solid" border="0" CellPadding="0" CellSpacing="0"><tr height="30" align="center"><td background="/blog/Images/main/l-bg3.jpg" width="300"><font color="#ffff66"><b>标题</b></font></td><td background="/blog/Images/main/l-bg3.jpg" width="120"><font color="#ffff66"><b>分类</b></font></td><td background="/blog/Images/main/l-bg3.jpg" width="60"><font color="#ffff66"><b>浏览人数</b></font></td><td background="/blog/Images/main/l-bg3.jpg" width="60"><font color="#ffff66"><b>评论人数</b></font></td><td background="/blog/Images/main/l-bg3.jpg" width="240" colspan="3"><font color="#ffff66"><b>操作</b></font></td></tr></table></HeaderTemplate><ItemTemplate><table width="780" style="background-color:#F5F5F5;border-right:#CCCCCC 1px solid;border-left:#CCCCCC 1px solid;"><tr height="20" align="center"><td width="300" align="left"> <%# DataBinder.Eval(Container.DataItem,"Subject") %></td><td width="120"><%# DataBinder.Eval(Container.DataItem,"Category") %></td><td width="60"><%# DataBinder.Eval(Container.DataItem,"View") %></td><td width="60"><%# DataBinder.Eval(Container.DataItem,"FeedBack") %></td><td width="80"><%# DataBinder.Eval(Container.DataItem,"Info") %></td><td width="80"><%# DataBinder.Eval(Container.DataItem,"Edit") %></td><td width="80"><%# DataBinder.Eval(Container.DataItem,"Remove") %></td></tr></table></ItemTemplate><AlternatingItemTemplate><table width="780" style="border-right:#CCCCCC 1px solid;border-left:#CCCCCC 1px solid;"><tr height="20" align="center"><td width="300" align="left"> <%# DataBinder.Eval(Container.DataItem,"Subject") %></td><td width="120"><%# DataBinder.Eval(Container.DataItem,"Category") %></td><td width="60"><%# DataBinder.Eval(Container.DataItem,"View") %></td><td width="60"><%# DataBinder.Eval(Container.DataItem,"FeedBack") %></td><td width="80"><%# DataBinder.Eval(Container.DataItem,"Info") %></td><td width="80"><%# DataBinder.Eval(Container.DataItem,"Edit") %></td><td width="80"><%# DataBinder.Eval(Container.DataItem,"Remove") %></td></tr></table></AlternatingItemTemplate><SeparatorStyle BackColor="#E6E6E6"></SeparatorStyle><SeparatorTemplate></SeparatorTemplate><FooterTemplate><table width="780" style="border-right:#CCCCCC 1px solid;border-left:#CCCCCC 1px solid;border-bottom:#CCCCCC 1px solid"><tr><td height="1"></td></tr></table></FooterTemplate></asp:datalist>由于DataList不像DataGrid有自动分页功能,所以我在这个系统中引入了一个第三方控件AspNetPager进行分页管理。首先声明控件:<% Register TagPrefix="Webdiyer" Namespace="Wuqi.Webdiyer" Assembly="AspNetPager"%>然后在页面中插入分页控件,如代码3:代码3分页控件<WEBDIYER:ASPNETPAGER id="pager" runat="server" Width="100%" OnPageChanged="ChangePage" PageSize="5" TextAfterInputBox=" 页 "TextBeforeInputBox="转到第 " ShowCustomInfoSection="left" NextPageText="下页" PrevPageText="上页" LastPageText="末页" FirstPageText="首页"ShowPageIndex="false" CssClass="text_white" ShowInputBox="always" HorizontalAlign="right" AlwaysShow="false"></WEBDIYER:ASPNETPAGER>(2)实现控制层由于随笔管理页面两次使用了DataList控件,所以要对DataList控件进行数据绑定,于是添加一个BindData()方法来处理数据捆绑过程。里面定义两个参数BlogID与CategoryID分别为博客编号与分类编号,用来确定当前显示是哪个博客中哪个分类中随笔内容。程序如代码4:代码4随笔数据绑定private void BindData(int BlogID,int CategoryID)DataSet cDs = cDAO.LoadList(BlogID,"e");cDs.Tables0.Columns.Add("CategoryStr");for(int i=0;i<cDs.Tables0.Rows.Count;i+)cDs.Tables0.Rowsi"CategoryStr" = "<a href="Essay.aspx?CategoryID="+cDs.Tables0.Rowsi"CategoryID".ToString()+"">"+cDs.Tables0.Rowsi"Name".ToString()+"</a>"this.essayCategory.DataSource = cDs.Tables0.DefaultView;this.essayCategory.DataBind();DataSet eDs = eDAO.LoadList(BlogID,CategoryID,pager.PageSize*(pager.CurrentPageIndex-1),pager.PageSize,"","");eDs.Tables0.Columns.Add("Category");eDs.Tables0.Columns.Add("Info");eDs.Tables0.Columns.Add("Edit");eDs.Tables0.Columns.Add("Remove");for(int i=0;i<eDs.Tables0.Rows.Count;i+)eDs.Tables0.Rowsi"Category" = cDAO.Load(Convert.ToInt32(eDs.Tables0.Rowsi"CategoryID").Name;eDs.Tables0.Rowsi"Info" = "<a href="View.aspx?EssayID=" + eDs.Tables0.Rowsi"EssayID".ToString() + "">浏览</a>"eDs.Tables0.Rowsi"Edit" = "<a href="Edit.aspx?EssayID=" + eDs.Tables0.Rowsi"EssayID".ToString() + "">修改</a>"eDs.Tables0.Rowsi"Remove" = "<a href="Remove.aspx?EssayID=" + eDs.Tables0.Rowsi"EssayID".ToString() + "">删除</a>"essayList.DataSource = eDs.Tables0.DefaultView;essayList.DataBind();pager.CustomInfoText="共"+pager.PageCount.ToString()+"页,当前为第"+pager.CurrentPageIndex.ToString()+"页"这里面使用了数据库操作对象CategoryDAOLoadList方法获取了DataSet对象对分类列表进行绑定,而用创建随笔数据库操作对EssayDAOLoadList方法生成随笔列表。(3)实现数据层在随笔管理绑定控制层中要使用到数据层操作类,如EssayDAOLoadList方法,它在BlogCore/EssayEssayDAO.cs文件中。代码5随笔数据层类public EssayVO Load(int id)Connection.Open();SqlCommand sqlComm = new SqlCommand("select * from Essay where EssayID = " + id,Connection);SqlDataReader tmpReader = sqlComm.ExecuteReader();EssayVO essayVO = new EssayVO();if(tmpReader.Read()essayVO.EssayID = Convert.ToInt32(tmpReader"EssayID".ToString();essayVO.BlogID = Convert.ToInt32(tmpReader"BlogID".ToString();essayVO.Subject = tmpReader"Subject".ToString();essayVO.Content = tmpReader"Content".ToString();essayVO.Time = tmpReader"Time".ToString();essayVO.View = Convert.ToInt32(tmpReader"View".ToString();essayVO.FeedBack = Convert.ToInt32(tmpReader"FeedBack".ToString();tmpReader.Close();Connection.Close();return essayVO;EssayDAO是DBObject子类,它完成了EssayVO对象基本方法,包括对EssayVO对象创建、修改、删除、选取与列表方法。以下是DBObject子类代码及EssayVO类代码:代码6public class DbObjectprotected SqlConnection Connection;private string connectionString;public DbObject()connectionString = System.Configuration.ConfigurationSettings.AppSettings"sqlConnection"Connection = new SqlConnection( connectionString );protected string ConnectionStringget return connectionString;代码7public class EssayVOprivate int essayID;private string subject;private string content;private string time;private int view;private int feedBack;private int categoryID;private int blogID;public int EssayIDget return essayID;set essayID = value;public string Subjectget return subject;set subject = value;public string Contentget return content;set content = value;public string Timeget return time;set time = value;public int Viewget return view;set view = value;public int FeedBackget return feedBack;set feedBack = value;public int Categor