RSS 2.0 Feed
2004-12 Entries
摘要: 目前已联系到的课程如下:大坏蛋 Remoting装配脑袋 VS.NET 2005 新特性陈叙远 NUnit单元测试的高级应用盛国军 设计高度可伸缩的数据访问层宝玉 ASP.NET Froums 架构 可能还会联系一到两门课程,联系好以后在本贴公布. 每门课程半个小时左右,重点是大家一起交流技术:) 还有就是会后大家可以选择一起去FB去,元旦FB的估计会比较多,Bestcomy已经订好位子了,呵呵。FB采用AA制:-) 还没有报名的抓紧时间了哦,呵呵。 本周六(2005年1月1日)下午2:00-4:30在中央民族大学16号楼...[阅读全文]

posted @ | Feedback (25) | Filed Under [ 生活 ]

摘要: 博客园&博客堂 北京聚会 定于本周六(2005年1月1日)下午2:00-4:30在中央民族大学16号楼举行,如果你不知道如何到达,请至图行天下查询。另外,请大家就附件中的参与人员提出你希望其就某一方面做技术演讲的申请,发送邮件给我,我会通知当事人,当然可能无法一一满足,希望大家谅解。同时你如果希望给大家讲一讲你所了解的技术,也请告诉我主题,便于我安排会议的进程。希望大家积极参与,主动发言。 请大家转告大家,如果还有报名的同学,请抓紧时间,发送邮件到bestcomy@hotmail.com。 注:请大家查收邮件,参会人员在附件中,排名不分先后.之所以选择学校是大家就不用掏钱了,教室的环境也不错,有电脑和投影仪. 链接:《博客园 & 博客堂 计划在北京联合聚会》...[阅读全文]

posted @ | Feedback (8) | Filed Under [ 生活 ]

摘要:征得dudu 和 开心就好 的同意,本次发起的博客园北京用户聚会决定采取 博客园 & 博客堂 联合在北京举办的形式进行,因为 开心 没有时间组织,博客堂方面委托 宝玉 代为协助组织。 再次请 博客园 和 博客堂 北京用户踊跃参与本次活动,这可是一次难得的机会哦。下一步:首先,统计参加人员。请愿意参加的人员发邮件到bestcomy@hotmail.com,注明你真实姓名,是否愿意向参与聚会的人员透露你的联系方式,博客的url,联系方式(手机,电子邮件),你所研究或者应用的技术领域,是否愿意做主题技术发言及发言内容。 开心 说如果参与人数较多,会为大家介绍Team System的一个实际的Demo。 公布参与人员信息(不包括联系方式)参与人员可请求另外一部分人员就某个技术问题进行讲解,发邮件到我邮箱告知,我再与当事人联系,涉及到商业或者其他地三方利益的,被请求人可以拒绝。 确定议题 最后确定聚会时间及地点。 相关链接: 博客园发的贴子时间过与仓促,北京博客园用户聚会推迟到下周进行关于博客园北京用户聚会的提议 ...[阅读全文]

posted @ | Feedback (16) | Filed Under [ 生活 ]

