ASP.net页面揭秘

原文:http://www.cnblogs.com/couhujia/archive/2010/04/21/1717366.html

     http://www.cnblogs.com/couhujia/archive/2010/04/22/1717835.html

     http://www.cnblogs.com/couhujia/archive/2010/04/23/1718405.html

     http://www.cnblogs.com/couhujia/archive/2010/03/23/1692586.html

ASP.NET页面揭秘(一)

 

 

  其实对这方面一直掌握的不够熟练,属于半桶水那种类型—一知半解,所以这次重新这阅读了《asp.net 2.0技术内幕》对这块知识又有了新的认识。

  在基于IIS的Web服务器上可以访问的所有资源按文件扩展名进行分组。然后把任何一个输入的请求分配给特定的运行时模块处理。ISAPI(Internet Server Application Programming Interface)扩展在 IIS的上下文中处理Web的资源的模块。它就是一个普通的旧式Win32动态链接库(DLL),提供了大量有预定义名称和原型的API函数,为开发人员提供了更加强大的对于IIS功能的扩展。IIS和 ISAPI扩展作为一种私有的通信协议使用这些DLL项。对一个资源的请求到达时,IIS首先验证资源类型。图像,文本文件,HTML页面和无脚本ASP页面等静态资源,由IIS直接解析。需要服务器端进行加工的资源被转到已注册的模块。例:.aspx文件就会分配给一个名为C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll的ISAPI扩展处理。

资源映射存储在IIS元库中。ASP.NET在安装时对IIS元库进行修改,确保aspnet_isappi.dll能处理某些典型的ASP.NET资源。(.asax,.ascx,ashx,asmx,aspx,axd等等)

 

IIS5.0进程模型

 

 

跟据该模型,当一个http资源请求来的时候,aspnet_isapi.dll 不能处理.aspx文件,而是充当调度程序。它收集所有有关激活的URL和基础资源信息,然后把请求传给另一个进程: 名为aspnet_wp.exe的asp.net工作进程。ISAPI扩展和该工作进程之间的通道通过命名管道进行。工作进程的一个副本始终在运行,并托管所有的活动的web应用程序。每个web应用程序用自己虚拟目录进行标识,并且属于一个不同的应用区域(通常称为AppDomain)。每当客户第一次处理一个虚拟目录时,在ASP.NET工作进程内创建一个新的AppDomain.创建新的AppDomain后,ASP.NET运行库加载所有必须的程序集,并把控制传递给托管的HTTP 管道以实际服务请求。如果客户从一个已经运行的Web应用程序请求一个页,则ASP.NET运行库只把该请求转发到与该虚拟目录关联的现有AppDomain。如果该AppDomain中没有加载处理该页所有的程序集,则动态地创建它,否则在第一次调用时已经创建,则只使用它。

 

表示请求页

  每个引用.aspx资源的进入请求都会被映射到一个派生 Page类,并且通过它提供服务。ASP.NET HTTP运行时环境首先确定用于服务该请求的类的名称。这里有个特殊的命名约定将该页的URL与该类的名称相关联。例 default.aspx对应类ASP.default_aspx。如果AppDomian当前装入的任何程序集中都不存在具有该名称的类,则HTTP运行库就会命令创建该类并编译。该类的源代码通过解析.aspx 资源的源代码而创建的,并临时保存在ASP.NET文件夹中。接着就对该类进行编译,并载入内存以服务请求。

 

处理请求

上面谈到创建了一个解析.aspx资源的类,那么接着HTTP运行时环境会通过一个接口(IHttpHandler)的方法来激活该类。根类Page实现该接口(两个成员:ProcessRequest方法和Boolean特性).一旦 HTTP运行库获得了表示被请求资源的类的实例,激活ProcessRequest方法就会产生一个进程,并在生成浏览器的最终响应时间结束。执行和触发ProcessRequest调用的步骤和事件统称为页面生存周期。

 

什么是ASP.NET HTTP运行时环境?

ASP.NET HTTP运行时环境,它主要包括4个对象

(1)HttpRuntime对象 网页请求通过一个处理原始HTTP负荷的对象管道,并在该链末端为浏览器产生一些标记代码。该管道入口点是HttpRuntime类。ASP.NET工作(IIS5.0是aspnet_wp.exe)进程激活该HTTP管道方法是创建HttpRuntime对象实例,然后调用它的ProcessRequest方法。注意:HttpRuntime.ProcessRequest方法与IHttpHandler接口无关。

