[WEB]提高网站性能之 —— 减少图片HTTP请求的方案

mikel阅读(483)

转载:http://www.cnblogs.com/xugang/archive/2009/10/26/1589934.html

当一个页面的图片在没有使用任何方案的情况下,五个图片超链接就只能使用五个图标按钮。
代码如下:

<div style="border: 2px ridge rgb(51, 51, 51); background-color: rgb(244, 245, 235); width: 200px; padding-top: 4px;">
<center>         <href="JavaScript:alert('Home')" title="Home"><img src="http_request_img/home.gif" border="0"></a>
<href="JavaScript:alert('Gift')" title="Gift"><img src="http_request_img/gift.gif" border="0"></a>
<href="javascript:alert('Cart')" title="Cart"><img src="http_request_img/cart.gif" border="0"></a>
<href="javascript:alert('Settings')" title="Settings"><img src="http_request_img/settings.gif" border="0"></a>
<href="javascript:alert('Help')" title="Help"><img src="http_request_img/help.gif" border="0"></a>
</center>
</div>

效果如下:

注意:这五个按钮分别使用了五张图片

 

那么,五张图片就意味着你的该页面又多了五个HTTP请求,它将大大降低页面的呈现效率。增加的HTTP请求是导致页面性能下降的最大刽子手,所以我们应该尽量减少HTTP请求,而图片是增加HTTP请求的最大可能者,搞定它,事不宜迟!呵呵^_^

下面列出了三种解决方案:

 

方案一:图片地图(图像热点):它将用户的点击映射到一个操作,而无需向后端Web服务器发送任何请求。

代码如下:

<div class="panel_div" style="border:2px ridge #333333;background-color:rgb(244, 245, 235);width:180px;padding:4px 0px 0px 2px;">
     
<img usemap="#mymap" src="http_request_img/imagemap.gif" border="0" />
     
<map name="mymap"> <!– img使用的map –>
         
<area shape="rect" coords="0,0,31,31" href="javascript:alert('Home');"/>
         
<area shape="rect" coords="36,0,66,31" href="javascript:alert('Gifts');"/>
         
<area shape="rect" coords="71,0,101,31" href="javascript:alert('Cart')"/>
         
<area shape="rect" coords="106,0,136,31" href="javascript:alert('Set')"/>
         
<area shape="rect" coords="141,0,171,31" href="javascript:alert('Help')"/>
     
</map>
</div>

效果如下:

注意:这五个按钮其实是在一张图片中

 

方案二:CSS Sprites:使用这种方式也可以将五张图片合并为一张图片,并且更为灵活。

代码如下:

<style>
/* 对div中所有span的样式设置 */
#navbar span 
{
  
/* 定义<span>标签将截取的图片宽度和高度 */
  width
:30px; height:31px;
  
/* 添加包含了所有图标的图片 */
  background-image
:url(http_request_img/imagemap.gif);
  display
:inline; float:left;
}
 
/* background-position:指定图标在CSS Sprites图片的偏移量
    margin-left 和 margin-right 则用来定位图标位置
 
*/
.home     
{ background-position:0 0; margin-left:2px;}
.gifts    
{ background-position:-35px 0; margin-left:50px;}
.cart     
{ background-position:-70px 0; margin-left:120px;}
</style>
<div id="navbar" style="border: 2px ridge rgb(51, 51, 51); padding: 4px 0pt; background-color:#ff0; width: 300px; height: 32px;">
  
<href="javascript:alert('Home')" title="Home">
     
<span class="home"></span></a> <!– 注意:该span标签用来加载图片 –>
  
<href="javascript:alert('Gifts')" title="Gifts">
    
<span class="gifts"></span></a> <!– 注意:该span标签用来加载图片 –>
  
<href="javascript:alert('Cart')" title="Cart">
    
<span class="cart"></span></a>  <!– 注意:该span标签用来加载图片 –>
</div>

效果如下:

注意:在这个“CSS Sprites”中用到的图片就是“图片地图”中的同一张图片。(并特地只显示其中的三个图标)

 

CSS Sprites的原理:只是定位到图片其中的一块区域,并显示在某个位置而已。

CSS Sprites的优点:通过只使用一个图片减少了HTTP请求,并且比“图片地图”更灵活。

很多人会误认为:合并的图片要比分离的图片的总和要大,因为合并的图片中包含有附加的空白区域。
实际上,合并的图片要比分离的图片的总和要小,这是因为它降低了图片自身的开销(颜色表、格式信息,等等)。

 

方案三:内联图片:通过使用data: URL模式在Web页面中包含图片,且无需任何额外的HTTP请求。(IE目前不支持)

      1、内联图片的原理:允许将小块数据内联为‘立即数(immediate data)’,数据就包含在其URL自身之中。

      2、内联图片的格式:data:[<mediatype>][;base64],<data>

举例:一个内联图片可以定义为
<img src="data:image/gif;base64,asdfghjklaasdvdddddddaaaaaddddd++ddd======ssswdvdv33" >

其中“asdfghjklaasdvdddddddaaaaaddddd++ddd======ssswdvdv33”就是该图片的数据。

data: URL模式-> 基本用于内联图片,可以用在任何需要指定URL的地方,如:script和a标签中。

 

      3、内联图片的缺陷

            a> 不受IE的支持(IE7也如此);

            b> 保存数据的大小上受限制(Firefox 1.5支持高达100KB的数据);

            c> Base64编码会增加其图片的大小;

            d> 在跨越不同页面时不会被缓存

              (可以将内联图片作为背景图片保存在外部CSS样式表中来解决此问题,但会增加一个HTTP请求以换得数据被缓存的结果。);

 

在PHP技术中,使用函数file_get_contents从磁盘读取图片并插入到页面中来创建内联图片:

在其HTML中,使用style标签的href属性指定外部样式表文件时,直接指定到了一个PHP模版的.php文件(注意:不是.css文件),该PHP模版使用file_get_contents函数生成其样式表:

.home{ background-image:url(data:image/gif;base64,<?php echo base64_encode(file_get_contents("../img/home.gif")) ?>);}

其最终数据将是base64编码格式的图片data数据。

当然,使用ASP.NET技术生成其base64编码格式的图片data数据也不会很难。大家可以自行实验。

 

本人推荐:根据具体情况,使用方案一:图片地图(图像热点)方案二:CSS Sprites

 

附加知识:URL中的相关协议:http:、data:、file:、ftp:、mailto:、smtp:、pop:、dns:、whois:、finger:、daytime:、news:、urn: 等。这其中有一些是官方注册的,还有一些是由于广泛使用而被接受。

[SQL]Select 语句查询原理

mikel阅读(664)

