首先,实现ihttphandler时要实现一个isreusable的属性,这个属性告诉asp.net此httphandler是否可重用。如果一个httphandler是可重用的,那么多次请求都有可能用同一个httphandler实例;而如果一个httphandler是不可重用的,那么asp.net应该确保每次请求使用的都是一个新构造的httphandler实例。
page是设计为不可重用,所以每次请求都会导致构造一个新的page实例,这是因为page的生命周期不能恢复到初始状态,一个page经历完生命周期后就不能用于处理下一次的请求。类似的,如果我们有一个httphandler有类似的性质,处理一次请求后其状态就难以恢复到适合于处理下一次请求,或者说恢复还不如构造一个新的,那么我们就应该设计为不可重用。
我在做一个通过iframe提交的无刷新上传控件,这东西包括一些httphandler,为的是能够直接关联到axd后缀而用于路径无关的场合。其中有一个httphandler我直接继承自page,并且写得好像aspx+cs编译出来的代码那样,在oninit阶段构建完整的控件树。这个httphandler以前在xp的iis5上一直没问题的,但到了vista的iis7就出问题了。
先说明,在iis7我采用其新的配置模式,将<httphandlers />配置在<system.webserver />节,而不是<system.web />节,这是模仿着asp.net ajax的web.config做的。做好之后就发现问题了,这个用作httphandler的page竟然时候抛出exception,说page上面有多于一个的htmlform。仔细检查后确认,我的page代码确实仅仅添加了一个htmlform,并且这个exception不会出现在编译后的第一次请求,于是我就怀疑page被重用了,所以oninit被多次执行,这才可能导致它有多于一个htmlform。我启用了page的trace,在render中注释掉base.render,并且用trace输出page上的htmlform数量,发现真的是每次请求都会导致多一个htmlform,这基本上可以肯定是因为page被重用了。
然后我就用google搜索,结果发现forums.asp.net上有人提出了完全一样的问题,他也是用page来做httphandler。我想只有拿page来做httphandler的人才会遇到这样的问题,因为一般自己写的httphandler都是无状态的,所以都是可以重用的。而那张帖子只有管理员回复了一句,“你最好去forums.iis.net问吧”。于是我就去iis.net搜索,结果发现没有人提到过这个问题,于是只好自己去论坛提问,可惜等了一天都没有人回答,看来iis7普及之前iis.net的人气都不会上升(iis7的默认欢迎页面链接到iis.net)。
最后,我选择了先采用jeffrey zhao建议的work around,就是再制作一个httphandlerfactory,它负责每次返回page的新实例,然后在配置中改用该httphandlerfactory。这个解决方案实验证明是可行的,就是多一个类而已,不知道性能损失有多少。如果有人知道这个问题的官方解决方案的话,或者有一个更好的work around,请告诉我,谢谢。
新闻热点
疑难解答
图片精选