HttpRuntime对象在创建时初始化许多有助于首先网页请求的内部对象。调用ProcessRequest方法时,HttpRuntime对象首先把网页提供给浏览器。它为请求创建一个新的上下文(HttpContext类的一个实例,封装了有关请求的所有Http特有信息),并初始化一个特殊的writer对象,其中将收集标记代码。HttpRuntime对象使用该上下文信息找到或创建一个能够处理该请求的Web应用程序对象。通过使用URL中包含的虚拟目录信息搜索该应用程序。用来寻找或创建web应用程序对象的是HttpApplicationFactor(是一个内部使用的对象,负责返回一个能够处理该请求的有效对象。)

(2)应用程序工厂

在应用程序的生命周期内,HttpApplicationFactory对象维护一个HttpApplication对象池,以服务于进入的Http请求。在被激活后,该应用程序工厂对请求验证所瞄准的虚拟文件夹是否有一个AppDomain.如果应用程序已经运行,该工厂就从可用的对象池中获取一个HttpApplication,并把它传递给请求。如果现有的对象不可用,则创建一个新的HttpApplication对象。

(3)HttpApplication对象

HttpApplication对象是一个基类,它代表一个正在运行的ASP.NET应用程序。一个正在运行的ASP.NET应用程序由一个动态创建的继承自HttpApplication的类表示。通过解析global.asax文件内容,可以创建动态生成的应用程序类的源代码。

HttpApplication派生类的一个实例负责管理分配给它的请求的整个生命周期。只有完成后才能重用。HttpApplication维护一个HTTP模块对象列表,它可以筛选或修改请求的内容。当请求通过管道时,调用那些已经注册的模块。

 HttpApplication对象确定表示被请求的资源的对象类型,这个类型通常是一个ASP.NET页,一个Web服务或者一个用户控件.然后HttpApplication使用合适的处理程序工厂,获得一个表示被请求资源的对象。一个处理程序工厂对象是一个实现了IHttpHandlerFacory接口类,负责返回一个能够处理该Http请求的托管类的实例——一个HTTP处理程序。ASP.NET页面是一个处理程序对象,一个实现了IHttpHandler接口的类的实例。 

(4)页面工厂

HttpApplication 类确定必须处理请求的对象的类型并委派该类型特定的处理程序工厂创建该类型一个实例。当被请求的资源是网页时,那么该工厂就是PageHandlerFactory的类。为了找到合适的处理程序,HttpApplication使用配置文件的<httpHandlers>节中的信息。处理程序工厂对象并创建一个对象的实例,表示被请求的特定页。该对象继承System.Web.UI.Page类,Page类实现了IHttpHandler接口。该页对象返回应用程序工厂,而程序工厂又把它传回到HttpRuntime对象。ASP.NET运行库完成最后调用是IHttpHandler的ProcessRequest方法。这个调用使网页执行该页的代码,并生成浏览器的标记。

 

小结一下,ASP.NET工作进程服务一个输入的Http请求,首先请求被分配给aspnet_isapi.dll ISAPI扩展,而该扩展又把它传递给HTTP运行时管道。ASP.NET管道入口点是HttpRuntime类。为每个请求创建该类的一个新实例,控制它的总体执行情况,并生成浏览器响应的文本。实例化时,HttpRuntime类执行实例化任务,其中的首要任务是创建一个包装器对象,以封装有关该请求的所有Http特有信息。然后将新建的对象(HttpContext对象的一个实例)传递给该管道,并被各个模块来访问内在的工作对象。

 

 

 

 

 

ASP.NET页面揭秘(二)

 

   这里主要谈谈Application类中的事件

由前一篇文章可以知道,一旦出现了HttpContext类的一个实例,HttpRuntime类就会建立一个ASP.NET应用程序对象来完成该请求。一个应用程序包括HttpApplication类的一个实例。HttpApplication是一个global.asax派生的对象,处理所有被传递给某个虚文件夹得Http请求。一个正在运行的ASP.NET运行程序完全由它的虚拟文件来表示,并选择性地global.asax文件来表示。虚拟文件夹名称是一种键,Http运行库用它来选择表示哪一个正在运行的应用程序应当负责输入请求。Global.asax包含一些设置和代码,用于响应ASP.NET引发的或者影响该应用程序的HTTP模块注册的应用程序级事件。只有完成请求以后才能重用HttpApplication的实例。如果没有HttpApplication对象可以使用,则创建一个新的HttpApplication对象,并把它放入到对象池中。

 