我并非专业DBA,但做为B/S架构的 开发人员,总是离不开数据库,一般开发员只会应用SQL的四条经典语句:select ,insert,delete,update。但是我从来没有研究过它们的工作原理,这篇我想说一说select在数据库中的工作原理。B/S架构中最经 典的话题无非于三层架构,可以大概分为数据层,业务逻辑层和表示层,而数据层的作用一般都是和数据库交互,例如查询记录。
      我们经常是写好查询SQL,然后调用程序执行SQL。但是它内部的工作流程是怎样的呢?先做哪一步,然后做哪一步等,我想还有大部分朋友和我一样都不一定清楚。 
    第一步:应用程序把查询SQL语句发给服务器端执行。
                我们在数据层执行SQL语句时,应用程序会连接到相应的数据库服务器,把SQL语句发送给服务器处理。
    第二步:服务器解析请求的SQL语句。
                1:SQL计划缓存,经常用查询分析器的朋友大概都知道这样一个事实,往往一个查询语句在第一次运行的时候需要执行特别长的时间,但是如果你马上或者在一定时间内运行同样的语句,会在很短的时间内返回查询结果。   
                原因:
                    1):服务器在接收到查询请求后,并不会马上去数据库查询,而是在数据库中的计划缓存中找是否有相对应的执行计划,如果存在,就直接调用已经编译好的执行计划,节省了执行计划的编译时间。
                    2):如果所查询的行已经存在于数据缓冲存储中,就不用查询物理文件了,而是从缓存中取数据,这样从内存中取数据就会比从硬盘上读取数据快很多,提高了查询效率.数据缓冲存储区会在后面提到。
              2:如果在SQL计划缓存中没有对应的执行计划,服务器首先会对用户请求的SQL语句进行语法效验,如果有语法错误,服务器会结束查询操作,并用返回相应的错误信息给调用它的应用程序。
                注意:此时返回的错误信息中,只会包含基本的语法错误信息,例如select 写成selec等,错误信息中如果包含一列表中本没有的列,此时服务器是不会检查出来的,因为只是语法验证,语义是否正确放在下一步进行。
              3:语法符合后,就开始验证它的语义是否正确,例如,表名,列名,存储过程等等数据库对象是否真正存在,如果发现有不存在的,就会报错给应用程序,同时结束查询。
              4:接下来就是获得对象的解析锁,我们在查询一个表时,首先服务器会对这个对象加锁,这是为了保证数据的统一性,如果不加锁,此时有数据插入,但因为没有加锁的原因,查询已经将这条记录读入,而有的插入会因为事务的失败会回滚,就会形成脏读的现象。
              5:接下来就是对数据库用户权限的验证,SQL 语句语法,语义都正确,此时并不一定能够得到查询结果,如果数据库用户没有相应的访问权限,服务器会报出权限不足的错误给应用程序,在稍大的项目中,往往 一个项目里面会包含好几个数据库连接串,这些数据库用户具有不同的权限,有的是只读权限,有的是只写权限,有的是可读可写,根据不同的操作选取不同的用户 来执行,稍微不注意,无论你的SQL语句写的多么完善,完美无缺都没用。
              6:解析的最后一步,就是确定最终的执行计划。当语法,语义,权限都验证后,服务器并不会马上给你返回结果,而是会针对你的SQL进行优化,选择不同的查询算法以 最高效的形式返回给应用程序。例如在做表联合查询时,服务器会根据开销成本来最终决定采用hash join,merge join ,还是loop join,采用哪一个索引会更高效等等,不过它的自动化优化是有限的,要想写出高效的查询SQL还是要优化自己的SQL查询语句。
            当确定好执行计划后,就会把这个执行计划保存到SQL计划缓存中,下次在有相同的执行请求时,就直接从计划缓存中取,避免重新编译执行计划。
  第三步:语句执行。
              服务器对SQL语句解析完成后,服务器才会知道这条语句到底表态了什么意思,接下来才会真正的执行SQL语句。
  些时分两种情况:
            1):如果查询语句所包含的数据行已经读取到数据缓冲存储区的话,服务器会直接从数据缓冲存储区中读取数据返回给应用程序,避免了从物理文件中读取,提高查询速度。
            2):如果数据行没有在数据缓冲存储区中,则会从物理文件中读取记录返回给应用程序,同时把数据行写入数据缓冲存储区中,供下次使用。
            说明:SQL缓存分好几种,这里有兴趣的朋友可以去搜索一下,有时因为缓存的存在,使得我们很难马上看出优化的结果,因为第二次执行因为有缓存的存在,会特别快速,所以一般都是先消除缓存,然后比较优化前后的性能表现,这里有几个常用的方法:
DBCC DropCLEANBUFFERS
从缓冲池中删除所有清除缓冲区。
DBCC FREEPROCCACHE
从过程缓存中删除所有元素。
DBCC FREESYSTEMCACHE
  从所有缓存中释放所有未使用的缓存条目。SQL Server 2005 数据库引擎会事先在后台清理未使用的缓存条目,以使内存可用于当前条目。但是,可以使用此命令从所有缓存中手动删除未使用的条目。
    这只能基本消除SQL缓存的影响,目前好像没有完全消除缓存的方案,如果大家有,请指教。
    结论:只有知道了服务执行应用程序提交的SQL的操作流程才能很好的调试我们的应用程序。
            1:确保SQL语法正确;
            2:确保SQL语义上的正确性,即对象是否存在;
            3:数据库用户是否具有相应的访问权限。 注:
  本文引用:
http://database.ctocio.com.cn/tips/210/7791210.shtml
http://tech.it168.com/a2008/0805/199/000000199573.shtml

[ORM]实现自己的O/R Mapping组件[二]-高效缓存的思考一

mikel阅读(618)

转载:http://www.cnblogs.com/william_fire/articles/126646.html
       缓存在O/R Mapping组件中是非常重要的,一个比较好的缓存方案,可以大大地提高对象的使用效率,避免内存空间上的浪费。目前需要在构思架构部分,但缓存的实现 方式突然吸引了我,所以就对缓存进行一些思考,并研究了Gentle.NET与NHibernate的实现原理。 [这里的研究基于NHibernate 0.7.0]

NHibernate的实现方案

  在NHibernate上,缓存的机制实现充分考虑了性能与扩展性,它与Gentle.NET在实现不同的是全部是基于Hashtable而 非HybridDictionary。一开始,我看见这样的实现的时候,还误以为,NHibenate过于模仿Java,而没有充分利用.NET的特性, 然而,在仔细分析之后,发现直接使用Hashtable是一个非常好的思路。
  因为在HybridDictionary中,当插入一个新的对象到集合中时,该类会进行一个判断,如果集合中的元素多于9个时,则切换为 Hashtable模式,这看起来非常有意思。但实际上,在O/R Mapping中,集合的数量往往都是比较多的,尤其是在企业应用中,由于网络传输数据的延迟,缓存的实现是一个非常珍贵的资源,它大大的减轻了数据库服 务端的压力。就这个层次上来说,实际上实现ListDictionary并没有太大的意义。
  NHibernate的缓存机制,比起Gentle.NET来说,要复杂一些。NHibernate中,缓存对象的创建实际上通过 CacheFactory产生的。这样做的原因是,在NHibernate中,缓存包括ReadOnlyCache、ReadWriteCache、 NonstrictReadWriteCache这三种缓存管理类,它们都继承自ICacheConcurrencyStrategy接口,可以非常方便 地添加应用了新策略的缓存管理类。
  另外,在NHibernate中,缓存对象的类型也并不是不可变的,在现有的设计上,使用了 HashtableCacheProvider与HashtableCache两个类来描述Provider对象和Cache对象,分别继承于 ICacheProvider与ICache,如下代码所示:

        /// <summary>
        
/// Creates an <see cref="ICacheConcurrencyStrategy"/> from the parameters.
        
/// </summary>
        
/// <param name="usage">The name of the strategy that <see cref="ICacheProvider"/> should use for the class.</param>
        
/// <param name="name">The name of the class the strategy is being created for.</param>
        
/// <param name="mutable"><c>true</c> if the object being stored in the cache is mutable.</param>
        