摘要:在Asp.Net中使用定时器,破宝之前已有Blog写过《在 ASP.NET 中使用计时器(Timer)》,这里主要针对Asp.Net Forums来说一下其具体实现。 在Asp.Net Forums中,对定时器有如下应用:1. 更新论坛统计信息2. 定时索引指定条数的帖子3. 定时群发队列中的邮件 Forums中对定时器的调用是放在自定义HttpModule的Init方法中(如果您没有使用HttpModule,也可以在Globals.aspx中的Application_OnStart 中调用定时器)。         // 定时器         static Timer statsTimer;         static Timer emailTimer;         // 定时间隔         private long EmailInterval = ForumConfiguration.GetConfig().ThreadIntervalEmail * 60000;         private long StatsInterval = ForumConfiguration.GetConfig().ThreadIntervalStats * 60000;         public String ModuleName {              get { return "ForumsHttpModule"; }          }             // *********************************************************************         //  ForumsHttpModule         //         /**//// <summary>         /// Initializes the HttpModule and performs the wireup of all application         /// events.         /// </summary>         /// <param name="application">Application the module is being run for</param>         public void Init(HttpApplication application) {              // Wire-up application events             //             // 略去其他代码                          ForumConfiguration forumConfig = ForumConfiguration.GetConfig();             // 如果使用定时器并且定时器还没初始化             if( forumConfig != null             &&  forumConfig.IsBackgroundThreadingDisabled == false ) {                 if (emailTimer == null)                     // 新建定时器                     // 新建一个TimerCallback委托,具体要执行的方法在ScheduledWorkCallbackEmailInterval中                     emailTimer = new Timer(new TimerCallback(ScheduledWorkCallbackEmailInterval), application.Context, EmailInterval, EmailInterval);                 if( forumConfig.IsIndexingDisabled == false                  &&    statsTimer == null ) {                     statsTimer = new Timer(new TimerCallback(ScheduledWorkCallbackStatsInterval), application.Context, StatsInterval, StatsInterval);             }         }         }         /**//// <summary>         /// 释放定时器         /// </summary>         public void Dispose() {             statsTimer = null;             emailTimer = null;         }         Timer Callbacks#region Timer Callbacks         /**//// <summary>         /// 定时发送队列中待发送的邮件         /// </summary>         private void ScheduledWorkCallbackEmailInterval (object sender) {             try {                 // 当处理邮件时暂停定时器                 emailTimer.Change( System.Threading.Timeout.Infinite, EmailInterval );                 // 发送队列中的邮件                 //                 Emails.SendQueuedEmails( (HttpContext) sender);                 // 更新匿名用户                 //                 Users.UpdateAnonymousUsers( (HttpContext) sender);             }             catch( Exception e ) {                 ForumException fe = new ForumException( ForumExceptionType.EmailUnableToSend, "Scheduled Worker Thread failed.", e );                 fe.Log();             }             finally {                 // 重新启动定时器                 emailTimer.Change( EmailInterval, EmailInterval );             }         }         /**//// <summary>         /// 定时索引帖子和定时更新论坛统计信息         /// </summary>         private void ScheduledWorkCallbackStatsInterval(object sender) {             try {                 // 休眠定时器                 statsTimer.Change( System.Threading.Timeout.Infinite, StatsInterval );                 // 每次索引100篇帖子                 //                 Search.IndexPosts( (HttpContext) sender, 100); ......[阅读全文]

posted @ | Feedback (15) | Filed Under [ CnForums ]