HttpApplication类的事件

HttpApplication_Start在Web应用程序的生命周期内只激发一次。它表示已经创建HttpApplication类的第一个实例,以启动服务它的第一个请求。Application_End只在应用程序被关闭时才被调用。

HttpApplication有许多事件,以下是按照事件先后激发顺序。

1.  对请求进行验证,将检查浏览器发送的信息,并确定其是否包含潜在恶意标记。

2.  如果已在 Web.config 文件的 UrlMappingsSection 节中配置了任何 URL,则执行 URL 映射

3.  BeginRequest ASP.NET HTTP管道开始处理该请求。该事件在Application_Start之后到达应用程序。

4.  AuthenticateRequest 正在验证请求。所有的内部ASP.NET验证模块都订阅该事件,并企图产生一个标识。如果没有一个验证模块产生一个已验证用户,则调用一个默认的内部验证模块,为这个未验证的用户产生一个标识。这么做是为了一致性,使该代码不必考虑null值。

5.  PostAuthenticateRequest请求已被验证。所有可能的信息存储在HttpContext的User属性中。

6.  AuthorizeRequest 即将发生请求授权。该事件通常被应用程序的代码进程处理,以根据业务逻辑或其它应用程序需求完成定制的授权。

7.  PostAuthorizeRequest该请求已被授权

8.  ResolveRequestCache ASP.NET运行库验证返回一个以前缓存的页面能否解决该请求。如果找到一个有效地缓存标识,则从该缓存中服务该请求,并缩短该请求的处理过程,只调用任何已注册的EndRequest处理程序。

9.  PostResolveRequestCache 请求不能从缓存中得到服务,继续下面的处理过程。这时创建一个对应被请求的URL的Http处理程序。如果被请求的是一个.aspx页面,则创建一个页面类型的实例。

10.  根据所请求资源的文件扩展名(在应用程序的配置文件中映射),选择实现 IHttpHandler 的类,对请求进行处理。如果该请求针对从 Page 类派生的对象(页),并且需要对该页进行编译,则 ASP.NET 会在创建该页的实例之前对其进行编译。

11.  PostMapRequestHandler 成功创建对应被请求URL的Http处理程序时,该事件触发。

12.  AcquireRequestState 连接该事件的模块愿意获取该请求的任何状态信息。

13.  PostAcquireRequestState 已经获取状态信息(如Application或session)

14.  PreRequestHandlerExecute在执行一个给定请求的处理程序之前立即爆发。处理程序完成它的工作,并为客户端输出。

15.  为该请求调用合适的 IHttpHandler 类的 ProcessRequest 方法(或异步版 BeginProcessRequest)。例如,如果该请求针对某页,则当前的页实例将处理该请求。

16.  PostRequestHandlerExecute当该处理程序产生响应文本时激发这一事件。

17.  ReleaseRequestState 当处理程序释放状态信息并准备关闭时激发该事件。

18.  PostReleaseRequestState 已经持久地保存了状态(页面执行时被修改过)。这时完成任何有关的响应筛选。

19. 如果定义了 Filter 属性,则执行响应筛选。获取或设置一个包装筛选器对象,该对象用于在传输之前修改 HTTP 实体主体。

20. UpdateRequestCache ASP.NET运行库决定是否应当缓存产生的输出(现在也已经被已注册模块正常筛选过),以便供将来相同请求重用。

21. PostUpdateRequestCache 页面已被保存到输出缓存中

22. EndRequest 该事件作为Http管道的最后一步激发。控制传回到HttpRuntime对象,由它负责将响应真正地转发给客户端。

 

