|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
一个很大的类库。应用程序之所以难以跨平台,在于直接调用了特定平台的接口,而一个巨大的类库,就能极大地减少应用程序对平台的依赖。asp.net 本文次要经由过程剖析在ASP.NET2.0中开辟ASP.NET通配符映照使用程序碰到的一些成绩,来讲明ASP.NET2.0中页面编译模子的不敷的地方。文章中假如有不当的地方,接待您指出。
这里所说的ASP.NET通配符映照使用程序是指在IIS中将一切哀求转发至ASP.NET2.0运转时处置(关于IIS5.0,就是创建.*到aspnet_isapi.dll的映照),在程序中经由过程完成System.Web.IhttpHandlerFactory接口来处置一切哀求,完成System.Web.IhttpHandlerFactory的类就相称于一个前端把持器。典范使用就是.Text及基于.Text开辟的博客园Blog软件。
在ASP.NET1.1中,完成通配符映照使用程序人人大概对照分明,次要是两点:
1、完成System.Web.IhttpHandlerFactory接口,在GetHandler(HttpContextcontext,stringrequestType,stringurl,stringpath)中依据哀求的url,基于一些划定规矩,找到实践会见的页面文件,然后挪用PageParser.GetCompiledPageInstance对页面举行编译并天生响应的实例处置哀求。如许做的优点是:你可使用恣意的url地点,不用体贴是不是存在对应的页面文件,并且能够便利地把持对Web服务器上资本的会见。
2、在web.config中加上:
<httpHandlers>
<addpath="*"verb="*"type="Dottext.Common.UrlManager.UrlReWriteHandlerFactory,Dottext.Common"validate="false"/>
</httpHandlers>
ASP.NET2.0中新的页面编译模子给完成通配符映照使用程序带来意想不到的成绩,上面我以博客园Blog软件为例与人人一些切磋这些成绩。
在博客园Blog软件中,完成IhttpHandlerFactory接口的是Dottext.Common.UrlManager.UrlReWriteHandlerFactory,不改动在ASP.NET1.1中完成的UrlReWriteHandlerFactory代码,间接在ASP.NET2.0中编译并运转,当程序运转在IIS根目次下,就会在实行PageParser.GetCompiledPageInstance时呈现“Objectreferencenotsettoaninstanceofanobject”非常(运转在假造目次中不会呈现这个成绩)。这个成绩是ASP.NET2.0中的一个小Bug,之前我写的PageParser.GetCompiledPageInstance中的一个Bug及办理办法对这个成绩举行了一些剖析,这个成绩能够经由过程在PageParser.GetCompiledPageInstance之前挪用context.RewritePath("~/default.aspx")办理。
接着举行会见团体Blog主页的测试,好比:http://www.ckuyun.com/dudu,会见时呈现毛病:
“Thereisnobuildproviderregisteredfortheextension.Youcanregisteroneinthe<compilation><buildProviders>sectioninmachine.configorweb.config.MakesureishasaBuildProviderAppliesToAttributeattributewhichincludesthevalueWeborAll.”
在ASP.NET2.0中,当我们第一次会见一个页面时,必很多的两个历程是:1、页面编译2、创立编译后的页面代码的实例。页面编译是依据所会见的url地点中的扩大名找到婚配的BuildProvider对页面举行编译。这里呈现的成绩是因为ASP.NET2.0运转时没找到响应的BuildProvider,对http://www.ckuyun.com/dudu如许地点,因为利用了通配符映照,在ASP.NET2.0运转时处置时,失掉的扩大名是空(假如没有利用通配符映照,IIS会主动将地点改成:http://www.ckuyun.com/dudu/default.aspx)。ASP.NET2.0在这里的计划不敷的地方是没有思索这类情形,没法经由过程在web.config中举行响应的设置来办理这个成绩。假如能供应上面的设置,这个成绩就能够轻松办理:
<buildProviders>
<addextension=".*"type="System.Web.Compilation.PageBuildProvider"/>
</buildProviders>
关于这个成绩,我的办理办法是在PageParser.GetCompiledPageInstance之前对url举行处置,在url中加上缺省文件,好比:default.aspx。假如你想利用其他的扩大名,好比:.html,必要在web.config中加上:
<buildProviders>
<addextension=".html"type="System.Web.Compilation.PageBuildProvider"/>
</buildProviders>
这里另有一个小bug,在下面的毛病信息“MakesureishasaBuildProviderAppliesToAttributeattributewhichincludesthevalueWeborAll.”提醒必要设置AppliesToAttribute属性,实践上web.config中其实不撑持如许的属性,多是正式版之前的ASP.NET2.0撑持过这个属性,厥后往失落后,毛病提醒信息并没有修正。
办理了下面的两个成绩,原觉得通配符映照使用程序能够在ASP.NET2.0中一般运转了,我在本机上测试博客园的程序,页面能一般会见。但是明天清晨在服务器进大将网站晋级到ASP.NET2.0以后,发明ASP.NET运转时在频仍地编译页面,CPU占用一向100%,编译了一个多小时还在编译,并且编译仿佛与会见量有关,会见少的站点页面还能翻开,博客园主站因为会见量年夜,几近没法会见。成绩出在哪?因而我从PageParser.GetCompiledPageInstance的源代码寻觅线索,在BuildManager.GetCacheKeyFromVirtualPath中发明可疑的地方,BuildManager是依据所哀求的假造路径创立缓存键,然后依据这个键查找或创立页面编译后的缓存工具。当对一个页面收回哀求时,BuildManager会反省缓存,先从内存中反省,假如内存中没有就从缓存文件夹(TemporaryASP.NETFiles)中查找,假如找到,就间接创立该范例的实例,不举行静态编译。假如没找到,就举行页面编译事情,并且查找的根据就是依据假造路径创立的缓存键。
关于一般的页面会见体例,如许处置不会引发成绩。但关于通配符映照的情形,就会带来成绩。由于通配符映照时,罕见情形是分歧的url地点会见的倒是统一个页面文件。好比博客园中每篇文章地点分歧,但会见的倒是一样的页面代码,假如依照今朝ASP.NET2.0中的页面编译模子,每篇文章第一次会见都要举行编译,假如博客园中的几十万篇文章被会见,就要举行几十万编译,难怪明天博客园网站晋级至ASP.NET2.0以后,服务器一向忙于编译。
经由测试情形公然如许,固然会见地点:http://www.ckuyun.com/dudu/archive/2006/03/07/345107.html时会在TemporaryASP.NETFiles中文件夹编译天生类ASP.dudu_archive_2006_03_07_345107_html,而会见其他文章地时,也依据文章地点天生别的一个类。如许编译效力其实太低了!为何要依据假造路径创立缓键,计划者计划时基本没思索到通配符映照的成绩,真是糟的计划!假如依照ASP.NET1.1那样依据实践会见的页面文件名创立缓存键,就能够轻松地制止这个成绩。ASP.NET2.0新的页面编译模子在这里仿佛是一个败笔。更糟的是连闪开发职员填补这个Bug的时机都没有,System.Web.Compilation.BuildManager中没有供应一个闪开发职员本人设置缓存键的办法或属性。
(注:创立缓存键的办法是BuildManager.GetCacheKeyFromVirtualPath(VirtualPathvirtualPath,outboolkeyFromVPP))。更糟的是,System.Web.Compilation中的良多类都是internal,良多类的办法是灰色(Reflector用灰色显现internalstatic或private,色彩用的不错,让人看了就悲观),想本人挪用响应办法举行页面编译几近是不成能(用反射的办法不知可否挪用,还没试过,即便能挪用,也要思索功能上的丧失)。
岂非要本人写System.Web.Compilation中那些类去向理页面编译?我宁肯选择ASP.NET1.1,然后等ASP.NET2.0SP1,SP1办理不了,等SP2......但愿不要比及ASP.NET3.0。
大概你想到了在GetHandler(HttpContextcontext,stringrequestType,stringurl,stringpath)中挪用System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath来编译并创立页面的实例。这个办法我也实验过,谜底是不可,还不如PageParser.GetCompiledPageInstance,最少后者能让程序运转起来。利用BuildManager.CreateInstanceFromVirtualPath时,当会见的地点中不带扩大名时就会呈现“Theresourcecannotbefound”毛病,缘故原由是在GetVPathBuildResultInternal(VirtualPathvirtualPath,boolnoBuild,boolallowCrossApp,boolallowBuildInPrecompile)中挪用了Util.CheckVirtualFileExists(virtualPath)对假造路径举行反省,反省时将假造路径转换为物理路径,反省以后哀求的页面文件是不是存在,关于通配符映照使用程序,良多地点是实践上不存在的,以是就呈现“Theresourcecannotbefound”毛病。而PageParser.GetCompiledPageInstance中经由过程挪用HostingEnvironment.AddVirtualPathToFileMapping制止了这个成绩。而这个办法被
Internal回护,在代码中也没法挪用。
我以为成绩的中心是ASP.NET2.0计划者在计划时没有思索通配符映照如许的情形。是疏忽仍是尚有思索,就不得而知了。但ASP.NET1.1能准确处置这个成绩,而ASP.NET2.0却处置不了,这里很不该该的。利用通配符映照的Web使用程序用户只能看ASP.NET2.0心叹。比来花了很年夜精神想把博客园的程序迁徙到ASP.NET2.0,而了局倒是没法迁徙到ASP.NET2.0,使人扫兴!只能寄但愿微软推出响应的补钉。
还好,利用通配符映照的Web使用程序不是良多,这个成绩影响不是很年夜。
有时也搞不懂应该学那种;主要看你以后去的那个公司是使用哪种了。就像王千祥的课上说的:企业应用现在主要就三层(其实也差不多就是MVC):表示层(主要使用html写的,很简单)、业务逻辑层(主要就是应用服务器的)。最后就是数据层(其实就是学习数据库) |
|