浪漫骑士必胜

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

图书商城项目总论

这些年来,我随指南针公司做了一些网站。在这里也感谢指南针用户对鄙人的大力支持,厚爱。汇聚很多程序员多年的智慧,今天我把多年来积累的经验汇聚到一个图书商城项目里面,为大家介绍网站的源代码。关键的环节在于融会贯通,举一反三。

先从注册开始,注册说起来相对来比较简单

      

一、登录界面

注册界面里面有文本框,有用户名的检测 – 用到“AJAX”这个知识点

填写完信息点击注册后,有个js或是jq的校验

当信息全部填写完,用户点击注册按钮后,把表单里面的数据向服务端提交,在服务端接收数据,插入数据库。

 

那么,除了把用户信息插入数据库当中之外,我们还要实现用户激活的功能。就是获取用户输入邮箱,根据邮箱发一封邮件。邮件的内容就是激活链接。

 

把用户信息写入数据库相对简单,问题是怎么去发邮件,怎么发激活链接?这是我们重点讲解的内容。介绍怎么知道用户点没点链接,怎样进行激活。

 

接下来做的一个功能就是找回密码功能。

 

二、找回密码演示界面

根据用户的邮箱,把用户名和密码发给用户。这也是我们重点讲解的内容。

这部分用到了之前我们讲解的缓存。

接下来我们做下用户注册之后上传头像的功能,

以前我们上传的时候可能用的是<input type=”File”>但是用户的体验度不是特别的好,为什么呢?<input type=”submit”>一点submit就刷新了。

我们要做个无刷新上传。讲解两种方式,重点介绍flash开源的组件。

 

 

 

 

 

三、无刷新上传演示

上传之后,完成截取功能。

 

四、头像截取功能介绍

讲解flash组件的使用,上传的服务端代码,jq和js实现截取,获取坐标。

然后实现登录功能:

 

五、登录功能介绍

这里要实现用户名,密码的校验,实现:“记住我”的功能。记住我使用cookie。

这块说完了之后,我们再说下AJAX的登录模式。

 

 

 

 

 

 

 

 

六、AJAX登录模式

以及遮罩效果,遮罩我们使用jq来实现。

下一步我们看下:图书列表的展示,我们怎样用美工做好的html网页,怎么样把数据从数据库中拿出来并且进行绑定。

具体实现步骤,从服务端获取相关数据,绑定以及分页的实现。排序的基本实现,还会详细探讨下viewstate。

 

七、图书列表展示

 

八、分页效果一

 

九、另外一种分页的模式

看完另外一种分页的形式后,我们看下url重新问题。

 

十、url重写

并且深入探讨url重写问题。url重写主要就是为了SEO网站优化的问题。

接下来看下怎么生成静态页:

 

十一、生成静态页

也就是纯html网页,当用户量比较大的时候,我们最好做成静态页。

然后再看下评论的发布。

 

十二、评论的发布

这里要实现评论的发布,以及评论内容的加载。重点关注的是时间问题,非具体时间的显示。请仔细看下我们评论区域,不是普通的文本编辑器,是个ubb的文本编辑器。

在这里还要看下xss跨站点脚本攻击的问题和敏感词过滤问题(禁用词,审查词,替换词)。关于审查词,如:发票。这两个字先提交到数据库,管理员进行审核。

接下来的内容自己可以做了,就是评论内容的无刷新分页。

还有就是当滚动条滚动到页面的最下端的时候,才显示评论信息的功能。

这些都讲解完成后,进入购物车功能:

 

十三、购物车功能

  在这里实现商品的增加,商品的递减,商品的删除一系列功能。用jq或js完成。

  接下来我们完成结算的功能讲解。

 

十四、结算功能

 进入到订单确认页面里面,输入收货人的地址,选择支付方式,在这里重点讲解怎么实现支付宝。当然在这里我们使用的是模拟的支付宝系统,带大家理解下原理,以及流程。

 接下来就到结算功能了,在这里用户要完成下订单操作,向支付宝发送数据的功能。

 介绍完这部分内容以后,我们再详细的介绍下编辑器。

 

十五、编辑器

  在这里我们要了解下它的基本使用,再带大家学习词库

 

十六、词库

  要实现敏感词的过滤功能的话,在我们的系统里面必须得有个词库。在这里我们讲解下词库的添加与下载。

  接下来我们再讲解下日志记录问题。用到一个开源的框架。

  再来介绍下开源的定时框架。就是每隔多长时间去执行什么任务。比如:每天一个约定时间去统计今天的订单数。

  这些介绍完以后,我们再来介绍下SEO的问题。

  最后的文章里面会给大家介绍下视频处理的问题,就是怎么样做视频的播放的问题。当用户上传任意的格式的视频的时候我们怎么样进行转换。转完以后又怎么播放。

 

 

 

 

 

 

 