/// <returns>An <see cref="ICacheConcurrencyStrategy"/> to use for this object in the <see cref="ICache"/>.</returns>

        // was private in h2.1
        public static ICacheConcurrencyStrategy CreateCache( string usage, string name, bool mutable )
        
{
            
if( log.IsDebugEnabled )
            
{
                log.Debug( 
"cache for: " + name + "usage strategy: " + usage );
            }


            ICacheConcurrencyStrategy ccs 
= null;
            
switch( usage )
            
{
                
case CacheFactory.ReadOnly:
                    
if( mutable )
                    
{
                        log.Warn( 
"read-only cache configured for mutable: " + name );
                    }

                    ccs 
= new ReadOnlyCache();
                    
break;
                
case CacheFactory.ReadWrite:
                    ccs 
= new ReadWriteCache();
                    
break;
                
case CacheFactory.NonstrictReadWrite:
                    ccs 
= new NonstrictReadWriteCache();
                    
break;
                
default:
                    
throw new MappingException( "cache usage attribute should be read-write, read-only, nonstrict-read-write, or transactional" );
            }


            
return ccs;

        }

  可以看出,这样的实现是一个非常优秀的设计,意味着非常强大的扩展性与可维护性。
  在NHibernate的缓存方案中,使用了锁模式进行管理,它的实现是模仿操作系统中的“原语”进行的,是一个基于线程安全的实现的方案,具体的管理方式类似PV操作的形式。

[Flash]Flash摄像头游戏课件设计与开发

mikel阅读(604)

转载:http://space.flash8.net/space/?246908/viewspace-452337.html
      【摘 要】摄像头游戏是随着技术的进步产生出来的一种新的游戏形式,它摆脱了鼠标与键盘的限制,给游戏者以全新的互动体验。Flash 8提供的位图处理功能为Flash摄像头游戏的实现提供了可能。将摄像头游戏技术引入到Flash课件的开发,可以充分发挥其互动性和趣味性,与传统 Flash课件相比,具有其不可替代的优势。该文提出设计Flash摄像头游戏课件的基本原则,并以《水果乐园》课件为例,详细介绍了开发的过程和主要实 现方法,为摄像头游戏类课件制作提供了参考。
  【关键词】Flash;摄像头游戏;课件
  【中图分类号】G434【文献标识码】B【论文编号】1009—8097 (2008) 01—0107—05
  
  一 引言
  
   摄像头游戏是随着摄像头的普及和图形图像技术的不断发展而出现的。它摆脱了鼠标键盘的限制,给游戏者带来全新的游戏体验,能够实现许多传统游戏无法实现 的游戏效果。它通过摄像头将玩家投影到游戏中,由玩家自己做动作与游戏进行交互。画面中登场的敌人或道具都将对玩家的动作即刻做出反应,让玩家体验到前所 未有的新鲜感。
  Flash课件是用Flash的形式表现教学内容一种课件形式。Flash课件充分利用了Flash的直观性、互动性以及 娱乐性,能够有效的调动学生的学习积极性,激发学生的学习乐趣,在当前的教学过程中发挥着越来越大的作用。Flash摄像头游戏课件整合了摄像头游戏和 Flash课件的优点,充分体现了“寓教于乐”的教学思想。它带给学生全新的游戏感受,能够极大的激发学生的学习兴趣。它能够激发学生的多种感观刺激,建 立强烈的真实感,通过游戏过程中学生与游戏的互动,还能够促进学生手、耳、眼以及肢体的相互协调,达到较好的教学效果。
  
  二 Flash摄像头游戏课件的设计原则
  
  Flash摄像头游戏课件具有较好参与性、体验性,能够有效增强学习效果,提高学习效率,特别适合于学生动作类技能的训练。在设计的过程中,应遵循如下原则,体现其独特的优势。
  (1)教学性原则
  这是所有课件,应用于教学的最基本的要求,该类课件也不例外,在设计的过程中,必须针对一定的教学目标,遵循认知过程的一般规律,组织教学内容和教学活动。紧密围绕“以学生学习为中心”的设计思路。
  (2)易用性原则
  摄像头游戏课件的交互,计算机对于学习者的动作回应,都是建立在动作检测,捕捉学习者动作影像的基础上。设计过程中应考虑让学习者的操作尽量简便,易于上手使用。做好课件使用的帮助或者使用手册。
  (3)科学性原则
  课件的内容,不能有科学性的错误,这也是设计中基本要求,必须对课件所有呈示的内容,进行严格仔细的审查,保证学生看到的所有知识点,都必须科学、准确,一般由课件开发小组中学科专家把好关。
  (4)艺术性原则
  如果一个课件的展示不但取得良好的教学效果,而日‘使人赏心悦目,使人获得美的享受,则说课件具有较高的艺术性。这样的课件是好的内容与美的形式的统一,美的形式能激发学生的兴趣,史好地表现内容。其表现有:展示的对象结构对称,色彩柔和,搭配合理,有审美性。
  (5)体验性原则
   摄像头游戏课件因其交互的多维化,全方位,检测学习者动作,使得学习者的沉浸感很强,要求学习者的个人形象和课件环境融合的过程中,能让学习能有身临其 境的感觉,所以课件在设计的过程中,注意课件环境,界面的元素,声音的效果,都必然能激发学习者的投入感。该原则是摄像头游戏课件设计过程中最重要的原 则,也是整个课件制作的关键,成败所在。
  
  三 Flash摄像头游戏课件的设计与实现
  
  在儿童英语教学中,引入Flash摄像头游戏课件,使得儿童摆脱键盘和鼠标的单一化的交互方式,而进行身体动作与计算机的交互,增强儿童学习的体验感,能较好的辅助英语的学习。以下是设计与开发的“水果乐园”课件的实现步骤和主要功能代码。
  1 摄像头图像的捕获
   使用Camera类实现对摄像头图像的捕获。Camera.get()方法返回对用于捕获视频的 Camera 对象的引用。当 SWF 文件尝试访问 Camera.get() 返回的摄像头时,Flash Player 显示“拒绝”对话框,用户可从中选择是允许还是拒绝对摄像头的访问,如图1所示。
  

