摘要: 我的上篇博客【我心目中的Asp.net核心对象】 讲述了一些我认为在Asp.net中比较重要的核心对象,以及演示了直接使用它们也能实现一个简单的服务响应。今天,我将继续把我认为Asp.net的另一些重要的内容拿出来与大家一起分享, 同时将使用本次所讲述的内容改进上篇博客所演示的那个简单的服务,让它成为一个真正能用的服务框架。 在这篇博客中,不仅会继续演示上次提到的三个核心对象,我还会再引入另二个关键对象,我将用更多实战代码来演示它们如何在一起协同工作,来完成许多常见任务,展现它们的精彩故事,也最终会让它们来实现我的服务框架。因此,这篇博客不仅仅是针对Asp.net的基础技术的讲触,而是更多地以阅读全文
posted @ 2011-09-05 23:28 JV Studio 阅读(12) 评论(0) 编辑

现在的web应用越来越复杂,需要响应各种各样的用户触发事件,因而也就不可避免的,需要给我们的html页面上的dom元素增加事件监听函数.

我们知道给dom元素绑定事件监听函数的方法有如下3种:

1 :  页面html:

<button onclick=”test();”></button>
 

2:  页面html:

<button id=”btn”></button>

 Javascript:

document.getElementById(“btn”).onclick = test;

 3:   页面html:

<button id=”btn”></button>

 Javascript:

document.getElementById(“btn”).atachEvent(“onclick”,test); //ie

这3种方法的功能效果和差异,大家都了解,在此就不在赘述了,但是这3种方法,对页面渲染的速度,资源的消耗,却是有很大不同的.

正文后面的html代码是一个demo页面,大家可以用ie浏览器打开,通过注释不同的代码段,查看页面运行效果.

可以看到第一种方式的效率是最低的,随着页面节点的增多,页面渲染时间急剧增加,在ie7下运行,大概670ms;

第二种方式明显好一些,在ie7下,大概250ms

而第三种方式则是最快的方法,也是web前端开发推荐的标准写法,在ie7下,大概188ms;

然后我们去掉事件绑定的逻辑,发现只渲染dom元素,不绑定事件的时间,仅仅125ms,可见事件绑定的时间消耗还是很大的 ,尤其是第一种方式,也就是Dom Level 0 Event,最为耗时.

另外,大家运行各段代码的时候,不妨打开任务管理器,找到浏览器对应的进程,查看代码运行时cpu的消耗以及内存的使用.

我们可以看到,Dom Level 0 Event,对cpu的消耗明显要高很多.

对内存的消耗分析:

重新打开浏览器,空白页面的内存占用量大概是37M,虚拟内存为28M,页面渲染后:

1        内存使用 54M,虚拟内存41M

2        内存使用44M,虚拟内存31M

3        内存使用44M,虚拟内存31M

可见Dom Level 0 Event对内存的消耗,也远远超出了其它方式.

为什么Dom Level 0 Event会这么消耗系统资源呢?对cpu和内存的消耗都远远超出了其它方式.我们来做一个简单分析.

为了便于分析,我们不妨修改一下我们的代码  <button onclick=”debugger;test();”></button> ,然后运行页面,在ie的script debugger里我们找到堆栈调用这一项,可以看到有一个anonymos function,这个function是从何而来的呢.原来浏览器在对Dom Level 0 Event做绑定的时候,会自动生成一个包含我们的代码的匿名函数,然后把这个匿名函数绑定到事件.类似于如下方式:

document.getElementById(“btn”).onclick = function(event){

        test();

} ;

而ie浏览器又没有足够的智能,区分出众多内部功能完全一致的匿名函数并合并它们的引用,所以导致了随着dom事件绑定的越来越多,匿名函数的个数也越来越多.因为要声明数量众多的事件处理匿名函数,也就不难明白,为什么会消耗如此多的系统资源了.

随着dom元素的增多,这个资源消耗就会越来越严重.而且我们可以尝试着刷新一下页面,发现随着刷新的次数增加,页面运行越来越慢,cpu消耗也越来越多,内存也会有少量增加.可见,Dom Level 0 Event 还会带来少量的内存泄露.至于时间的延长,cpu消耗的加聚,推测是因为浏览器忙于释放众多的匿名函数所占用的资源所带来的后果.

