原文地址:
http://www.cnblogs.com/yqhome/archive/2012/07/11/2585584.html
在上一篇文章中,已经对该博客系统的架构,功能设计做了一些介绍。点击查看:YQBlog - 基于Asp.Net MVC3的个人博客系统分享【开源】
这里对新增的部分做一些分享。
博客预览
后台预览(屏蔽了增删改)
源码下载(请下载最新版YQBlog1.1)
新增功能:
1.用户中心。
2.用户在页面中对于所发评论/留言的修改,删除。
3.系统邮件发送(留言、回复email通知提醒)
4.简单的ubb编辑器
主要知识点:
1.jquery选项卡
2.membership profile对于用户信息的扩充
3.flash头像上传
4.email在线发送(异步)
5.html,ubb代码在c#以及js中的互相转换
1.jquery 选项卡
基本上所有的选项卡菜单原理都一样,首先把所有的内容列出来,切换也就是显示一个,其它的隐藏起来。一些看起来比较炫的效果无非就是通过到位的backgournd,border等样式定义来实现。Jquery让一切变得华丽且简单:
$(function () { $("#ucenter .tabbtn").click(function () { var index = $("#ucenter .tabbtn").index($(this)); $(this).addClass("u_current").siblings("li").removeClass("u_current"); $($("#ucenter .tabitem").get(index)).show().siblings(".tabitem").hide(); }); });
html文档:
<div class="uoperation"> <ul> <li class="u_index tabbtn u_current">@res.BasicInformation</li> <li class="u_avatar tabbtn">@res.UploadAvatar</li> <li class="u_profile tabbtn">@res.ModifyInformation</li> <li class="u_comment tabbtn">@res.MyComments</li> <li class="u_note tabbtn">@res.MyMessages</li> </ul> </div> <div class="ucontent"> <div class="tabitem" style="display:block;"> <div class="uitem">@res.BasicInformation</div> <!--content--> </div> <div class="tabitem"> <div class="uitem">@res.UploadAvatar</div> <!--content--> </div> <div class="tabitem"> <div class="uitem">@res.ModifyInformation</div> <!--content> </div> <div class="tabitem"> <div class="uitem">@res.MyComments</div> <!--content--> </div> <div class="tabitem"> <div class="uitem">@res.MyMessages</div> <!--content--> </div> </div>
效果图:
2.membership profile对于用户信息的扩充
YQBlog的用户系统采用了微软自带的membership,在上一个版本中,并没有涉及多少用户的操作。所以这次主要是新增了一些用户的功能。这里,我们需要对用户信息进行扩展,包括用户头像上传,详细资料填写,比如所在地,生日,qq,微博,facebook等。
基于membership的用户系统需要扩展用户信息,通常有两种方式:
1,创建新的用户扩展信息表,通过用户主表的自增id关联。结构类似membership中的 aspnet_Users(主表) 与 aspnet_Membership
2.使用membership自带的Profile机制。
我们采用方法2,利用membership的Profile机制扩展用户信息。
(1)web.config中配置SqlProfileProvider以及自定义属性元素。system.web节点下添加:
<profile> <providers> <clear /> <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" /> </providers> <properties> <add name="nickname" type="String"/> <add name="signature" type="String"/> <add name="intro" type="String"/> <add name="gender" type="String"/> <add name="birth" type="String"/> <add name="location" type="String"/> <add name="website" type="String"/> <add name="qq" type="String"/> <add name="sina" type="String"/> <add name="facebook" type="String"/> <add name="twitter" type="String"/> <add name="medals" type="String"/> <add name="phone" type="String"/> <add name="email" type="String"/> <add name="isSendEmail" type="String"/> </properties> </profile>
(2)处理程序。注意区分“当前用户”与“指定用户”
//获取当前用户Profile信息 public ActionResult Index() { ViewBag.nickname = HttpContext.Profile.GetPropertyValue(nickname); ...... return View(); } //获取指定用户Profile信息 public ActionResult Index(string user) { ProfileBase objProfile = System.Web.Profile.ProfileBase.Create(user); ViewBag.nickname = objProfile.GetPropertyValue("nickname"); ...... return View(); } //更新当前用户 [HttpPost] public ViewResult Index(string nickname) { HttpContext.Profile["nickname"] = nickname; ...... return View(); }
(完整代码见程序源码 Controllers/AccountController.cs)
假如我们录入nickname属性的内容为test。数据库中查看aspnet_Profile表,PropertyNames字段中为nickname:S:0:4,nickname表示属性名,S表示String类型,0:4表示PropertyValuesString字段中的从第0到第4位的内容即为nickname属性值,这里是test。可见membership profile是把所有属性作为一个字符串,所有属性值作为一个字符串来存储的。再通过属性部分的特定格式数据来存储其数据格式信息以及匹配对应的属性值。
小结:membership profile对于扩展一些用户基础信息还是很灵活的。但如果是一些读写频繁或者会涉及到检索,排序之类的操作,还是会选择用扩展表的方式。
3.flash头像上传
用的是Discuz!NT的会员头像上传功能。迁移到了MVC中。相关程序:
flash文件及上传目录:/Content/Avatar 调用程序: /Account/UCenter (/Views/Account/UCenter.cshtml) 上传程序:/AjaxAvatar.ashx
Global.asax中添加:
routes.IgnoreRoute("ajaxAvatar.ashx");
4.email在线发送(异步)
介绍两种方式,WebMail 和 SmtpClient。程序中采用了SmtpClient
(1)WebMail
/// <summary> /// WebMail发送电子邮件 /// </summary> public static void SendWebMail(string emailTo, string emailTitle, string emailContent,string[] filePath = null, string[] additionalHeaders = null) { WebMail.SmtpServer = configinfo.SmtpServer;//获取或设置要用于发送电子邮件的 SMTP 中继邮件服务器的名称。 WebMail.SmtpPort = configinfo.SmtpPort;//发送端口 WebMail.UserName = configinfo.SmtpUser;//账号名 WebMail.From = configinfo.AdminEmail;//邮箱名 WebMail.Password = configinfo.SmtpPass;//密码 WebMail.EnableSsl = true;//是否启用 SSL GMAIL 需要 而其他都不需要 具体看你在邮箱中的配置 WebMail.SmtpUseDefaultCredentials = true;//是否使用默认配置 try { WebMail.Send(to: emailTo, subject: emailTitle, body: emailContent, isBodyHtml: true, filesToAttach: filePath, additionalHeaders: additionalHeaders); } catch{} }
(2)SmtpClient
/// <summary> /// SmtpClient发送电子邮件 /// </summary> public static void SendSysMail(string to, string subject, string body) { string from = configinfo.AdminEmail; string host = configinfo.SmtpServer; string userName = configinfo.SmtpUser; string password = configinfo.SmtpPass; int port = configinfo.SmtpPort; SendMail(from, to, subject, body, host, port, userName, password); } /// <summary> /// SmtpClient发送电子邮件 /// </summary> /// <param name="from">发件人</param> /// <param name="to">收件人</param> /// <param name="subject">邮件主题</param> /// <param name="body">邮件内容</param> /// <param name="host">发送服务地址(smtp.gmail.com)</param> /// <param name="port">发送邮件服务器端口</param> /// <param name="userName">用户名</param> /// <param name="password">密码</param> public static void SendMail(string from, string to, string subject, string body, string host, int port, string userName, string password) { MailMessage message = new MailMessage(from, to, subject, body); message.IsBodyHtml = true; message.BodyEncoding = Encoding.UTF8; SmtpClient client = new SmtpClient(host); client.Credentials = new NetworkCredential(userName, password); client.DeliveryMethod = SmtpDeliveryMethod.Network; client.EnableSsl = true; client.Port = port; client.Send(message); }
实现异步发送
用户提交评论/留言的同时,会判断他@了哪些用户需要发送email提醒信并且发送,email发送是比较耗时的,如果等这个操作完成才返回,就会很容易卡在发评论/回复的位置。所以我们应用委托异步来实现。
//定义委托 delegate void sendDelegate(string paras); //发送email private void SendEmails(string paras) { //email发送代码 } //调用 new sendDelegate(SendEmails).BeginInvoke(paras, null, null);
这里是把邮件的相关设置项写到了我们自定义的网站配置文件中(general.config),你也可以硬编码在函数里,或者在webconfig的appSettings中去定义。
后台邮件发送相关配置截图:
5.UBB编辑器,html,ubb代码在c#以及js中的互相转换
js部分位于Content\js\blog.js中
c#部分位于General\WebUtils.cs中
主要也就是各种正则转换。
6.用户在页面中对于所发评论/留言的修改,删除
主要是一些ajax异步操作
一个小技巧。异步加载的对象事件执行需要用live.直接click是不行的。
例如:
//评论修改 $(".reply-update").live("click", function () { //your code });
小分享一下我的学习心得:
1.百度知道
百度知道什么都知道,不乏小白问题,比如,你可以去百度知道搜索mvc是什么,怎么学mvc,要看哪些书等等。你想问的,不管有多小白,基本上都会有人问过。这个过程主要是为了让你对即将涉足的领域能有个大体轮廓。往往它能够让你在后面少走一些弯路。当你觉得已经看出个大概的时候,该转战博客园了。
2.博客园
(1)如果博客园制作了这个部分的专题。去看看专题里的文章。
(2)不妨看看所谓“速成”的文章,虽然没有真正速成这回事,但基本上他能给你讲了重点。“入门”的快感对初学者来说也很重要的。
(3)用你能想到的想关联关键字去搜索,好的博文不吝收藏,好的博客不吝关注。
(4)挑选一两个不错的系列(博客园写各种系列文章的博主很多),专注的去学习。3.源码
下载一些源码来学习。
不要一开始就去下源码,一头雾水的次数多了也会打击积极性。还是得先看一些文章,有一些基础知识储备。你可以集中一个时间去搜集源码。然后泛泛的过一遍,最后还是挑选一两个觉得不错的去深入学习。4.实践
比如学习MVC,MVC是什么?它是微软继webform后新的web开发框架。对,它是用来做网站的,那我们现在正在学习MVC,不,你在学习做网站。MVC只是我们做网站的一个解决方案,我们学习MVC,那我们就一定要去做网站。在实践的过程中,发现问题,解决问题。也通过实践,让我们学习的各种知识能有所积累,沉淀。翻看我前面几篇博文可以看出,现在的这个YQBlog其实就是几个月前我开始学习MVC3时的那个demo.
5.搜索
不懂就问,切记自己跟自己钻牛角尖,也切记闭门造车。闭门造车就是有时候我们要解决一个问题,自己在那折腾来折腾去,好不容易搞定了,回头一看,微软都给你封装好了,一个方法就ok了。
搜索的方法:“先博客园站内搜索再google搜索”。博客园的专注度更高,且搜索结果博客里的其它文章往往也会让我们有意外收获。google在于它的精准,特别是多关键字的模糊搜索时,忘了百度吧。如果还是搜索不到结果,试着把关键字换成英文的。这个时候,基本上stackoverflow就会出来告诉你答案。6.网站推荐
中文:
http://www.cnblogs.com/
http://www.csdn.net/
http://www.51cto.com/
http://msdn.microsoft.com/zh-cn/.net领域的话,一个博客园其实就够用了。
英文:
http://stackoverflow.com/
http://msdn.microsoft.com/
http://www.codeproject.com/
http://www.asp.net/
http://windowsclient.net/
http://jquery.com/
预告一下我的另一个开源程序YQCMS.
它可以算是YQBlog的增强版。在YQBlog基础上,它会增加下面一些特性:
1.静态化,可生成html页面
2.增加论坛(Forum),问答(Answers)模块。
3.多语言版本内容分离。(更彻底的多语言)
4.不同语言版本可设置各自的显示模板。
5.自定义字段(比如做企业站时,同样一个产品展示,字段差异是很大的)