setMode()方法将摄像头的捕获模式设置为最符合指定要求的本机模式。
  //新建一个Camera对象,实例名为my_cam,并设置对象属性。
  var my_cam:Camera = Camera.get();
  my_cam.setMode(160,120,30,true);
  2 摄像头图像的显示
  1)显示图像
  若要实际开始捕获视频,必须将 Camera 对象附加到 Video 对象。attachVideo(source:Object) : Void指定将在舞台上的 Video 对象的边界内显示的视频流 (source)。
  //新建一个Video对象,将Camera对象附加到Video上。
  var my_video:Video;
  my_video.attachVideo(my_cam);
  2)水平翻转图像
  由于摄像头中看到的图像与游戏者本人的方向相反。为了方便游戏者操作游戏,在加载图像时应该把图像左右翻转。这一操作非常重要,将直接影响游戏者的游戏体验。
  Video._rotation 属性可以实现对Video图像的旋转,但是无法实现左右翻转的效果。
   Video._xscale 属性指示从 Video 对象注册点开始应用的 Video 对象的水平缩放比例 。当x轴的水平缩放比例为-100时,则可以实现对Video对象的水平翻转。默认注册点为 (0,0)。缩放本地坐标系统将影响 _x 和 _y 属性设置,这些设置是以整像素定义的。由于翻转时是以左上角主测点为中心,因此在水平翻转之后,Video对象的坐标虽然未发生改变,但是整体位置向左平 移了Video. _width个像素。因此翻转之后我们需要设置Video的新坐标为Video._x = Video._x+Video._width。
  3 获取图像信息
  要对获取的图像进行分析,必须将从摄像头获取的图像信息提 取出来。在Flash8中, Bitmap对象存储了图像中各点的RGB通道信息以及Alpha通道信息,可以使用new方法建立一个Bitmap对象。然后使用draw()方法提取 某一时刻video对象中的像素信息。
   draw(source:Object,[matrix:Matrix],[colorTransform.:ColorTransform], [blendMode:Object], [clipRect:Rectangle], [smooth:Boolean]) : Void使用 Flash Player 矢量呈现器在目标图像上绘制源图像。使用 Matrix、ColorTransform、BlendMode 对象以及目标 Rectangle 对象来控制呈现的执行方式。或者也可以指定缩放时是否应对位图进行平滑处理。这只适用于当源对象是 BitmapData 对象时的情况。
  import Flash.display.BitmapData;
  
  //创建BitmapData对象
  Var snapshot:BitmapData=new
  BitmapData(output_vid._width,output_vid._height);
  //从my_video获取当前图像
  now.draw(my_video);
  4 运动检测的实现
  该部分是整个摄像头游戏实现的核心。主要利用了Flash 8的位图处理功能,即BitmapData类。
  1)基本思路
  我们可以使用getPixel(x,y)获取前一张图片上每个像素点的像素值,然后对比后一张图片中的每一点的像素值,当像素的亮度差值变化达到一定程度时,认为该点发生了运动变化。通过这种方式,得到前后两张图片的负片效果图。
  //阀值
  tolerance=10;
  //获取当前图像now某一点的RGB值
  nc=now.getPixel(x,y);
  //红色通道
  nr=nc>>16&0xff;
  //绿色通道
  ng=nc>>8&0xff;
  //蓝色通道
  nb=nc&0xff;
  //计算该点亮度值
  nl=Math.sqrt(nr*nr + ng*ng + nb*nb)
  //获取前一快照before同一点的RGB值
  bc=before.getPixel(x,y);

//红色通道
  br=bc>>16&0xff;
  //绿色通道
  bg=bc>>8&0xff;
  //蓝色通道
  bb=bc&0xff;
  //计算该点亮度值
  bl=Math.sqrt(br*br + bg*bg + bb*bb);
  //计算亮度值的变化
  d=Math.round(Math.abs(bl-nl));
  if(d>tolerance)
  {
  //该点发生了变化
  }
   但是这种方法存在计算效率问题。按图像大小为180*160像素,每秒30帧计算,每计算一副图片需要的计算次数为180*160*30。图像的像素越 大,需要的计算次数就越多。采用隔点检测的方法可以在一定程度上缓解计算压力,即每隔n个像素检测一次,这样电脑的计算次数减少为原来的1/n。
  2)改进思路
   Flash8提供的图像混合模式可以解决上面遇到的效率问题。Flash8提供了11种图像混合模式。每一种混合模式可以得到不同的混合效果。 Different 混合模式是基于两张图片之间的亮度差值进行计算,从而得到图片的负片效果。利用该模式,便可以得到移动像素的检测图像。
  //将前一张快照before的图像绘制到当前快照now上,使用different混合模式
  now.draw(before, new Matrix(), null, "difference");
  图像中黑色表示没有发生移动,其他颜色表示发生了移动。由于Flash8提供的混合模式是采用C++编码实现的,因此运行效率要比Action Script编码更加高效。
  5 动态显示检测图像
  1)处理检测图像
   通过以上两种方式得到的图像中色彩范围较广,这增加了统计上面的困难。通过使用 threshold() 方法,可以隔离和替换图像中的颜色范围,并对图像像素执行其它逻辑操作。threshold()函数根据指定的阈值测试图像中的像素值,并将通过测试的像 素设置为新的颜色值。这样,便得到了清晰醒目的检测图像。
  //将大于阀值0xFF111111的像素替换为绿色。
   myBitmap.threshold(myBitmap, myBitmap.rectangle, myBitmap.rectangle.topLeft, ">", 0xFF111111, 0xFF00FF00, 0x00FFFFFF, false);
  2)检测图像的显示
  Bitmap对象无法直接在舞台上显示,必须附着在MovieClip上面才能显示。因此可以使用MovieClip类的attachBitmap()方法,将获取的图像信息显示出来。
  //创建一个影片剪辑来显示当前图像
  this.createEmptyMovieClip(“当前”,this.getNextHighest Depth());
  //将摄像头获取的图像显示在影片剪辑内
  bitmap_mc.attachBitmap(now,1);
  3)检测图像的动态显示
  要实现检测图像的动态显示,必须不断的更新当前图像now和历史图像before,并进行混合处理。可以把检测图像的功能写成方法snapshot(),每隔100毫秒调用一次。
  伪代码如下:
  function snapshot() {
  //获取当前图像
  //获取检测图像
  //将检测图像绘制到
  //将检测图像中RGB超过阀值0xFF111111的部分替换成绿色
  //显示检测图像
  //本次检测完成之后,当前图像便成为了历史图像。为下一次检测做好准备。
  preBitmap = nowBitmap.clone();
   }
  在该方法中,关键在于每次检测完成之后当前图像和历史图像的更新。
  6 检测特定区域内的运动状态
  经过上面几步操作,已经得到了检测图像。检测图像是对整幅图像的运动情况的反映。在游戏中,经常需要检测的是某一特定区域的运动状态。
  1)检测某点的运动状态
  因为已经到了检测图像,所以在检测某一点运动状态时,只需要判断检测图像上该点的RGB值是否大于阀值。
  伪代码如下:
  pix = myBitmap.getPixel(x, y);