摘要:前面在《Asp.Net Forums中对.Net中序列化和反序列化的应用》一文中讲了,对于一些扩展属性,可以将字符串集合序列化为二进制,也可以从二进制反序列化为字符串集合。其实我一直有个疑问,对于asp.net中可以很容易实现,但是在asp中该如何? 在CS和DNN3中都采用了asp.net2.0的新特性MemberShip,今天研究了一下CSBeta2,特地研究了一下MemberShip中对于用户资料的序列化保存。发现在aspnet_Profile表中有三个特殊字段PropertyNames、PropertyValuesString和PropertyValuesBinary,其中的PropertyValuesBinary十之八九就是保存序列化为二进制后的内容。对于PropertyNames、PropertyValuesString这两个字段倒是不知道,打开查看,发现其中一条记录这两个字段的内容分别为下面两行的内容: publicEmail:S:0:0:yahooIM:S:0:0:timezone:S:0:1:birthdate:B:0:-1:gender:S:1:6:location:S:7:0:fontsize:S:7:1:signature:S:8:0:dateFormat:S:8:10:webLog:S:18:7:enablePostPreviewPopup:B:0:-1:language:S:25:5:interests:S:30:0:occupation:S:30:0:webAddress:S:30:7:icqIM:S:37:0:aolIM:S:37:0:signatureFormatted:S:37:0:msnIM:S:37:0: 8NotSet0MM-dd-yyyyhttp://zh-CNhttp:// 借助Reflector分析了一下源码,终于明白了,原来在PropertyNames字段中,由“:”分割为若干个数组,其中每个属性占数组的4项(如publicEmail:S:0:0:为一个属性的整体):第1项为属性名称第2项有两种可能值,B表示该属性值为null,S表示不为null第3项表示在PropertyValuesString字段中字符串的起始位置第4项表示长度那么publicEmail:S:0:0:就表示为空值,timezone:S:0:1:表示“8NotSet0MM-dd-yyyyhttp://zh-CNhttp://“中从0开始取1个字符长度为“8”,birthdate:B:0:-1:就表示为null,dateFormat:S:8:10:就表示取“8NotSet0MM-dd-yyyyhttp://zh-CNhttp://”中第8位开始取10个字符为“MM-dd-yyyy”…… 通过这种序列化为字符串的方式,即使是一些弱语言,如vbscript,jscript都可以实现序列化和反序列化了,那么在asp中也就可以共享asp.net的MemberShip了。 贴两段核心代码参考一下: internal static void PrepareDataForSaving(ref string allNames, ref string allValues, ref byte[] buf, bool binarySupported, SettingsPropertyValueCollection properties, bool userIsAuthenticated) {       StringBuilder builder1 = new StringBuilder();       StringBuilder builder2 = new StringBuilder();       MemoryStream stream1 = binarySupported ? new MemoryStream() : null;       try       {             bool flag1 = false;             foreach (SettingsPropertyValue value1 in properties)             {                   if (!value1.IsDirty)                   {                         continue;                   }                   if (userIsAuthenticated || ((bool) value1.Property.Attributes["AllowAnonymous"]))                   {                         flag1 = true;                         break;                   }             }             if (!flag1)             {                   return;             }             foreach (SettingsPropertyValue value2 in properties)             {                   if (!userIsAuthenticated && !((bool) value2.Property.Attributes["AllowAnonymous"]))                   {                         continue;                   }                   if (value2.IsDirty || !value2.UsingDefaultValue)                   {                         int num1 = 0;                         int num2 = 0;                         string text1 = null;                         if (value2.Deserialized && (value2.PropertyValue == null))                         {                               num1 = -1;                         }                         else                         {                               object obj1 = value2.SerializedValue;                               if (obj1 == null)                               {                                     num1 = -1;                               }                               else                               {                                     if (!(obj1 is string) && !binarySupported)                                     {                                           obj1 = Convert.ToBase64String((byte[]) obj1);                                     }                                     if (obj1 is string)                                     {                                           text1 = (string) obj1;                                           num1 = text1.Length;                                           num2 = builder2.Length;                                     }                                     else                                     {                                           byte[] buffer1 = (byte[]) obj1;                                           num2 = (int) stream1.Position;                                           stream1.Write(buffer1, 0, buffer1.Length);                                           stream1.Position = num2 + buffer1.Length;                                           num1 = buffer1.Length;                                     }                               }                         }                         string[] textArray1 = new string[8] { value2.Name, ":", (text1 != null) ? "S" : "B", ":", num2.ToString(CultureInfo.InvariantCulture), ":", num1.ToString(CultureInfo.InvariantCulture), ":" } ;                         builder1.Append(string.Concat(textArray1));                         if (text1 != null)                         {                               builder2.Append(text1);                         }                   }             }             if (binarySupported)             {                   buf = stream1.ToArray();             }       }       catch       {             throw;       }       finally       {             if (stream1 != null)             {                   stream1.Close();             }       }       allNames = builder1.ToString();       allValues = builder2.ToString(); } internal static void ParseDataFromDB(string[] names, string values, byte[] buf, SettingsPropertyValueCollection properties) {       for (int num1 = 0; num1 < (names.Length / 4); num1++)       {......[阅读全文]

posted @ | Feedback (15) | Filed Under [ Web技术 ]

摘要:几个月前,写过一篇关于Asp无组件上传带进度条的Blog,当时主要分析了一下通过Web文件上传并在后台获取分析数据的实现原理。其中实现进度条的根本就是要实现分块获取数据,根据分块大小和块数记录已上传大小。还有一些具体的细节问题当时并没有说清楚: Q: 进度信息如何访问?A: 进度信息保存在Application中,每次上传时生成一个进度ID,根据这个进度ID可以检索Application中的当前上传进度信息。 Q: 进度信息以什么形式保存在Application中?A: Asp太弱了,我分别试过Scripting.Dictionary和XMLDom,但是Asp中Application不能保存这种对象,要是asp.net就直接可以用Hashtable了。最后是在Application中用一个ADODB.Recordset对象来保存进度相关信息。 Q: 怎么保证的页面能即时反应显示进度条信息?A: 文件开头加上<%@enablesessionstate=false%>声明来关闭会话状态要保证禁用缓存: Response.CacheControl = "no-cache" Response.Expires = -1 Q: 可以上传多大文件?A: 这个和网速,服务器内存等多方面因素有关,将Server.ScriptTimeout设置足够长,那么理论上可以和服务器保持连接很长时间。因为在asp中,不能实现对文件的“追加”写入,必须将所有待写入文件的数据都先保存在内存,这样如果上传大文件,那么将很占用服务器内存(文本文件可以使用TextStream.Write追加写入)。在asp.net下就比较爽了,分块读取的时候,每读一块分析一块,然后将上传文件的数据内容“追加”写入硬盘文件中,对内存占用很小很小。一般几十MB的文件还是没问题,太大的上传其实对于web下也不是很有意义。 写了一个比较完善的实例,可以直接下载使用: 演示下载...[阅读全文]