进一步深入,由于ie浏览器是基于冒泡的事件模型,子元素的event会冒泡到父元素,所以更极致的优化,是去掉众多子元素的事件绑定,而将事件绑定到父元素,在正文后的demo中,也有这方面的尝试,可以看到不仅cpu,内存消耗最低,时间上也跟渲染干净的html页面是一样的.

所以我们在页面事件绑定中,要尽量避免Dom Level 0 Event,而且要尽可能的将事件上升.(当然也要考虑事件处理的灵活性).

demo:

<BODY>
<ul id="list"></ul>
<SCRIPT LANGUAGE="JavaScript">
<!--
var $ = function(id){
return document.getElementById(id)
};
function test(){
alert(
1)
}
var ul = $("list");
var count = 5000;
// ie7
//-->
</SCRIPT>
<script>
var d = new Date()
var str = [];
for(var i = 0;i<count;i++){
str.push(
'<li onclick="test();">'+i+'</li>')
}
ul.innerHTML
= str.join("");
alert(
new Date - d);
//670 刷新时时间增加 85
</script>
<SCRIPT LANGUAGE="JavaScript">
<!--
/*var d = new Date()
var str = [];
for(var i = 0;i<count;i++){
str.push('<li>'+i+'</li>')
}
ul.innerHTML = str.join("");
alert(new Date - d);
*/
//125
//-->
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
<!--
/*var d = new Date()
var str = [];
for(var i = 0;i<count;i++){
str.push('<li>'+i+'</li>')
}
ul.innerHTML = str.join("");
var li = document.getElementsByTagName("li");
var l = li.length;
for(var i=0;i<l;i++){
li[i].onclick = test;
}
li = null;
alert(new Date - d);
*/
//250
//-->
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
<!--
/*var d = new Date()
var str = [];
for(var i = 0;i<count;i++){
str.push('<li>'+i+'</li>')
}
ul.innerHTML = str.join("");
var li = document.getElementsByTagName("li");
var l = li.length;
for(var i=0;i<l;i++){
li[i].attachEvent("onclick",test);
}
li = null;
alert(new Date - d);
*/
//188
//-->
</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
<!--
/*var d = new Date()
var str = [];
for(var i = 0;i<count;i++){
str.push('<li>'+i+'</li>')
}
ul.innerHTML = str.join("");
ul.attachEvent("onclick",test);
alert(new Date - d);
*/
//125
//-->
</SCRIPT>
</BODY>
posted @ 2011-04-16 15:17 JV Studio 阅读(36) 评论(1) 编辑
近在公司某管理系统中,用了一些独立的模块,在这些类的实现中,错误是直接抛出异常的,我想这是我们通常的做法。然而,问题也来了,由于自己在Asp.net页面中没有去捕获这些异常,并且多处页面中都使用了这些类,于是在多个页面都会出现不友好的错误提示信息。

怎么办?又不想一处一处修改代码,既费时又费力,这样编程不就变成了体力劳动,从而失去了乐趣。 这时让我想起了自定义错误页,于是Google,终于找到了答案。

1、配置web.config:

<customErrors mode="RemoteOnly" defaultRedirect="ErrorPage.aspx" redirectMode="ResponseRewrite"/>
 关键是redirectMode属性,该属性默认为ResponseRedirect,由于被Redirect了,异常也就被忽略了,使你无法捕获到异常。这里罗嗦一句:因为出错前后被认为是两次请求,我们知道http协议是一种无状态的协议,第二次请求忽略了第一次的异常也就不奇怪了。于是有人用了Session或Application来保存异常,这是不可取的。正确的做法是使用“ResponseRewrite"。

 

2、输出异常信息:

 我们知道网站出错时,会自动导向我们的ErrorPage.apx页面,在ErrorPage.aspx中如何访问这个异常呢?答案是:Server.GetLastError(),当然有可能是Server.GetLastError().InnerException。这要具体分析了。