if (pix大于阀值) {
   //该点发生了运动
   }
  2)检测某区域的运动状态
  由于灯 光因素、摄像头图像噪点等干扰因素的存在,每次只检测一个点容易造成检测结果的不稳定。因此,大多采用区域检测的方式。即在检测某点运动状态时,检测的不 仅仅是这个点,而是以该点开始的n*n个像素的区域(n的取值根据实际情况确定,在检测点数量较多时,n的值不宜取太大。)。如果检测区域内的像素点变化 数量超过一定阀值,如60%,则认为该区域发生了运动。
  需要注意的一点是,由于看到的图像是经过水平翻转的,但原有的图像内部坐标系并没有发生变化,因此,检测时的取点位置也要水平翻转。
  //以(rectx,recty)为顶点的rectw*recth的矩形区域的运动情况
  function ismove(a, rectx, recty, rectw, recth) {
   var i, j;
   var sum = 0;
   var pix;
   for (i=1; i<=rectw; i++) {
   for (j=1; j<=recth; j++) {
  //图像水平翻转后取点位置相对变化
   pix = a.getPixel(160-i-rectx, j+recty);
   if (pix>132361) {
   sum++;
   }
   }
   }
   //trace("sum="+sum);
   if (sum>(recth*rectw/2)) {
   return (sum);
   //该区域发生了运动
   } else {
   return 0;
   }
  }
  
  在该方法中,检测图像、检测区域顶点坐标、检测区域大小都为作为变量输入。采用这种方法,提高了程序的重用性,还可以实现对运动物体的检测。
  3)检测点的设置
   所谓检测点,实际是一个影片剪辑。在进行区域检测时,以该影片剪辑的坐标(x,y)确定检测区域的坐标位置。检测点可以是一个不可见的辅助点,也可以是 舞台中运动的物体。当把运动物体做为检测点时,随着物体的移动,检测区域也随之移动,因此可以实现对运动物体的检测。检测点的作用:一是可以起到辅助点的 作用,简化了检测区域定位的繁琐工作,使定位操作可视化。二是实现了代码的重用,起到了简化程序的作用。
  7 实现摄像头运动检测的控制接口
  游戏中检测点接口的作用就是返回舞台中被触碰的检测点编号。在接口函数中,调用了以上几个功能函数。返回值为检测点编号。
  function istouch() {
   var max:Number = 0;
   var min:Number;
   var num:Number;
   for (var i = 1; i<=9; i++) {
   //检测第i个检测点是否被触碰
   min = ismove(myBitmap, this["point"+i]._x-xpoint, this["point"+i]._y-ypoint, 10, 10);
   //每次只能激发一个点,选择9个点中移动最显著的一个
   if (max

this._x = this._x-30*Math.cos(rot*Math.PI/180);
  this._y = this._y-30*Math.sin(rot*Math.PI/180);
  当子弹出界时,要使用this.unloadMovie()方法将该子弹实例销毁,释放内存。
  2)气球系统的实现
  该部分主要是实现气球的碰撞检测,判断气球是否被子弹击中需使用hitTest()函数。该函数有两种用法:
  用法 1:根据 shapeFlag 设置,将 x 和 y 坐标与指定实例的形状或边框进行比较。如果 shapeFlag 设置为 true,则只计算在舞台上的实例实际占据的区域,并且如果 x 和 y 在任意一点重叠,则返回 true 值。
  用法 2:计算 target 和指定实例的边框,如果它们在任意一点上重叠或交叉,则返回 true。
  3)主控制系统的实现
  主控制系统是实现互动功能的核心部分。主要工作就是把游戏中所有的功能模块集成起来,对各功能模块进行调度和显示。一方面,主控制系统要接收从摄像头功能接口传递的信息;一方面根据接收的信息执行相应的功能代码。
  
  四 结束语
  
   Flash摄像头游戏课件能够实现很多传统Flash课件难以实现的效果,特别是对操作技能的培养。我们开发的《水果乐园》课件提供给一些小学,进行了 英语学习实践,效果还不错。但是,对于Flash摄像头游戏课件应用于学生高级思维策略的训练,还没有进行深入的研究,特别是角色扮演型、问题探究型等学 习模式等实施,有待进一步的的探索和实践。

[SQL]SQL2005/2008中的CTE应用--递归查询

mikel阅读(549)

微软从SQL2005起引入了CTE(Common Table Expression)以强化T-SQL。这是一个类似于非持久视图的好东东。

按照MSDN介绍

1、公用表表达式 (CTE) 可以认为是在单个 Select、Insert、Update、Delete 或 Create VIEW 语句的执行范围内定义的临时结果集CTE 与派生表类似,具体表现在不存储为对象,并且只在查询期间有效。与派生表的不同之处在于,CTE 可自引用,还可在同一查询中引用多次

CTE 可用于:

  • 创建递归查询。有关详细信息,请参阅使用公用表表达式的递归查询
  • 在不需要常规使用视图时替换视图,也就是说,不必将定义存储在元数据中。
  • 启用按从标量嵌套 select 语句派生的列进行分组,或者按不确定性函数或有外部访问的函数进行分组。
  • 在同一语句中多次引用生成的表。

使用 CTE 可以获得提高可读性和轻松维护复杂查询的优点。查询可以分为单独块、简单块、逻辑生成块。之后,这些简单块可用于生成更复杂的临时 CTE,直到生成最终结果集。可以在用户定义的例程(如函数、存储过程、触发器或视图)中定义 CTE。

2、公用表表达式 (CTE) 具有一个重要的优点,那就是能够引用其自身,从而创建递归 CTE。递归 CTE 是一个重复执行初始 CTE 以返回数据子集直到获取完整结果集的公用表表达式。当某个查询引用递归 CTE 时,它即被称为递归查询。递归查询通常用于返回分层数据,例如:显示某个组织图中的雇员或物料清单方案(其中父级产品有一个或多个组件,而那些组件可能还有子组件,或者是其他父级产品的组件)中的数据。

递 归 CTE 可以极大地简化在 Select、Insert、Update、Delete 或 Create VIEW 语句中运行递归查询所需的代码。在 SQL Server 的早期版本中,递归查询通常需要使用临时表、游标和逻辑来控制递归步骤流。有关公用表表达式的详细信息,请参阅使用公用表表达式

 这里举例说明如下:

 为了描述方便,邀月特地列举了一个常见的自关联Table

表结构如下:

表结构

 再插入一些测试数据

Insert

 一个典型的应用场景是:在这个自关联的表中,查询以PKID为2的分类包含所有子分类。也许很多情况下,我们不得不用临时表\表变量\游标等。现在我们有了CTE,就简单多了

CTEDemo1

 查询结果如下:

C_Name    C_ParentName    C_ParentCode
分类5    分类2    2
分类8    分类5    2/5
分类12    分类8    2/5/8

分类13    分类8    2/5/8

 感觉怎么样?如果我只想查询第二层,而不是默认的无限查询下去,

可以在上面的SQL后加一个选项 Option(MAXRECURSION 5),注意5表示到第5层就不往下找了。如果只想找第二层,但实际结果有三层,此时会出错,

 Msg 530, Level 16, State 1, Line 1
The statement terminated. The maximum recursion 1 has been exhausted before statement completion.

此时可以通过where条件来解决,而保证不出错,看如下SQL语句:

CTEDemo2

 查询结果:

C_Name    C_ParentName    C_ParentCode
分类5    分类2    2
分类8    分类5    2/5
当然,我们不是说CTE就是万能的。通过好的表设计也可以某种程度上解决特定的问题。下面用常规的SQL实现上面这个需求。

注意:上面表中有一个字段很重要,就是C_Code,编码 ,格式如"1/2",“2/5/8"表示该分类的上级分类是1/2,2/5/8

这样,我们查询就简单多,查询以PKID为2的分类包含所有子分类:

Select C_Name as C_Name, (Select top 1 C_Name from CategorySelf s where c.C_Parent=s.PKID) as C_ParentName,C_Code as C_ParentCode
from CategorySelf c where C_Code like '2/%'

 查询以PKID为2的分类包含所有子分类,且级别不大于3

Select C_Name as C_Name, (Select top 1 C_Name from CategorySelf s where c.C_Parent=s.PKID)  as C_ParentName,C_Code as C_ParentCode
from CategorySelf c where C_Code like '2/%' and C_Level<=3

 查询结果同上,略去。这里我们看出,有时候,好的表结构设计相当重要。

邀月于2009.10.23 1:36 完成分享。
有人很关心性能问题。目前没有测试过。稍后会附上百万级测试报告。不过,有两点理解邀月忘了补充:

一、CTE其实是面向对象的,运行的基础是CLR。一个很好的说明是With查询语句中是区分字段的大小写的。即"C_Code"和"c_Code"是不一样的,后者会报错。这与普通的SQL语句不同

二、 这个应用示例重在简化业务逻辑,即便是性能不佳,但对临时表\表变量\游标等传统处理方式是一种业务层次上的简化或者说是优化。

助人等于自助!   3w@live.cn

[IIS]应用程序池运行状况

mikel阅读(638)

应用程序池运行状况

要点 要点 只有在工作进程隔离模式下运行时才能使用该 IIS 6.0 功能。

在工作进程隔离模式中,可以配置应用程序池以监视其工作进程的运行状况,还可以监视整个应用程序池的运行状况。监视工作进程的运行状况包括检测工作进程不能为请求提供服务并进行适当的操作。例如,如果工作进程没有响应万维网发布服务(WWW 服务)发出的 Ping 请求,那么工作进程可能没有可用线程处理传入的请求。发生这种情况时,WWW 服务会终止该工作进程,或者释放工作进程并使其保持运行状态,然后启动一个新的工作进程替代它。管理员可以预先配置释放未正常运行的工作进程时所进行的操作,例如将工作进行附加到调试程序。

除了监视工作进程的运行状况,WWW 服务还可以检测整个应用程序池中当前的问题。例如,如果工作进行每几秒钟就异常终止一次,则 WWW 服务可以确定工作进程运行不正常并将其停止,从而防止运行不正常的应用程序影响其他应用程序池中的应用程序。

下列情况将导致应用程序池启动或停止:

  • 启用快速失败保护会导致应用程序池停止。
  • 达到时间限制的作业对象会导致应用程序池停止,随后会在时间窗口过期后启动。
  • 由于试图使用不存在的标识而引起的配置错误会导致应用程序池停止。
  • Windows 管理员在应用程序池中执行请求停止或启动。

监视应用程序池运行状况

工作进程 ping 使 WWW 服务能够检测到工作进程无法响应请求(即工作进程不能正常运行)。Ping 是在 WWW 服务与工作进程之间发送的消息。如果 Ping 成功,则 WWW 服务假设应用程序池运行正常。如果 Ping 失败(未收到工作进程的响应),WWW 服务则假设工作进程存在问题。如果存在问题,则 WWW 服务会终止工作进程或将其释放,然后在需要为新请求提供服务时启动新的工作进程。如果工作进程被释放后仍然处于运行状态,则 WWW 服务会运行由管理员配置的操作。

WWW 服务 Ping 功能的设置和 Ping 的频率由配置数据库属性 PingingEnabledPingInterval 控制。

ISAPI 扩展能够声明自己运行不正常

可以生成 ISAPI 扩展应用程序以编程方式通知 IIS 它需要进行回收。此操作可以通过新的服务器支持函数 HSE_REQ_REPORT_UNHEALTHY 来完成。请参阅 MSDN Online 上 ISAPI 扩展参考中的 ServerSupportFunction

要有效地使用此函数,运行应用程序的 IIS 服务器必须启用了工作进程 Ping(请参阅配置工作进程运行状况监视),因为正是在 Ping 操作期间,WWW 服务能够检测到 ISAPI 未正常运行以及工作进程应该回收。ISAPI 需要能够确定其未正常运行状况的内部机制,例如监视内部线程池的状态。您应该考虑到此类的编程会关闭 ISAPI 扩展在其间运行的工作进程。因此,在该工作进程中运行的所有应用程序都需要重新启动。

由于 ASP ISAPI 扩展能够监视其内部线程池的状态,因此可以实现使用此功能的逻辑。如果进入锁定状态的线程过多,它将会发出回收的信号。

运行状况检测的限制

运行状况检测不能用于未导致工作进程损坏的应用程序失败,也不能阻止工作进程中的可用线程。例如,返回无效响应代码(如 HTTP 500)但能够正常运行的应用程序仍然可以对 WWW 服务的 Ping 做出响应,除非应用程序是实现了特定代码指示其未正常运行状态的自定义 ISAPI 扩展。

启用调试操作

如果确定某个工作进程无法正常运行,您可能会希望在启动新的工作进程为请求提供服务之前,WWW 服务保持原工作进程处于运行状态以便进行调试,而不是终止该进程。通过启用应用程序池中的调试功能,可以通知 WWW 服务不要终止工作进程,而使其从为应用程序池服务中释放出来,并保持运行状态。

除了以释放状态运行运行不正常的工作进程,还可以将 WWW 服务配置为启动可执行应用程序或脚本(例如,向管理员发送电子邮件以便通知他们失败消息可以配置为启用调试功能的应用程序)。被认为是运行不正常的工作进程的“进程 id”是发送给可执行程序或脚本的第一个参数。

注意 注意 已被释放并保持运行状态的工作进程可能仍然会终止。WWW 服务会使其处于运行状态。如果工作进程从不正常运行状态中恢复,则会检测到自己与 WWW 服务无关系,并自终止。因此,可能找到声明工作进程被释放的日志项,但是无法找到工作进程运行的证据。

由于工作进程不会由 IIS 从内存中删除,因此如果启用运行要被释放的未正常运行的工作进程,请考虑到可能需要处理被阻止的工作进程。如果管理员未正确处理用于调试的工作进程,那么您的计算机上会运行大量运行不正常的工作进程。并且这些工作进程可能会占用其他进程所需的资源。为了释放这些资源,可能需要快速终止这些工作进程。

快速失败保护

如果在指定时间段内发现指派给应用程序池的太多工作进程运行不正常,快速失败保护将停止该应用程序池。

应用程序池停止后,HTTP.sys 将返回停止服务消息(503:服务不可用),或者基于应用程序池 LoadBalancerCapabilities 属性的配置重置连接。而且,如果应用程序池自动停止,则可以配置操作(例如调试操作),通知管理员应用程序池已停止。

注意 注意 如果一台计算机上主控了多个应用程序,则应该小心配置负载平衡器,或者将硬件切换为仅重新路由对于失败的应用程序池的通信。不要将请求路由出能够正常运行的应用程序池,因为它们仍然可以接收和处理请求。

由于请求不进入用户模式的处理,因此快速失败保护可以减少处理出现问题的应用程序的开销。因此,其他应用程序池受到保护,防止它们受到运行不正常的应用程序池的影响。

可以使用以下两种方式设置快速失败保护:

  1. 根据给定时间段(以分钟计)内工作进程失败数,配置 IIS 来放置处于快速失败状态的应用程序。
  2. 手动设置应用程序处于快速失败状态。

监视应用程序池运行状况的方案

监视应用程序池运行状况并进行修正操作至少需要完成下列步骤:

  1. 通过启用 WWW 服务 Ping 工作进程,允许 WWW 服务检测未正常运行的应用程序。请参阅配置工作进程运行状况监视
  2. 指派给应用程序池的工作进程在指定时间段内损坏很多次时,将快速失败保护配置为允许禁用应用程序池。请参阅配置快速失败保护
相关主题

[MVC]PdfResult custom ActionResult in ASP.NET MVC

mikel阅读(565)

转载:http://www.jimzimmerman.com/blog/CommentView,guid,0649294f-cece-4fca-8d29-080435bd10bb.aspx

I have been very bad about not blogging and not posting code from my recent talks.  For that I apologize.  Let me say just one thing on that.  4 kids, ADD, and shiny new toys. 🙂

Ok, so several people have asked about generating pdf’s from html and css.  At work, we needed this for receipts for registration among other things.  We found a great tool from Winnovative Software that works great with css and html and spitting out an almost perfect pdf. 

We are using mvc in our solution, so we decided to come up with a custom ActionResult so that it would make it very easy to return a pdf from an action call.

Here is what the action looks like:

public PdfResult PdfForm()
{
string html = this.CaptureActionHtml(this, c => (ViewResult)c.PrintForm());
return new PdfResult(html, "PdfForm", true);
}
public ActionResult PrintForm()
{
var db = new NorthwindDataContext();
List<Customer> customers = db.Customers.ToList<Customer>();
ViewData["customers"] = customers;
return View("PrintForm");
}

 

Notice the CaptureActionHtml.  I found this code on this blog post as I was trying to figure out a way to use ASP.NET mvc as the template engine to save time for generating the html which the html to pdf tool needed.

Here is the CaptureActionHtml class:

using System;
using System.IO;
using System.Web;
using System.Web.Mvc;
namespace HtmlHelperExamples
{
public static class ControllerExtensions
{
/// <summary>
/// Captures the HTML output by a controller action that returns a ViewResult
/// </summary>
/// <typeparam name="TController">The type of controller to execute the action on</typeparam>
/// <param name="controller">The controller</param>
/// <param name="action">The action to execute</param>
/// <returns>The HTML output from the view</returns>
public static string CaptureActionHtml<TController>(
this TController controller,
Func<TController, ViewResult> action)
where TController : Controller
{
return controller.CaptureActionHtml(controller, null, action);
}
/// <summary>
/// Captures the HTML output by a controller action that returns a ViewResult
/// </summary>
/// <typeparam name="TController">The type of controller to execute the action on</typeparam>
/// <param name="controller">The controller</param>
/// <param name="masterPageName">The master page to use for the view</param>
/// <param name="action">The action to execute</param>
/// <returns>The HTML output from the view</returns>
public static string CaptureActionHtml<TController>(
this TController controller,
string masterPageName,
Func<TController, ViewResult> action)
where TController : Controller
{
return controller.CaptureActionHtml(controller, masterPageName, action);
}
/// <summary>
/// Captures the HTML output by a controller action that returns a ViewResult
/// </summary>
/// <typeparam name="TController">The type of controller to execute the action on</typeparam>
/// <param name="controller">The current controller</param>
/// <param name="targetController">The controller which has the action to execute</param>
/// <param name="action">The action to execute</param>
/// <returns>The HTML output from the view</returns>
public static string CaptureActionHtml<TController>(
this Controller controller,
TController targetController,
Func<TController, ViewResult> action)
where TController : Controller
{
return controller.CaptureActionHtml(targetController, null, action);
}
/// <summary>
/// Captures the HTML output by a controller action that returns a ViewResult
/// </summary>
/// <typeparam name="TController">The type of controller to execute the action on</typeparam>
/// <param name="controller">The current controller</param>
/// <param name="targetController">The controller which has the action to execute</param>
/// <param name="masterPageName">The name of the master page for the view</param>
/// <param name="action">The action to execute</param>
/// <returns>The HTML output from the view</returns>
public static string CaptureActionHtml<TController>(
this Controller controller,
TController targetController,
string masterPageName,
Func<TController, ViewResult> action)
where TController : Controller
{
if (controller == null)
{
throw new ArgumentNullException("controller");
}
if (targetController == null)
{
throw new ArgumentNullException("targetController");
}
if (action == null)
{
throw new ArgumentNullException("action");
}
// pass the current controller context to orderController
var controllerContext = controller.ControllerContext;
targetController.ControllerContext = controllerContext;
// replace the current context with a new context that writes to a string writer
var existingContext = System.Web.HttpContext.Current;
var writer = new StringWriter();
var response = new HttpResponse(writer);
var context = new HttpContext(existingContext.Request, response) {User = existingContext.User};
System.Web.HttpContext.Current = context;
// execute the action
var viewResult = action(targetController);
// change the master page name
if (masterPageName != null)
{
viewResult.MasterName = masterPageName;
}
// we have to set the controller route value to the name of the controller we want to execute
// because the ViewLocator class uses this to find the correct view
var oldController = controllerContext.RouteData.Values["controller"];
controllerContext.RouteData.Values["controller"] = typeof(TController).Name.Replace("Controller", "");
// execute the result
viewResult.ExecuteResult(controllerContext);
// restore the old route data
controllerContext.RouteData.Values["controller"] = oldController;
// restore the old context
System.Web.HttpContext.Current = existingContext;
return writer.ToString();
}
}
}

Here is the PdfResult class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Winnovative.WnvHtmlConvert;
using System.Text.RegularExpressions;
namespace System.Web.Mvc
{
public class PdfResult : ViewResult
{
public string ContentType { get; set; }
public string Content { get; set; }
public string OutputFileName { get; set; }
public bool ReturnAsAttachment { get; set; }
public PdfResult(string html, string outputFileName, bool returnAsAttachment)
{
// ViewResult vr = ar as ViewResult;
this.ContentType = "application/pdf";
this.Content = html;
this.OutputFileName = outputFileName;
this.ReturnAsAttachment = returnAsAttachment;
}
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.ContentType = ContentType;
string baseURL = "";
string htmlString = this.Content;
bool selectablePDF = true;
// Create the PDF converter. Optionally you can specify the virtual browser width as parameter.
//1024 pixels is default, 0 means autodetect
PdfConverter pdfConverter = new PdfConverter();
// set the license key
pdfConverter.LicenseKey = "yourkeyhere";
// set the converter options
pdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
pdfConverter.PdfDocumentOptions.PdfCompressionLevel = PdfCompressionLevel.Normal;
pdfConverter.PdfDocumentOptions.PdfPageOrientation = PDFPageOrientation.Portrait;
pdfConverter.PdfDocumentOptions.ShowHeader = false;
pdfConverter.PdfDocumentOptions.ShowFooter = false;
// set to generate selectable pdf or a pdf with embedded image
pdfConverter.PdfDocumentOptions.GenerateSelectablePdf = selectablePDF;
// Performs the conversion and get the pdf document bytes that you can further
// save to a file or send as a browser response
// The baseURL parameterhelps the converter to get the CSS files and images
// referenced by a relative URL in the HTML string. This option has efect only
// if the HTML string contains a valid HEAD tag.
// The converter will automatically inserts a <BASE HREF="baseURL"> tag.
byte[] pdfBytes = null;
if (baseURL.Length > 0)
{
pdfBytes = pdfConverter.GetPdfBytesFromHtmlString(htmlString, baseURL);
}
else
{
pdfBytes = pdfConverter.GetPdfBytesFromHtmlString(htmlString);
}
// send the PDF document as a response to the browser for download
// System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
context.HttpContext.Response.Clear();
// this.OutputFileName = Regex.Replace(this.OutputFileName, " ", "_", RegexOptions.IgnoreCase);
// this.OutputFileName = StringHelper.StripNonAlphaNumeric(this.OutputFileName);
context.HttpContext.Response.AddHeader("Content-Type", "application/pdf");
if (this.ReturnAsAttachment)
{
context.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=" + this.OutputFileName + ".pdf; size=" + pdfBytes.Length.ToString());
}
context.HttpContext.Response.Flush();
context.HttpContext.Response.BinaryWrite(pdfBytes);
context.HttpContext.Response.Flush();
context.HttpContext.Response.End();
}
}
}

 