posted @ | Feedback (74) | Filed Under [ Web技术 ]

摘要:在Forums中,有些内容是不固定的,例如用户资料,除了一些基本资料,可能还要有一些其他资料信息,例如MSN、个人主页、签名档等,一般对于这样的都是每一个属性对应于数据库中的一个字段。但是如果以后我们因为需要增加一些属性,例如QQ号、Blog地址等,如果还是用这种增加数据表字段的方法,那么将会频繁的修改数据库表结构、存储过程、数据库访问的程序。 或许您也遇到过类似问题,看Forums中是怎么借用.Net的序列化和反序列化来解决的:例如我需要在用户资料里面增加QQ号这个属性,那么我只需要在User类中增加一个属性public String QQIM {    get { return GetExtendedAttribute("QQIM"); }    set { SetExtendedAttribute("QQIM", value); }}不需要修改数据库表结构,不需要修改存储过程,连数据库访问的程序都不需要动。 其具体实现的主要代码: // 首先新建在User类中新建一个NameValueCollection对象,将这些扩展属性都保存在NameValueCollection对象中 NameValueCollection extendedAttributes = new NameValueCollection(); // 从NameValueCollection集合中取纪录 public string GetExtendedAttribute(string name)     {     string returnValue = extendedAttributes[name];     if (returnValue    == null)     return string.Empty;     else     return returnValue; } // 设置扩展属性的在NameValueCollection中的键值和值 public void SetExtendedAttribute(string    name, string value)     {     extendedAttributes[name] = value; } // 将extendedAttributes对象(前面定义的用来保存所有的用户扩展信息的NameValueCollection对象)序列化为内存流 // 可以用来保存到数据库中 public byte[] SerializeExtendedAttributes()     {     // 序列化对象     BinaryFormatter    binaryFormatter    = new BinaryFormatter();     // 创建一个内存流,序列化后保存在其中     MemoryStream ms    = new MemoryStream();     byte[] b;     // 将extendedAttributes对象(里面保存了所有的用户扩展信息)序列化为内存流     //     binaryFormatter.Serialize(ms, extendedAttributes);     // 设置内存流的起始位置     //     ms.Position    = 0;              // 读入到 byte 数组     //     b =    new    Byte[ms.Length];     ms.Read(b, 0, b.Length);     ms.Close();     return b; } // 反序列化extendedAttributes对象的内容 // 从数据库中读取出来的 public void DeserializeExtendedAttributes(byte[] serializedExtendedAttributes)  {     if (serializedExtendedAttributes.Length    == 0)     return;     try         {     BinaryFormatter    binaryFormatter    = new BinaryFormatter();     MemoryStream ms    = new MemoryStream();     // 将 byte 数组到内存流     //     ms.Write(serializedExtendedAttributes, 0, serializedExtendedAttributes.Length);     // 将内存流的位置到最开始位置     //     ms.Position    = 0;     // 反序列化成NameValueCollection对象,创建出与原对象完全相同的副本     //     extendedAttributes = (NameValueCollection) binaryFormatter.Deserialize(ms);     ms.Close();     }      catch    {}      } 实质上序列化机制是将类的值转化为一个一般的(即连续的)字节流,然后就可以将该流保存到数据库的某个字段中(在数据库中forums_UserProfile表中有一个字段“StringNameValues varbinary(7500)”)。读取的过程对对象进行反序列化时,创建出与原对象完全相同的副本。 注意一般这类属性在数据库中是不能被检索到的,并且要这些属性能被序列化。 更详细内容请查阅MSDN和Asp.Net Forums源码...[阅读全文]

posted @ | Feedback (41) | Filed Under [ CnForums ]