十七、播放有关内容

  接下来再说下权限管理的内容:

  这块我们单独的进行演示

 

十八、权限管理系统

 

十九、权限管理-用户管理

  当admin管理员进入的时候,可以展示出所有的菜单。管理员可以添加新的用户,添加完用户以后可以给这个用户添加角色。

 

二十、权限管理-角色管理

  然后为这个角色指定权限。

 

二十一、为角色指定权限

  以及菜单管理。

 

二十二、菜单管理

  菜单用户可以进行添加。

 

二十三、添加菜单

  然后菜单项也是与权限相关联的。当管理员登陆的时候,菜单全部展开,普通用户登录,只能展示出相应的菜单。所以说,菜单也有权限编号。当用户登录的时候拿到菜单的权限编号和用户的权限编号进行对比,来决定显示哪个菜单。

 

好,总论讲解完毕,下面进入详细环节。先看下权限管理内容。

权限表分析:在权限管理里面最重要的是三个对象,用户管理对象,角色管理对象,权限管理对象。这里就用到了面向对象的思想。

请看下面的图示:

 

二十四、权限管理数据库分析

先看下名词解释,用户很好理解。什么叫角色呢?老师,学生都是角色。权限也比较的好理解。

在这里用户为什么没有跟权限直接的进行关联呢?

用户要和角色进行关联,用户属于某个角色。在这里举个例子讲解:杨川川入职了,就是个新员工,公司里面有个打卡系统,经理要开给杨川川在办公系统开个账户。现在公司决定新入职的员工权限提升一次,之前5个权限,现在6个权限。假如说系统在设计的时候是用户和权限直接关联的。本月来的10个新员工,都要调整权限。但是用户要是和角色相关联的话,这时,只要把新员工的权限改下就行了。所有属于新员工的用户权限就都发生变化了。

下面我们就看下权限的数据库怎么进行设计了,最基本的得有用户表,角色表,权限表。

用户表里面有哪几个字段呢?

用户编号,用户名,密码,性别,邮件。

角色表里面有哪几个字段呢?

角色编号,角色名。

权限表里面有哪几个字段呢?

权限编号,权限名。

用户跟角色进行关联,按照我们之前讲解的内容,两个表就有关系了。主外建关系。如果我在用户表里面加个角色编号的话,你们认为合理么?

一个用户属于一个角色,一个角色下可以有多个用户,所以说这两个表的关系就是多对多的关系。既然是多对多的关系,我们怎么表现出这种关系呢?

还得需要一张表,就是用户角色关系表。用户和角色的关系就体现在用户关系角色表里面了。

用户关系角色表里面应该有哪些字段呢?

用户编号,角色编号。

角色表跟权限表是个什么关系呢?

也是个多对多的关系,所以,再建一张表,叫做角色权限关系表。

这张表中有:角色编号,权限编号的字段。

这五张表就是我们的核心表了,还有一张我多增加的表叫做权限类别表。然后权限都放在一个大类下面。

有:类别编号,类别名称字段。

在权限表中,增加个:类别编号的字段。

 

二十五、数据库当中的六张表

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

二十六、权限管理模块核心表结构

我们看到还有像菜单表,用户信息表中还有部门这样的字段。刚才的六张表的分析,以思路为主,采用的字段都是最基本的字段。

刚才我们分析了数据表的创建过程,关键是思路,能理解这个过程就可以了.

下一步我们开始设计登录的内容,打开项目,我们先用手写的三层,后面讲到图书商城项目的时候再演示代码生成器.

 

 

 

 

 

 

 

 

二十七、web登录(1)

 

二十八、放验证码的位置

验证码插入位置:

View Code
 1 using System;
 2 using System.Collections;
 3 using System.Data;
 4 using System.Linq;
 5 using System.Web;
 6 using System.Web.Services;
 7 using System.Web.Services.Protocols;
 8 using System.Xml.Linq;
 9 using System.Drawing;