Hopefully this will help those of you who are wanting to generate the pdf’s using html and css along with using the default mvc view engine as your template engine. Enjoy!

[MVC]Customizing ViewEngine in ASP.NET MVC

mikel阅读(470)

转载:http://geekswithblogs.net/sankarsan/archive/2008/12/25/customizing-viewengine-in-ASP.NET-mvc.aspx

In an ASP.NET MVC application the request URI is of the following format {controller}/{action}/{id}.Based on the controller name in the URI the ControllerFactory instantiates the appropriate Controller class and then based on the action in the URI the corresponding action method in the Controller is executed.Action method then dispatches the right view and by default the location of the views are in the path ~/Views/<Controller>/<Action>.aspx.But how can we change this default behavior and make the location of the view configurable based on Web.config settings.

This can be done very easily by overriding the FindView method of System.Web.Mvc.VirtualPathProviderViewEngine.In my previous post I have discussed in details about the Classes and Interfaces related to View Engines and how views are located.So we have create a class inheriting System.Web.Mvc.WebFormViewEngine and then override the FindView method as shown below:

public  class CustomViewEngine:WebFormViewEngine
{
     public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName)
     {
         string viewPath = string.Empty;
         string masterPath = string.Empty;
         ViewEngineResult result = null;

         if (controllerContext == null) throw new ArgumentNullException("ControllerContext cannot be null");
         if (viewName == null || viewName.Length == 0) throw new ArgumentNullException("ViewName cannot be null");

        //Read View Path from Web.config

         viewPath = ConfigurationManager.AppSettings[viewName];
         if (viewPath == null || viewPath.Length == 0) throw new ConfigurationErrorsException("View Path cannot be null or empty.Please check web.config");
         masterPath = ConfigurationManager.AppSettings[masterName];

       //Create an instance of IView and wrap the results in an ViewEngineResult instance

         result = new ViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);
         return result;

     }
}