if(Server.GetLastError()!=null){
   Response.Write(Server.GetLastError().Message);
}

 

顺便说一下:

Asp.net MVC中就简单多了,框架自带了一个Error.aspx,异常保存在Model.Exception中,并且Web.config中也为我们配置好了。

在下从去年以来开发的网页就基本是MVC的了,结构清晰,扩展方便,清凉的HTML代码输出。有空看看MVC的源代码还是很有帮助的。

posted @ 2011-04-16 14:34 JV Studio 阅读(69) 评论(1) 编辑

服务器上时不时就会出现vsjitdebugger.exe这个进程,还经常是好多一起出现,一旦出现,服务器上运行的软件就不工作了,甚是郁闷!远程桌面到服务器上,能看到每一个进程其实就是一个visual studio的调试窗口,挨个关掉就好了。有没有更好的解决方法呢?

今天上网查了查,终于找到了解决办法,但不知道给程序调试会不会留下什么隐患,后来想想反正服务器上也不做debug,就这样吧。

禁用实时调试:打开VS2005,在“工具”菜单中单击“选项”,选择“调试”文件夹,选择“实时”页,清除相关的程序类型:“托管”、“本机”、“脚本”,单击“确定”。

删除以下注册表项:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]

"Debugger"="C:\WINDOWS\system32\vsjitdebugger.exe" -p %ld -e %ld

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]

"DbgManagedDebugger"="C:\WINDOWS\system32\vsjitdebugger.exe" PID %d APPDOM %d EXTEXT "%s" EVTHDL %d

这样,windows就没有任何调试器了。


如果想恢复原来的调试:
选上相关的程序类型:“托管”、“本机”、“脚本”
或 执行: drwtsn32 -i
posted @ 2011-03-17 10:44 JV Studio 阅读(887) 评论(0) 编辑
SQL code
--你是否有足够的权限?如果有足够的权限,可以备份到本机
--如果有,可以用下面的方法,查询分析器中操作:
-- 创建共享目录
exec master.dbo.XP_cmdshell 'md c:\bak'
exec master.dbo.XP_cmdshell 'net share bak=c:\bak'

--进行数据备份
backup database 数据库 to disk='c:\bak\备份.bak'

/*--以下操作在我的电脑中进行:
   打开我的电脑,地址栏中输入:
   http://www.cnblogs.com/jvstudio/admin/file://\\SQL服务器的计算机名\bak\
   复制里面的备份.bak到你的电脑就行了

--我的电脑中的操作结束--*/

--删除备份生成的文件
exec master..xp_cmdshell 'del c:\bak\备份.bak'

--删除共享
exec master.dbo.XP_cmdshell 'net share c:\bak /delete /y'
exec master.dbo.XP_cmdshell 'rd c:\bak'

--否则,你还是完全共享你本机的目录,用下面的方法备份:
backup database 数据库 to disk='\\你的计算机名\共享目录名\备份文件名'

---或通过映射网络驱动器(这样可以解决权限问题)
--1.映射
exec master..xp_cmdshell 'net use z: \\xz\c$ "密码" /user:xz\administrator'

/*--说明:
z:            是映射网络路径对应本机的盘符,与下面的备份对应
\\xz\c$            是要映射的网络路径
xz\administrator        xz是远程的计算机名,administrator是登陆的用户名
密码                        上面指定的administrator用户的密码
--*/

--2.进行数据库备份
backup database 数据库名 to disk='z:\备份文件名'

--3.备份完成后删除映射
exec master..xp_cmdshell 'net use z: /delete'
posted @ 2011-02-24 13:16 JV Studio 阅读(162) 评论(0) 编辑

在上一篇文章中,为了解决成员访问级别的问题,我采用了一个object adapter,使得客户程序无法轻易地修改对象的属性。网友评论说,我的这种做法就是绕了一圈,的确,这种方法没办法阻止客户程序刻意地去修改对象的属性,但在一定程度上起到了保护作用:至少降低了误操作的可能性。