10 using System.Drawing.Drawing2D;
11 namespace Web
12 {
13     /// <summary>
14     /// $codebehindclassname$ 的摘要说明
15     /// </summary>
16     [WebService(Namespace = "http://tempuri.org/")]
17     [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
18     public class ValidateCode : IHttpHandler,System.Web.SessionState.IRequiresSessionState
19         //3.在一般处理程序中使用session要实现这个接口。
20     {
21 
22         public void ProcessRequest(HttpContext context)
23         {
24             context.Response.ContentType = "image/Gif";
25             CreateStr(CreateCode());
26           
27         }
28         private string CreateCode()
29         {
30             string str = "";
31             //1.随机生成一个数字
32             Random random = new Random();
33             str=random.Next(1000,9999).ToString();
34             //2.把数字放在个session里面。
35             HttpContext.Current.Session["code"] = str;
36             return str;
37         }
38         private void CreateStr(string code)
39         {
40             if (code.Length<= 0)
41                 return;
42             string str;
43             Random random=new Random();
44             using (Bitmap map = new Bitmap(4 * 14, 30))
45             {
46                 using (Graphics g = Graphics.FromImage(map))
47                 {
48                     g.Clear(Color.White);
49                     g.DrawRectangle(new Pen(Color.Gray), 0, 0, map.Width - 1, map.Height - 1);
50                     using (LinearGradientBrush brush = new LinearGradientBrush(new Point(0, 0), new Point(map.Width, map.Height), Color.Red, Color.Green))
51                     {
52                         for (int i = 0; i < code.Length; i++)
53                         {
54                             str = code.Substring(i, 1);
55                             g.DrawString(str, new Font("黑体", 14.0f, FontStyle.Bold), brush, new PointF(13.0f * i, random.Next(10)));
56                         }
57                         //for(int i=0;i<10;i++;)
58                         //{
59 
60                         //}
61                         for (int i = 0; i < 10; i++)
62                         {
63                             map.SetPixel(random.Next(map.Width), random.Next(map.Height), Color.FromArgb(random.Next(255), random.Next(255), random.Next(255)));
64                         }
65                         HttpContext.Current.Response.Clear();
66                         System.IO.MemoryStream stream = new System.IO.MemoryStream();
67                         map.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
68                         HttpContext.Current.Response.BinaryWrite(stream.ToArray());
69                     }
70                 }
71             }
72 
73         }
74 
75         public bool IsReusable
76         {
77             get
78             {
79                 return false;
80             }
81         }
82     }
83 }

下一步我们怎么把验证码放到登录页面上,我们该怎么放呢?

 

二十九、将验证码引入-用个img标签

接下来我点验证码的时候需要个切换效果,这个效果怎么实现呢?

我们用js来实现,我在这加了个a标签,在a标签里面写了个onclick

在js的函数里面怎么写呢?获取验证码的id,然后改变src属性,获取随机数加个毫秒数,这样第一步就完成了。

 

三十、切换验证码的代码

下一步我们就开始点击:登录按钮

现在我们在后台,后台的用户访问少,所以这里可以用服务端控件。

 

三十一、构建三层的时候需要注意的地方

 

三十二、DbHelperSQL

 

 

动软的代码生成器,把数据库连接字符串都放在appSettings里面了。不要放在这里面,因为ms为我们提供了connectionStrings。

那么我们在什么时候会用到appSettings里的键值对呢?比如分页,每页显示多少条记录,以前都写在程序里面。用户不想一页显示10条的话,我们只能再改程序。

最好的方式是写在配置文件里面,不需要改源代码。我们可以把关于每页显示多少页的项,放在appSettings里面。 ConfigurationManager.AppSettings["key"]获取一下。

 

三十三、配置文件中需要注意的地方

  其实,把经常变动的内容放在配置文件中也不是最佳的选择。如果现在网站正在服务器运行的情况下,正在使用这套程序的用户的会话丢了。最好的解决方式就是做个页面。可以在自己网站的后台做个页面,这个后面马上就讲。

像使用的数据库变化了这样的问题,涉及到抽象工厂。就是面向接口编程。建议看下《大话设计模式》。

 

三十四、配置页面

 

三十五、数据访问层我们回顾的内容

 

三十六、用户校验的DAL层代码

别忘了引用下model

下面写下业务逻辑层

 

三十七、用户校验的BLL层代码

  这里的BLL就是个打酱油的,别忘了引用DAL和Model。

接下来终于回到了web层。

引用bLL和Model,注意:每写完一层,我们都需要重新生成一下。

插入代码位置:

View Code
 1 using System;
 2 using System.Collections;
 3 using System.Configuration;
 4 using System.Data;
 5 using System.Linq;
 6 using System.Web;
 7 using System.Web.Security;
 8 using System.Web.UI;
 9 using System.Web.UI.HtmlControls;
10 using System.Web.UI.WebControls;
11 using System.Web.UI.WebControls.WebParts;
12 using System.Xml.Linq;
13 
14 namespace Web
15 {
16     public partial class Login : System.Web.UI.Page
17     {
18         protected void Page_Load(object sender, EventArgs e)
19         {
20         }
21         /// <summary>
22         /// 登录
23         /// </summary>
24         /// <param name="sender"></param>
25         /// <param name="e"></param>
26         protected void btnLogin_Click1(object sender, ImageClickEventArgs e)
27         {
28             //1:判断验证码
29             if (Session["code"] != null)
30             {
31                 if (Session["code"].ToString()== this.validateCode.Text)//拿到验证码的值。要是验证码中含有字母的话,不考虑大小写.tolower(),验证码的目的主要是防止机器注册。
32                 {
33                     //2:判读用户名密码
34                     string txtName = this.txtUsername.Text;//获取用户名
35                     string txtPass = this.txtPassword.Text;//获取密码
36 
37                    
38                     //开始校验,写个数据访问层,业务逻辑层
39                     BLL.Account_UserManager bll = new BLL.Account_UserManager();
40                     int userID=bll.CheckLogin(txtName, txtPass);//对用户进行校验,返回用户编号
41                     if (userID > 0)//登录成功
42                     {
43                         //对的话,记录下用户的信息
44                         Session["User"] = txtName;
45                         Session["UserID"] = userID;
46                         //跳转
47                         Response.Redirect("Manage/Main.htm");
48                     }
49                     else
50                     {
51                         this.lblMsg.Text = "用户名密码错误!";
52                     }
53 
54                 }
55                 else
56                 {
57                     this.lblMsg.Text = "验证码错误!";
58                 }
59 
60             }
61             else
62             {
63                 this.lblMsg.Text = "验证码错误!";
64             }
65         }
66     }
67 }

下面我们重点讨论下:session

session的主要作用就是记录用户登录信息,为什么要放进session,干什么用呢?在后台的页面里面进行校验。

 

三十八、新建test页

这个网页只有登录的用户才可以看,

 

三十九、登录测试页面

  网站管理员操作的后台页面有很多,在每个页面加这段代码的话,自己累,用户也非常的不爽。我们有什么好的方法处理这个问题么?

可以用过滤器:HttpModule---其中最核心的就是19个事件。

 

四十、19个事件

  看表,得知使用第九个。如何使用这张表:由于每一个动态页面都会走过滤器,我们就可以在过滤器里面进行判断。过滤器有19个事件,我们一查表发现是第9个。

  那么,我们怎么去使用第9个事件呢?

 可以自己定义个类,来继承HttpModule这个接口,也可以在全局配置文件里面,到底使用哪种方式,随便你.

下面我写好了这段代码,分享源代码贡大家使用:

插入CheckAdminModule.cs位置:

View Code
 1 using System;
 2 using System.Data;
 3 using System.Configuration;
 4 using System.Linq;
 5 using System.Web;
 6 using System.Web.Security;
 7 using System.Web.UI;
 8 using System.Web.UI.HtmlControls;
 9 using System.Web.UI.WebControls;
10 using System.Web.UI.WebControls.WebParts;
11 using System.Xml.Linq;
12 
13 namespace Web.Common
14 {
15     //1.自己定义个类继承自IHttpModule
16     public class CheckAdminModule:IHttpModule
17     {
18         #region IHttpModule 成员
19 
20         //2.IHttpModule里面有个主要的方法Init ,参数是HttpApplication。这就是我们的请求管道。
21         public void Init(HttpApplication context)
22           //3.获取第9个事件,通过委托调OnRequest这个方法
23         {
24             context.AcquireRequestState+=new EventHandler(OnRequest);
25            
26         }
27         //4.看下这个方法怎么做的呢?
28         public void OnRequest(object source, EventArgs e)
29         {
30             HttpApplication application = source as HttpApplication;//得到Application
31             HttpContext context = application.Context;//得到请求上下文.
32             Uri url = context.Request.Url;//得到当前请求的URL
33              
34             //5.请求Admin目录下的文件时,需要进行身份验证,只有管理员才能访问.
35             //6.为什么做个判断呢?就是我的后台的管理页面都要放在单独的文件夹里面,放在了admin里面了。如果下一步请求admin文件夹下的文件的话,肯定会带文件夹的名字。就判断一下这个路径里面有没有admin?有的话,就是请求的admin
36             if (url.AbsolutePath.ToLower().StartsWith("/admin"))
37             {
38                 //adminlogin.aspx和logout.aspx不需要身份验证
39                 //7.如果是的话,再判断一下,这个路径的末尾包不包含:adminlogin.aspx。包含的话,可以访问
40                 if (url.AbsolutePath.ToLower().EndsWith("adminlogin.aspx"))
41                 {
42                     return;
43                 }
44                 //退出
45                 if (url.AbsolutePath.ToLower().EndsWith("loginout.aspx"))
46                 {
47                     return;
48                 }
49                 //8.如果是admin下的一个文件但不是登陆退出的话,下一步就校验session,如果session为空的话,直接跳到登陆页面就行了。
50                 if (HttpContext.Current.Session["Name"] == null)
51                 {
52                     HttpContext.Current.Response.Redirect("adminlogin.aspx");
53                 }
54 
55 
56             }
57         }
58 
59         public void Dispose()
60         {
61             throw new NotImplementedException();
62         }
63 
64         #endregion
65     }
66 }

关键是配置项,我们要在Web.config里面配置一下。

                       

四十一、Web.config

上面的内容中我们把登录给大家写了一下,接着我们看下登录成功以后

 

四十二、跳转一

 

四十三、跳转二

 

四十四、然后看看Main.htm里面都是什么

 

四十五、用frameset的好处

可以使用母版页。母版页就是把公共的元素给独立出来。上面和左面都用母版页来做。那么,我在做后台管理系统的时候为什么没用母版页用的是frameset呢?用母版页一点就刷新,体验性不是特别的好。

 

四十六、frameset布局

前台(大众用户看的)页面的布局的时候,一般都用母版页来做,为什么这又不用frameset呢?frameset不利于SEO的优化,搜索引擎都有蜘蛛爬虫,这些蜘蛛不喜欢页面是frameset布局的。frameset放的是不同的页面,蜘蛛所喜欢页面就是一个页面。对于网站的后台(给管理员看的)就无所谓了。

接下来我们再回顾一下frameset的基本用法,

 

四十七、主页面

不需要用body了,因为body里面放的是网页的主体,只管分割,具体的内容显示交给其它的页面了。rows横向分割,iframe是内嵌框架,*剩下的高度或宽度,rows和cols不能同时使用。在left.html中设定target

 

四十八、设定left.html中的target属性

在使用frameset的时候,最好给它定死。noresize这个属性就是干这个事儿的。

下面我们看下菜单表的设计:

 

四十九、菜单设计一frameset

下面我们就看下怎么把菜单给取出来,

 

五十、干掉这条语句

 

五十一、给TreeView起个名字

菜单存在数据表里面,下一步要考虑菜单这个数据表它应该怎么设计。通过观察我们发现菜单是个树状结构,数据表要体现出这种主次关系。那么数据表怎么设计呢?通过父id体现这种主次关系。

 

五十二、数据表设计

那么我们这里不写ParentID行不行呢?做成两个表行不行呢?不行的,子菜单下面可能还有子菜单。所以,以后设计这种树状结构的时候,要增加一个父节点。

 

五十三、这样设计是不行的

下面我们就看下怎么取数据。

                    

五十四、IsPostBack属性

这个判断是我们在服务端经常用到的判断,下面我们再来说一下IsPostBack的用法。曾经是个面试题呦!

IsPostBack这个属性的值是个bool类型的,那么他在什么情况下为true,什么情况下为false呢?

当是一个get请求时,该属性的值为false。

如果是一个post请求时,该属性的值为true。

什么时候发get请求呢?用户在地址栏里面输入网址,点个超链接。

那么什么时候发post请求呢?

提交表单submit的时候。

那么在这个地方,加这个判断的意义是什么呢?

获取所有的菜单项,查询数据库,当用户第一次访问这个页面的时候,我们把数据从数据库里面取出来。加载到TreeView上,页面上有个submit或其它的提交按钮的话,一点按钮,发出post请求。导致页面挥发、刷新。这时还会再走下Page_Load方法,如果不加if(!IsPostBack)判断,又查询数据库了。加上这层判断就不用查询数据库了,因为IsPostBack属性为true,又加了个非。不成立就不执行下面的代码了。

继续往下走,为什么点击按钮导致页面刷新,为什么不用查数据库但是数据没有丢呢?因为VIEWSTATE。

 

五十五、viewstate

画图演示这个问题,

 

五十六、_ _VIEWSTATE出现的场景

那么IsPostBack这个属性,它怎么知道用户发的是get请求还是一个post请求呢?

根据的是请求报文,如果是get请求,请求报文里面只有请求头。如果是post请求还有请求体。

如果发出的是post请求,这时候会把_ _VIEWSTATE发到服务端,服务端一看有隐藏域过来,IsPostBack为true。

 

五十七、禁用隐藏域

当我们禁用隐藏域以后,_ _VIEWSTATE还有,但是它的value很少了。那么,我们想完完整整的干掉隐藏域的话,应该怎么办呢?

 

五十八、彻底干掉隐藏域

  但是,如果把它去掉了,服务端控件就没办法使用了,这样就回到了纯HTML的时代。

所以说,_ _VIEWSTATE这个东西让人用起来很方便,但是它返回的这坨代码很不爽。浏览器要加载这些东西,让浏览器变得很慢,卡住了一样。一般情况下,我们把隐藏域禁用掉。如果禁用掉的话,每次都要查数据库了。就不能加刚才的if(!IsPostBack)判断了。大家会问,如果我每次查询数据库的话也很慢,其实,在这个地方有外国专家写过博客,连数据库的时间比加载_ _VIEWSTATE的时间要短。一般情况下我们要把_ _VIEWSTATE禁用掉。但是我们现在做的是后台,就无所谓了。要是我们后面做图书列表的话,就没必要用_ _VIEWSTATE了。又不想每次查询数据,就只能启用缓存了。

 

下面我们就写下GetTreeData()

 

五十九、数据访问层代码

 

六十、业务逻辑层代码

 

六十一、UI层代码

接下来我们考虑下权限问题,我们获取用户的权限编号和菜单的权限编号进行一个对比.

                       

六十二、权限编号的由来

首先应获取下用户所具有的权限编号,

 

六十三、分析哪两张表关联好写sql语句

分析结果:角色权限关系表dbo.Accounts_RolePermissions

用户角色关系表dbo.Accounts_UserRoles

通过RoleID关联起来,得到权限编号了。

 

六十四、写好DAL.Account_UserService

 

六十五、写好BLL.Account_UserManager

然后再回到left.aspx.cs页面

 

六十六、登录的时候存到Session里面

 

六十七、权限UI层

最后,我们来看下退出的问题。

 

六十八、放个退出按钮

 

六十九、切换到设计模式

       

七十、退出代码

       这块出问题了,我们用的是frameset,跳转的时候只跳出上面这块。

 

七十一、这样写退出

target的其它选项自己去查,比较简单,不再这里说了。

再加个Loginout.aspx页面。其实退出页做个一般处理程序比较的好。

 

七十二、新建退出页

 

七十三、页面报错

 

七十四、报错的原因

关键就是target属性,今天我们的文章当中就提到了两次。

作者近期文章列表:

C#中级进阶教程(完全免费,献给代码爱好者的最好礼物。注:本作者分享自己精心整理的C#中级进阶教程,无任何商业目的。希望与更多的代码爱好者交流心得,也请高手多多指点!!!)
三层及其它内容 递归
三层(一)
三层相关案例(及常见的错误)
三层实例(内涵Sql CRUD)
手写代码生成器
SQL数据库 ADO.net 数据库的应用图解一
数据库的应用详解二
ADO.NET(内涵效率问题)
ADO.NET实例教学一
ADO.NET(内含存储过程讲解)
面向过程,面向对象中高级 面向过程,面向对象的深入理解一
面向过程,面向对象的深入理解二
面向对象的深入理解三
无处不在的XML
winform基础 Winform基础
winform中常用的控件
面向过程 三种循环的比较
C#中的方法(上)
我们常见的数组
面向对象 思想的转变
C#中超级好用的类
C#中析构函数和命名空间的妙用
C#中超级好用的字符串
C#中如何快速处理字符串
值类型和引用类型及其它
ArrayList和HashTable妙用一
ArrayList和HashTable妙用二
文件管理File类
多态
C#中其它一些问题的小节
GDI+ 这些年我收集的GDI+代码
这些年我收集的GDI+代码2
HTML概述以及CSS 你不能忽视的HTML语言
你不能忽视的HTML语言2精编篇
你不能忽视的HTML语言3
CSS基本相关内容--中秋特别奉献
CSS基本相关内容2
JavaScript基础 JavaScript基础一
javascript基础二JavaScript DOM编程
jQuery jQuery(内涵: jquery选择器)
posted on 2012-12-16 17:33  小事好  阅读(5055)  评论(29编辑  收藏  举报