首先简单介绍下Page类

  在.NET Framework中,Page类提供了ASP.NET应用程序从.aspx文件开始创建的所有对象的基本行为。Page类在System.Web.UI命名空间中定义,它派生于TemplateControl类并实现了IHttpHandler接口。TemplateControl类是一个抽象类,它为 Page 类和 UserControl 类提供通用属性和方法。

  由于Page类派生于一个是实现了INamingContainer接口的类,Page类还充当它的所有组成控件的容器。一个控件命名容器实现了INamingContainer接口的第一个父控件。对于任何一个实现了命名容器接口的类,ASP.NET创建一个新的虚拟命名空间,其中保证所有的子控件在整个控件树有唯一的名称。通俗点INamingContainer接口无任何方法,知识保证其子控件有唯一的名称。

  Page类实现IHttpHandler接口的方法,从而可以充当一种特殊类型的HTTP请求(.aspx文件的请求)的处理程序。ASP.NET运行库调用ProcessRequest方法用来处理请求。

  在ASP.NET页面中,runat属性设置为server的任何控件都不能放在<form>标签外。那么是怎么做到确定所有控件不在form外的呢?可以用Page类的VerifyRederingInSeverForm()方法。控件在生成时调用该方法,以确保服务器窗体的主体包含它们。该方法不返回一个值,但是出错的情况下会抛出一个异常。

 

  在ASP.NET页面揭秘(一)中我们提到执行和触发ProcessRequest调用的步骤和事件过程统称为页面生存周期。其实HTTP运行库激活ProcessRequest时便开始执行页面,ProcessRequest启动页面并控制生命期

  页面生命期分三个阶段:建立阶段,回发阶段,结束阶段。每个阶段有一个或多个子阶段,并且有一个或多个事件和步骤引发组成。

一 页面的建立

  当HTTP运行库实例化页面类以便为当前提供服务时,页面构造器创建一个控件树。该控件树连接到页面解析器在查看ASPX源文件后所创建的实际类。处理请求开始时,应设置所有的子控件和页面本征特征(如HTTP上下文,请求对象和响应对象)。

  页面生命期第一步是确定为什么运行库正在处理页面请求。其中原因有多样:正常请求,回发,跨页回发或者回叫。页面对象根据具体原因配置内部状态,并根据请求方法(GET或POST)准备投递的值集合(post value)。这部完成后,页面就准备激发用户代码事件。

1.PreIntit事件

  它是页面生命周期进入点。该事件激发时,页面还没有关联任何的母版页和主题。页面滚动位置已经恢复,投递的数据可以用,并且所有的页面控件已经被实例化且默认地取ASPX源文件中定义的属性值(注意这时控件没有ID,除非在.aspx源文件中显式地设置它)只有这时才可以通过编程方式修改母版页或主题。该事件只有在页面上可用。IsCallBack(该值指示页请求是否是回调的结果),IsCrossPagePostback(获取一个值,该值指示跨页回发中是否涉及该页)和IsPostback(获取一个值,该值指示该页是否正为响应客户端回发而加载,或者它是否正被首次加载和访问)都在这时设置其值。

2.Init 事件

  这时已经设置母版页和主题,并且不能修改。页面处理器,即Page类上的ProcessRequest方法,遍历所有的子控件,使他们有机会以一种上下文相关的方法初始化它们的状态。所有的子控件递归地调用它们的OnInit方法。为控件集合中的每个控件设置命名容器和一个具体的ID。Init事件首先到达子控件,然后到达页面。这个阶段,页面和控件通常开始加载他们的部分状态。然而这时没有恢复视图状态。

3.IntiComplete事件

  这个只有页面才有的事件,表明初始化子阶段的结束。在Init 事件和IntiComplete事件之间只发生一个操作:打开视图状态变更的跟踪功能。它始终使控件能够真正地把所有以编程方式添加到ViewState结合中的数值持久地存储在存储介质中。即没有打开跟踪状态的控件,任何添加到ViewState的值将会在下一次回发时丢失。所有控件在发出Inti事件后立即打开视图状态跟踪,页面也不例外。

4.视图状态恢复

  如果页面由于回发处理,则恢复VIEWSTATE隐藏字段内容。_VIEWSTATE隐藏字段保存着一个请求结束时所有控件视图状态。页面的总体视图状态是一种调用上下文,包含页面最后一次服务器时每个组成控件的状态。(ViewState个可以留到控件相关的知识里介绍)

5.处理投递的数据

  HTTP请求中包装的所有用户数据,即用<form>标签定义的所有输入字段的内容,都在这时进行处理。投递的数据通常采取如下格式:

      TextBox1=text&DropDownList1=selectedItem&Button1=Submit

这是一串用&隔开的名称/值对。这些值装入一个内部使用的集合。页面处理器视图将投递的数据集合中的名称与页面中的控件的ID进行匹配。每找到一个匹配,处理器检查该服务器控件有没有实现 IPostBackDataHanlder接口。如果实现了,则调用该接口的LoadPostData方法,该控件有机会根据投递的数据刷新它的状态。具体说,如果LoadPostData()方法返回true,即状态已被更新,则把该控件添加到一个不同的集合中,以便以后引起关注。