Now we need to remove the default view engine and plug in our custom view engine in Application_Start event of Global.asax.cs as follows:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new SB.Web.Mvc.CustomViewEngine());

Lastly we need to add the actual view paths in web.config as shown below:

<add key="Index" value="~/Pages/Index.aspx"/>
<add key="About" value="~/Pages/About.aspx"/>

[MVC]Lowercase Route URLs in ASP.NET MVC

mikel阅读(614)

转载:http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/

Lowercase Route URL's in ASP.NET MVC

For anybody interesting in having ruby on rails style routes; or follow a lowercase URL pattern (mysite.com/member/profile/goneale) which most web 2.0 sites seem to be following, check out the below code cited and enhanced from this article (http://www.makiwa.com/index.php/2008/05/31/lowercase-mvc-route-urls/).

Firstly you will need a RouteExtensions.cs file, or named anything you like with the following (compatible as at ASP.NET MVC RC1):

  1. using System;
  2. using System.Web.Mvc;
  3. using System.Web.Routing;
  4.  
  5. namespace MyMvcApplication.App.Helpers
  6. {
  7.     public class LowercaseRoute : System.Web.Routing.Route
  8.     {
  9.         public LowercaseRoute(string url, IRouteHandler routeHandler)
  10.             : base(url, routeHandler) { }
  11.         public LowercaseRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
  12.             : base(url, defaults, routeHandler) { }
  13.         public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
  14.             : base(url, defaults, constraints, routeHandler) { }
  15.         public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
  16.             : base(url, defaults, constraints, dataTokens, routeHandler) { }
  17.  
  18.         public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
  19.         {
  20.             VirtualPathData path = base.GetVirtualPath(requestContext, values);
  21.  
  22.             if (path != null)
  23.                 path.VirtualPath = path.VirtualPath.ToLowerInvariant();
  24.  
  25.             return path;
  26.         }
  27.     }
  28.  
  29.     public static class RouteCollectionExtensions
  30.     {
  31.         public static void MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults)
  32.         {
  33.             routes.MapRouteLowercase(name, url, defaults, null);
  34.         }
  35.  
  36.         public static void MapRouteLowercase(this RouteCollection routes, string name, string url, object defaults, object constraints)
  37.         {
  38.             if (routes == null)
  39.                 throw new ArgumentNullException("routes");
  40.  
  41.             if (url == null)
  42.                 throw new ArgumentNullException("url");
  43.  
  44.             var route = new LowercaseRoute(url, new MvcRouteHandler())
  45.             {
  46.                 Defaults = new RouteValueDictionary(defaults),
  47.                 Constraints = new RouteValueDictionary(constraints)
  48.             };
  49.  
  50.             if (String.IsNullOrEmpty(name))
  51.                 routes.Add(route);
  52.             else
  53.                 routes.Add(name, route);
  54.         }
  55.     }
  56. }