今天发现其实可以用System.Runtime.CompilerServices.InternalsVisibleToAttribute这个特性达到同样的效果。以下是操作步骤。

  1. 假设ExposedSetter.Library这个class library中包含了一个具有internal setter属性的SourcedAggregationRoot类。首先,对ExposedSetter.Library作数字签名。在ExposedSetter.Library项目上点右键选择“Properties”。在“Signing”页下选择“Sign the assembly”选项,然后指定一个强名称密钥文件。SourcedAggregationRoot的代码以及ExposedSetter.Library的签名设置如下
    隐藏行号 复制代码 代码
    1. public class SourcedAggregationRoot : IVersionControllable
      
    2. {
      
    3.     private long version;
      
    4.     private long branch;
      
    5.     #region IVersionControllable Members
      
    6.     public long Version
      
    7.     {
      
    8.         get { return this.version; }
      
    9.         internal set { this.version = value; }
      
    10.     }
      
    11.     public long Branch
      
    12.     {
      
    13.         get { return this.branch; }
      
    14.         internal set { this.branch = value; }
      
    15.     }
      
    16.     #endregion
      
    17. 
      
    18.     public override string ToString()
      
    19.     {
      
    20.         return string.Format("Version = {0}, Branch = {1}",
      
    21.             version, branch);
      
    22.     }
      
    23. }
      

     image

  2. 新建一个class library,以调用ExposedSetter.Library中SourcedAggregationRoot的internal setter属性。为方便描述,我们将这个class library命名为ExposedSetter.Library2。在这个class library上添加对ExposedSetter.Library的引用,同时随便写一个测试的类,在类里直接调用SourcedAggregationRoot的internal setter属性来设置属性值。
    隐藏行号 复制代码 代码
    1. public class Class1
      
    2. {
      
    3.     public SourcedAggregationRoot Test()
      
    4.     {
      
    5.         SourcedAggregationRoot sar = new SourcedAggregationRoot();
      
    6.         sar.Branch = 125;
      
    7.         return sar;
      
    8.     }
      
    9. }
      

    同样,为ExposedSetter.Library2做数字签名(这一点很重要!)

  3. 启动Visual Studio的Command Line,使用sn.exe获得ExposedSetter.Library2的公共密钥(public key),注意:是public key,而不是public key token
    image
  4. 打开ExposedSetter.Library的AssemblyInfo.cs文件,向其添加InternalsVisibleToAttribute:
    隐藏行号 复制代码 代码
    1. [assembly: InternalsVisibleTo("ExposedSetter.Library2, PublicKey=0024000004800000940000000602000000240" +
      
    2.     "000525341310004000001000100bbccb249a2e7a1" +
      
    3. "7cbddf86e24532777568cb13c2ea7643b61cf60367068f2b9ca785dca303c49f015823e4eaa17b" +
      
    4. "50ed60ac47563dc8d8771358f10c3dc41f288530cfa350e6a2a24781dedeb8ec4138f93e76c537" +
      
    5. "bce6c5aa7b25858fa90d6ef5c6ea613b1b49e6e287f9ebb7f990cfa0ce17fbfe1c338e95e88c14" +
      
    6. "81f9598f")]
      

    注意,InternalsVisibleToAttribute的参数指定了允许访问其internal成员的assembly名称和公共密钥数据。在此不能设置assembly的版本等信息,否则编译都过不去。

  5. 编译解决方案

这种方式有点像C++的友元。与我上文提到的引入object adapter的解决方案相比,这种做法更加professional一些,毕竟可以通过.NET Framework直接支持,而且也更加安全一些,它能够明确指定哪些assembly可以访问,其余的则不能访问。但这种做法也有弊端:假设我今后又有一个assembly希望使用ExposedSetter.Library中的internal成员,我需要去修改ExposedSetter.Library中的代码,以添加一个InteralsVisibleToAttribute特性。

 

转帖地址:http://www.cnblogs.com/daxnet/archive/2010/08/12/1797782.html