(注:LoadPostData实现IPostBackDataHandler(实现控件数据回传必须要继承该接口)的一个方法,该方法参数NameValueCollection类型的对象装载了客户端提交的数据。另外该方法还会比较控件的旧值和新值返回一个bool类型值,以决定是否执行RaisePostDatachangedEvent方法,即跟新控件里的值,详细请看深入理解.net服务器控件

  如果一个发送的名称与任何一个服务器控件都不匹配,则留下它并临时放在一个不同的集合中,稍后再试。

6.PreLoad事件

  它指页面已经结束系统初级初始化阶段,并且准备进入下一个阶段,即还有机会在该页面中的用户代码中配置页面的执行和呈现。

7.Load事件

  首先它针对页面的引发,然后递归针对所有的子控件引发。页面中的控件在此时创建,并且他们的状态完全反映前一个状态以及从客户端发送的任何数据。页面准备执行所有与页面逻辑和行为有关的初始化代码。这时,访问控件属性和视图状态是绝对安全的。

8处理动态创建的控件

  如果在显示前,页面中的所有控件都有机会完成初始化,页面处理器将再次尝试匹配那些尚未与现有控件匹配的投递值。这主要是应对动态的创建的控件

设想把一个控件动态地添加到页面树上,例如为了响应某个用户动作。每次回发以后重新创建页面,因此与动态创建的控件有关的任何信息会丢失。另一方面,提交页面的窗体时,其中的动态控件定期发送的合法而有效地信息填充。根据设计,第一次投递的数据时,不可能有什么服务器控件匹配动态控件ID。然而,ASP.NET Fromework知道Load事件会创建某些控件。因此有了再次匹配这一说。如果动态控件已经在Load事件中被重建了,现在就可以找到一种匹配,并且该控件可以用投递的数据刷新状态。

 

二 处理回发

  回发机制它涉及到把窗体数据投递到相同页面,然后使用视图状态恢复调用上下文,在服务器上最后一次生成投递页时存在的控件的同一种状态。

  在页面初始化已经完成并已经考虑投递的值以后,会发生某些服务器端事件。事件类型主要有两种。

1.检测控件状态变化

  整个ASP.NET工作机制围绕一个隐含的假设:在浏览器中操作一些HTML输入标签与服务器控件具有一一对应关系。例:<input type=”text”>与<asp:TextBox>。当用户把一些信息输入到元素中后,调用对应的TextBox 控件来处理该投递值。

  对于让LoadPostData方法返回true的所有控件,现在要执行RaisePostDataChangeEvent方法,该方法也属于IPostBackDataHandler接口。该方法通知ASP.NET应用程序控件的状态已经发生变化。

2.执行服务器端回发事件

  任何回发都从某个打算触发一个服务器端动作的客户端动作开始。相信大家对回发事件应经很理解了这里不再多介绍。通俗的说就是能触发服务器端的事件代码的执行。

3.LoadComplete事件

  表明页面准备阶段的结束。任何子控件都不会接受该事件。激发LoadComplete页面进入呈现阶段。

 

三 页面结束

处理回发事件以后,页面准备为浏览器生成输出。

1.PreRender事件

  通过处理该事件,页面和控件可以在呈现输出之前任何更新。PreRender事件首先为页面激发,然后递归地为控件激发。

2.PreRenderConmplete事件

  因为PreRender事件是递归地为所有子控件激发的,所以编程者无法知道何时完成预呈现阶段。而该事件的激发代表上面的事件结束了。

3.SaveStateComple事件

  在每个控件生成页面的标记之前,把页面的当前状态保存到视图状态存储介质。在页面上的控件状态已经全部保存到持久性质时,会触发该事件。

4.生成标记

  为浏览器生成标记是通过调用各组成控件来生成自己的标记来完成的,这些标记将存储到一个缓冲区中。这个阶段没有任何用户事件。

5.Unload事件

  生成阶段之后是一个递归调用,为每个控件引发Unload事件,并最终为页面引发Unload事件。Unload事件存在的目的是在释放页面对象之前执行所有最后的清除工作。典型操作是关闭文件和数据库连接。

 

  相信这里看过之后再读 深入理解.net服务器控件会有进一步理解

 

 

深入理解.net服务器控件

 

控件生命周期

1.初始化(对应Oninit方法)

这里页面通过ProcessRequest方法来递归遍历它的子控件(即页面中的空间,其实页面也算控件)。使子控件依次调用它们的Oninit方法。我们这里可以重写控件的OnInit方法,来扩展控件功能或增加初始化内容。在本阶段还要打开视图状态跟踪功能,调用TrackviewState方法,这样存储在viewState对象里面的值在页面回发时才能正确灰复到控件属性中。

2.加载视图状态(对应LoadViewState方法)

本阶段仅在页面回发时才执行,加载视图状态到控件。在第一次访问页面时我们还没有获得存储到视图状态的状态数据。

3.加载回传数据(对应LoadPostData方法)

在页面回发时执行。LoadPostData实现IPostBackDataHandler(实现控件数据回传必须要继承该接口)的一个方法,该方法参数NameValueCollection类型的对象装载了客户端提交的数据。另外该方法还会比较控件的旧值和新值返回一个bool类型值,以决定是否执行RaisePostDatachangedEvent方法。

客户修改窗体数据进行提交后,接收到的投递的数据是以 “&”符号隔开的一些键值串,页面处理器将投递的数据集合名称与页面控件的ID一一匹配,根据匹配ID检索对应的服务器控件有没有实现IPostBackDataHandler接口,如果实现了就调用控件的LoadPostData方法,给控件刷新其值。

4.装载(对应OnLoad方法)

页面装载时调用Page_Load()事件,在依次调用各个控件OnLoad方法.

5.数据回传事件通知(对应RaisePostDataChangeEvent方法)

在页面回发时执行。该方法也实现了IPostBackDataHandler接口。当bool值为true代表数据更改了,就执行该方法。

6.触发回发事件(对应RaisePostBackEvent方法)

在页面回发时执行。主要是处理引起回发的客户端事件,成功捕获回发的客户端事件进行服务器端的相应处理。也实现了IPostBackDataHandler接口。可以通过本法的参数来判断是哪个控件触发的回发事件,进而执行不同的事件处理逻辑。

7.预呈现(对应OnPreRender方法)

主要完成呈现(Render方法)之前所需要的一些处理。如注册JavaScript脚本和隐藏域控件等。

8.保存视图状态(对应SaveViewState方法)

该方法是把页面控件视图信息进行存储。第一次请求该页面就会执行该操作。

9.呈现(对应Render方法)

主要将控件标记和字符文本输出到服务器控件输出流中。

10.卸载(对应OnUnload方法)

对控件资源清除工作。

可以通过构造一个简单的服务器控件来熟悉它的生命周期

先创建一个控件库(新建项目选择ASP.NET服务器控件)和一个网站,再在类库中添加一个类(添加新建项选择ASP.NET 服务器控件)。在讲下列代码复制到类库中去。在生成该类库并在网站中引用该类库,再在该在网站上新建一个aspx文件,在页面工具箱中直接将控件拖到页面上即可。

 

代码

其实上面过程就算是我们开发了一个控件。了解它,最好的办法是尝试去开发它。

 

开发一个控件首先要选好它要继承的基类

选择基类

Control

控件开发基类,所有控件都直接或间接继承该类。提供了各类控件通用的属性和方法。

WebControl

webcontrol继承了control所有的属性,还增加了布局,可访问性,外观样式等特性。

CompositeControl

如果把现有控件聚合起来创建一个组合控件时,可以继承此类。该类默认实现了INamingContainer接口。

 

控件呈现顺序

 上面介绍到了控件Render阶段主要是将控件标记和字符文本输出到服务器控件流当中。这里可以直接写HTML标记(上面例子就是的)也可以调用每个控件都有的RenderControl方法到输出流。在WebControl中,介绍以下5个函数

RenderControl(HtmlTextWriter writer)

Render(HtmlTextWriter writer)

RenderBeginTag(HtmlTextWriter writer)

RenderContents(HtmlTextWriter writer)

RenderEndTag(HtmlTextWirter writer)

在RenderControl 会内部调用Render,在Render会内部调用RenderBeginTag,RenderContents,RenderEndTag。

其中RenderBeginTag,RenderEndTag可以重写,默认值为<span></span>。它们是用来定义控件起始和结束的标记。RenderContents看英文的意思就明白了。(待续。。。)

posted @   阿玛  阅读(147)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
点击右上角即可分享
微信分享提示