Then a using reference in your Global.asax.cs file to the above class, and you’re all set to create a lowercase route.
You can see a below example of a lowercase route and anytime this route is called your URL will be lowercased.

  1.             routes.MapRouteLowercase(
  2.                 "Default", // Route name
  3.                 "{controller}/{action}/{id}", // URL with parameters
  4.                 new {controller = "Home", action = "index", id = ""} // Parameter defaults
  5.                 );

and optionally if you are interested in converting any incoming URL’s to lowercase (manually typed by the user or called links) you can use this in your Application_BeginRequest() method (Remember, this is not needed for lowercase routes themselves, the code above will handle that):

  1.         protected void Application_BeginRequest(Object sender, EventArgs e)
  2.         {
  3.             // If upper case letters are found in the URL, redirect to lower case URL.
  4.             // Was receiving undesirable results here as my QueryString was also being converted to lowercase.
  5.             // You may want this, but I did not.
  6.             //if (Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), @"[A-Z]") == true)
  7.             //{
  8.             // string LowercaseURL = HttpContext.Current.Request.Url.ToString().ToLower();
  9.  
  10.             // Response.Clear();
  11.             // Response.Status = "301 Moved Permanently";
  12.             // Response.AddHeader("Location", LowercaseURL);
  13.             // Response.End();
  14.             //}
  15.  
  16.             // If upper case letters are found in the URL, redirect to lower case URL (keep querystring the same).
  17.             string lowercaseURL = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
  18.             if (Regex.IsMatch(lowercaseURL, @"[A-Z]"))
  19.             {
  20.                 lowercaseURL = lowercaseURL.ToLower() + HttpContext.Current.Request.Url.Query;
  21.  
  22.                 Response.Clear();
  23.                 Response.Status = "301 Moved Permanently";
  24.                 Response.AddHeader("Location", lowercaseURL);
  25.                 Response.End();
  26.             }
  27.         }

[缓存].NET中使用Memcached的相关资源整理

mikel阅读(538)

转载:http://www.cnblogs.com/dudu/archive/2009/07/19/1526407.html

Memcached官方站点:http://www.danga.com/memcached/

Memcached Win32 1.2.6下载:http://code.jellycan.com/memcached/

安装帮助:Windows下的.NET+ Memcached安装

Memcached .NET客户端:

1).NET memcached client library

  下载地址:https://sourceforge.net/projects/memcacheddotnet

  相关文章:分布式缓存系统Memcached简介与实践

2)enyim.com Memcached Client

  下载地址:http://www.codeplex.com/EnyimMemcached/

  相关文章:memcached系列2:memcached实例  

3)Memcached Providers

  下载地址:http://www.codeplex.com/memcachedproviders

  相关文章:.NET平台上的Memcached客户端介绍

4) BeIT Memcached

  下载地址:http://code.google.com/p/beitmemcached/

  相关文章:分布式缓存BeIT Memcached简介

相关链接: 

a) Memcached for Windows
b) Which .NET Memcached client do you use, EnyimMemcached vs. BeITMemcached?
c) 博客园知识库Memcached相关文章