posted @ 2010-08-12 09:24 JV Studio 阅读(39) 评论(0) 编辑

  几个月来,疑被SOA,一直在和XML操作打交道,SQL差不多又忘光了。现在已经知道,至少有四种常用人XML数据操作方式(好像Java差不多),不过还没有实际比较过这些方式各有哪些特点或优劣。正好看到网上也没有这方面的实验,偶来总结一下。

  测试开始先读取XML源,用一个比较大的RSS文件链接,复制到项目bin/debug目录下。

Stream xmlStream = new MemoryStream(File.ReadAllBytes(path));

    

  一、XmlDocument 方式

代码

 

  二、XPathNavigator 方式

代码
1 static IList testXmlNavigator()
2 {
3 var doc = new XmlDocument();
4 doc.Load(xmlStream);
5 var nav = doc.CreateNavigator();
6 nav.MoveToRoot();
7 var nodeList = nav.Select("/channel/item");
8 var lstChannel = new List<Object>(nodeList.Count);
9 foreach (XPathNavigator node in nodeList)
10 {
11 var channel = new
12 {
13 Title = node.SelectSingleNode("title").Value,
14 Link = node.SelectSingleNode("link").Value,
15 Description = node.SelectSingleNode("description").Value,
16 Content = node.SelectSingleNode("content").Value,
17 PubDate = node.SelectSingleNode("pubDate").Value,
18 Author = node.SelectSingleNode("author").Value,
19 Category = node.SelectSingleNode("category").Value
20 };
21 lstChannel.Add(channel);
22 }
23 return lstChannel;
24 }

 

  三、XmlTextReader 方式

代码

 

  四、Linq to XML 方式

代码

 

  测试结果:

XmlDocment 47ms
XPathNavigator 42ms
XmlTextReader 23ms
Xml Linq 28ms

 

  小结一下自己的认识,XmlDocument的操作基本按W3C的DOM操作方式,不过要将全部节点解析成对象加载到内存中,往往造成很大浪费。所以微软自己的编程规范也不推荐用它。这里由于读取了所有节点,可能因此性能和Navigator方式相差不大。在三种随机读取方式中,Xml Linq性能最高,只是方法名有点别扭。XmlTextReader方式是所谓的SAX,只读向前,无疑性能最高,不过实现上麻烦了不少,要比较精确的控制访问逻辑,也无法用匿名类存储数据。

  .Net 3.5发布Xml Linq可以很好地取代前两种方式,通常情况下,最好用它。只有个别场合,如果对性能要求极高,或者读取Xml数据量太大不能一下子下载或读取到内存中,那就只好痛苦委身于XmlTextReader了。

 

转帖地址:http://www.cnblogs.com/XmNotes/archive/2010/08/12/1796162.html

posted @ 2010-08-12 09:19 JV Studio 阅读(20) 评论(0) 编辑
摘要: using System; using System.IO; using System.Web; using System.Drawing; //GIF验证码类 public class Validate { //设置最少4位验证码 private byte TrueValidateCodeCount = 4; public byte ValidateCodeCount { get { r...阅读全文
posted @ 2010-07-17 14:42 JV Studio 阅读(336) 评论(1) 编辑
摘要: Uploadify是JQuery的一个上传插件,实现的效果非常不错,带进度显示。不过官方提供的实例时php版本的,本文将详细介绍 Uploadify在Aspnet中的使用。  首先按下面的步骤来实现一个简单的上传功能。  1 创建Web项目,命名为JQueryUploadDemo,从官网上下载最新的版本解压后添加到项目中。  2 在项目中添加UploadHandler.ashx文件用来处理文件的上...阅读全文
posted @ 2010-07-13 13:41 JV Studio 阅读(40) 评论(0) 编辑
摘要: 前言本文是我对ASP.NET页面载入速度提高的一些做法,这些做法分为以下部分:1.采用 HTTP Module 控制页面的生命周期。2.自定义Response.Filter得到输出流stream生成动态页面的静态内容(磁盘缓存)。3.页面GZIP压缩。4.OutputCache 编程方式输出页面缓存。5.删除页面空白字符串。(类似Google)6.完全删除ViewState。7.删除服务器控件生成...阅读全文
posted @ 2010-07-13 13:40 JV Studio 阅读(16) 评论(0) 编辑