在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
<h2>This content provided by Subpage.aspx</h2>
</td></tr></table> </asp:Content> 代码1 Subpage.aspx 代码1中所示的应用程序使用母版页来定义出现在每个页面上的页眉和页脚。子页面通过将Content控件插入母版页的ContentPlaceHolder中,从而在页眉和页脚之间插入内容。您应该注意匹配的ID和ContentPlaceHolderID,以及母版页中的@ Master指令。 母版页在ASP.NET对象模型中得到了充分支持。System.Web.UI.Page类的特点是具有一个名为Master的新属性,该属性使子页面可以用编程方式来引用它的母版页以及在其中定义的控件。母版页可以嵌套,并且可以包含能够在子页面中重写的默认内容。 <asp:ContentPlaceHolder ID="Main" RunAt="server">
This is default content that will appear in subpages unless explicitly overridden </asp:ContentPlaceHolder> 此外,应用程序可以在Web.config中指定默认的母版页,如下所示: <configuration>
<system.web> <pages masterPageFile="~/Foo.master" /> </system.web> </configuration>
数据源控件 <html>
<body> <form runat="server"> <asp:SqlDataSource ID="Titles" RunAt="server" ConnectionString="server=localhost;database=pubs;Integrated Security=SSPI" SelectCommand="select title_id, title, price from titles" /> <asp:DataGrid DataSourceID="Titles" RunAt="server" /> </form> </body> </html> SqlDataSource控件定义了数据源以及对它执行的查询,并且DataGrid的DataSourceID属性指向SqlDataSource。当加载该页时,SqlDataSource控件就会执行查询,并将结果提供给DataGrid。 当然,实际操作中的数据绑定很少会如此简单。假设您希望缓存查询结果,或者使用在其他控件中选择的项目来参数化数据库查询。图2 中的页使用一个SqlDataSource,用Northwind的Customers表中列出的国家/地区来填充一个下拉列表,并使用另一个SqlDataSource,用在该下拉列表中选择的国家/地区中的一系列客户来填充一个DataGrid。请注意元素,它指示DataGrid的SqlDataSource从下拉列表中获取@country的值。还请注意绑定到该下拉列表的SqlDataSource中的EnableCaching和CacheDuration属性。这些声明将SELECT DISTINCT查询的结果缓存60秒。 上述示例只是粗浅地探讨了可以通过数据源控件完成的工作。例如,您可以使用存储过程,可以使用从查询字符串、用户输入、会话状态和Cookie中提取的值来参数化查询,并且可以指定控件是否应该使用DataSet或DataReader。因为数据源控件包含数据适配器的功能,所以您甚至可以使用数据源控件来更新数据库。随着ASP.NET 2.0最终发布日期的迫近,读者有望看到大量有关数据源控件的文章。 尽管我所讨论的是数据绑定主题,但您还应该知道ASP.NET 2.0支持简化的数据绑定语法。ASP.NET开发人员可以找到与下面这个给人深刻印象的表达式类似的表达式: <%# DataBinder.Eval (Container.DataItem, "title") %> 在ASP.NET 2.0中,可以按如下形式写一个相同的表达式: <%# Eval("title") %> 除了Eval运算符以外,ASP.NET 2.0还支持名为XPath和XPathSelect(它们使用指向XML文档中数据的XPath表达式)的运算符。 主题与外观(skins) 如果您不使用属性来丰富控件,那么ASP.NET页面可能会显得非常单调。问题在于:迄今为止,一次只能应用一个属性,并且您无法通过成组地设置控件的可视属性来赋予控件主题。ASP.NET 2.0提供了一项新功能,即输入主题和外观。该功能简化了生成精美页面的任务。 要查看主题和外观的工作方式,请将以下指令添加到DataSource2.aspx中,如代码2 所示: <html>
<body> <form runat="server"> <asp:SqlDataSource ID="Countries" RunAt="server" ConnectionString="server=localhost;database=northwind; Integrated Security=SSPI" SelectCommand="select distinct country from customers order by country" EnableCaching="true" CacheDuration="60" /> <asp:SqlDataSource ID="Customers" RunAt="server" ConnectionString="server=localhost;database=northwind; Integrated Security=SSPI" SelectCommand="select * from customers where country=@country" > <SelectParameters> <asp:ControlParameter Name="Country" ControlID="MyDropDownList" PropertyName="SelectedValue" /> </SelectParameters> </asp:SqlDataSource> <asp:DropDownList ID="MyDropDownList" DataSourceID="Countries" DataTextField="country" AutoPostBack="true" RunAt="server" /> <asp:DataGrid DataSourceID="Customers" RunAt="server" /> </form> </body> </html> 代码2 DataSource2.aspx 现在刷新该页面。结果如图1中所示。 图1 主题和外观的工作方式 接下来,赋予该页面完全不同的外观,方法是:添加一个元素,并且更改@ Page指令以指示要使用的页面主题: @ Page指令的新Theme属性以声明方式将主题应用到页面中。还可以使用Page类的Theme属性以编程方式应用主题。主题是外观的集合,而外观是应用于一个控件类型的一组可视属性。BasicBlue和SmokeAndGlass是ASP.NET 2.0附带的几个预定义(或全局)主题中的两个。您可以在Microsoft.NET\Framework\...\ ASP.NETClientFiles\Themes下的子目录中找到它们。 您可以定义自己的主题和外观,并且自定义地将它们部署到应用程序Themes目录的子目录中。每个子目录构成一个主题,并且主题名称与子目录名称相同。一个主题子目录包含一个或多个.skin文件以及该主题使用的任何其他资源(例如,图像文件和样式表)。实际的外观定义包含在.skin文件中,并且非常类似于用来在ASPX文件中声明控件实例的标记。 为说明这一点,请在包含DataSource2.aspx的文件夹中创建一个名为Themes的子目录。在该Themes目录中,创建一个名为ShockingPink的子目录。将以下内容复制到ShockingPink目录中的新建的.skin文件中: <asp:DropDownList runat="server" BackColor="hotpink" ForeColor="white" />
<asp:DataGrid runat="server" BackColor="#CCCCCC" BorderWidth="2pt" BorderStyle="Solid" BorderColor="#CCCCCC" GridLines="Vertical" HorizontalAlign="Left" > <HeaderStyle ForeColor="white" BackColor="hotpink" /> <ItemStyle ForeColor="black" BackColor="white" /> <AlternatingItemStyle BackColor="pink" ForeColor="black" /> </asp:DataGrid> 接下来,将DataSource2.aspx中的@ Page指令更改为: <%@ Page Theme="ShockingPink" %> 上述操作的结果无疑是曾经创建过的最为华丽的Web页之一。 ShockingPink.skin定义了DropDownList和DataGrid控件的默认外观。外观文件不必与它们所属的主题具有相同的名称(尽管它们通常如此)。一个主题可以包含多个.skin文件,而单个.skin文件可以为任意数量的控件类型定义属性。此外,ASP.NET还可以区分默认外观和非默认外观。根据定义,缺少SkinID属性的外观是默认外观。非默认外观包含可以通过控件标记中的SkinID属性引用的SkinID。 新增控件 <%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %> <%@ Import Namespace="System.IO" %> <html> <body> <asp:DynamicImage ID="PieChart" DynamicImageType="ImageBytes" RunAt="server" /> </body> </html> <script language="C#" runat="server"> void Page_Load (Object sender, EventArgs e) { // Create a bitmap and draw a pie chart Bitmap bitmap = new Bitmap (240, 180, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage (bitmap); DrawPieChart (g, Color.White, new decimal[] { 100.0m, 200.0m, 300.0m, 400.0m }, 240, 180); g.Dispose(); // Attach the image to the DynamicImage control MemoryStream stream = new MemoryStream (); bitmap.Save (stream, ImageFormat.Gif); bitmap.Dispose(); PieChart.ImageBytes = stream.ToArray (); } void DrawPieChart (Graphics g, Color bkgnd, decimal[] vals, int width, int height) { // Erase the background SolidBrush br = new SolidBrush (bkgnd); g.FillRectangle (br, 0, 0, width, height); br.Dispose (); // Create an array of brushes SolidBrush[] brushes = new SolidBrush[6]; brushes[0] = new SolidBrush (Color.Red); brushes[1] = new SolidBrush (Color.Yellow); brushes[2] = new SolidBrush (Color.Blue); brushes[3] = new SolidBrush (Color.Cyan); brushes[4] = new SolidBrush (Color.Magenta); brushes[5] = new SolidBrush (Color.Green); // Sum the inputs decimal total = 0.0m; foreach (decimal val in vals) total += val; // Draw the chart float start = 0.0f; float end = 0.0f; decimal current = 0.0m; for (int i=0; i<vals.Length; i++) { current += vals[i]; start = end; end = (float) (current / total) * 360.0f; g.FillPie (brushes[i % 6], 0.0f, 0.0f, width, height, start, end - start); } // Clean up and return foreach (SolidBrush brush in brushes) brush.Dispose (); } </script> 代码4 DynamicImage.aspx ASP.NET 2.0中首次亮相的另一个有趣且非常有用的控件是MultiView控件。与View控件搭配使用时,MultiView可用来创建包含多个逻辑视图的页面。一次只能显示一个视图(其索引被分配给MultiView的ActiveViewIndex属性的那个视图),但您可以通过更改活动视图索引来切换视图。对于使用选项卡或其他控件来让用户在逻辑页之间进行导航的页面而言,MultiViews是非常理想的。 <%@ Page Theme="BasicBlue" %>
<html> <body> <form runat="server"> <asp:SqlDataSource ID="Titles" RunAt="server" ConnectionString="server=localhost;database=pubs; Integrated Security=SSPI" SelectCommand="select title_id, title, price from titles" /> <asp:DropDownList ID="ViewType" AutoPostBack="true" OnSelectedIndexChanged="OnSwitchView" RunAt="server" > <asp:ListItem Text="GridView" Selected="true" RunAt="server" /> <asp:ListItem Text="DetailsView" RunAt="server" /> </asp:DropDownList> <asp:MultiView ID="Main" ActiveViewIndex="0" RunAt="server"> <asp:View RunAt="server"> <asp:GridView DataSourceID="Titles" RunAt="server" /> </asp:View> <asp:View RunAt="server"> <asp:DetailsView DataSourceID="Titles" AllowPaging="true" RunAt="server" /> </asp:View> </asp:MultiView> </form> </body> </html> <script language="C#" runat="server"> void Page_Load (Object sender, EventArgs e) { if (IsPostBack) DataBind (); } void OnSwitchView (Object sender, EventArgs e) { Main.ActiveViewIndex = ViewType.SelectedIndex; } </script> 代码5 MultiView.aspx GridView和DetailsView控件 <%@ Page Theme="BasicBlue" %>
<html> <body> <form runat="server"> <asp:SqlDataSource ID="Titles1" RunAt="server" ConnectionString="server=localhost;database=pubs;Integrated Security=SSPI" SelectCommand="select title_id, title, price from titles" /> <asp:SqlDataSource ID="Titles2" RunAt="server" ConnectionString="server=localhost;database=pubs;Integrated Security=SSPI" SelectCommand="select title_id, title, price from titles where title_id=@title_id" > <SelectParameters> <asp:ControlParameter Name="title_id" ControlID="MyGridView" PropertyName="SelectedValue" /> </SelectParameters> </asp:SqlDataSource> <table><tr><td> <asp:GridView ID="MyGridView" DataSourceID="Titles1" Width="100%" RunAt="server" AutoGenerateColumns="false" SelectedIndex="0" AutoGenerateSelectButton="true" DataKeyNames="title_id" > <Columns> <asp:BoundField HeaderText="Title ID" DataField="title_id" /> <asp:BoundField HeaderText="Book Title" DataField="title" /> <asp:BoundField HeaderText="Price" DataField="price" DataFormatString="{0:c}" NullDisplayText="TBD" /> </Columns> </asp:GridView> </td></tr> <tr><td> <asp:DetailsView DataSourceID="Titles2" RunAt="server" AutoGenerateRows="false" Width="100%" > <Fields> <asp:BoundField HeaderText="Title ID" DataField="title_id" /> <asp:BoundField HeaderText="Book Title" DataField="title" /> <asp:BoundField HeaderText="Price" DataField="price" DataFormatString="{0:c}" NullDisplayText="TBD" /> </Fields> </asp:DetailsView> </td></tr></table> </form> </body> </html> 代码6 MasterDetail.aspx 请注意GridView和DetailsView控件中用于定义字段类型的和元素。这些元素实际上等效于DataGrid控件中的元素。表1列出了受支持的字段类型。特别重要的是ImageField和DropDownListField,它们都可以有效地削减目前开发人员为在DataGrid中包含图像和数据绑定下拉列表而编写的大部分代码。
表1 GridView and DetailsView字段类型 新增的管理功能 图2 管理GUI 尽管在撰写本文时尚不完善,但Webadmin.axd被设计为使您可以配置ASP.NET 2.0中包含的各种服务(如成员身份和角色管理服务)、查看Web站点统计信息以及应用安全设置。 bool isValid = Membership.ValidateUser (username, password);
下面的语句返回一个MembershipUser对象,该对象表示用户名为“jeffpro”的用户: MembershipUser user = Membership.GetUser ("jeffpro");
以下语句检索一个已注册用户的电子邮件地址(假设记录了电子邮件地址): string email = user.Email;
成员身份服务所管理的用户名、密码和其他数据存储在哪里?像ASP.NET 2.0中的几乎所有状态管理服务一样,成员身份是基于提供程序的。提供程序是使服务可以与物理数据源进行交互的模块。ASP.NET 2.0将包含Microsoft Access数据库、SQL Server数据库和Active Directory的成员身份提供程序,并且还可能包含其他数据存储的成员身份提供程序。 默认情况下,成员身份服务使用Access提供程序,并将成员身份数据存储在应用程序的Data子目录中名为AspNetDB.mdb的文件中。可以通过Web.config的部分选择备用提供程序。可以让Webadmin.axd修改Web.config,而不必自己进行修改。下面的内容节选自Web.config(在Webadmin.axd创建了一个名为WhidbeyLogin的SQL Server?数据库,并将成员身份服务配置为使用该数据库之后): <membership defaultProvider="WhidbeyLogin">
<providers> <add name="WhidbeyLogin" type="System.Web.Security.SqlMembershipProvider, ..." connectionStringName="webAdminConnection632112624221191376" applicationName="/Whidbey" requiresUniqueEmail="false" enablePasswordRetrieval="true" enablePasswordReset="false" requiresQuestionAndAnswer="false" passwordFormat="Encrypted" /> </providers> </membership> connectionStringName属性引用了Web.config的新部分中的连接字符串。ASP.NET 2.0将包含加密这部分的Web.config以保护数据库连接字符串的能力。 Webadmin.axd的用途并不仅限于创建数据库和选择成员身份提供程序:它还可以用于创建用户、管理凭据以及其他用途。在Webadmin.axd和成员身份API之间,还存在用于管理站点注册用户的声明性手段和编程手段。这是从ASP.NET 1.x向前迈出的一大步,它在很大程度上将凭据管理的问题留给用户自己去处理。 登录控件 成员身份服务本身就显著减少了验证登录和管理用户所需的代码量,此外还有一系列称为登录控件的新控件使窗体身份验证变得更加容易。登录控件可以与成员身份服务配合使用,也可以不与其配合使用,但它们与该服务之间的集成性非常好,以至于当登录控件与成员身份服务一起使用时,一些基本任务(例如,验证用户名和密码以及用电子邮件发送遗忘的密码)通常不必编写任何代码就可以完成。“新增控件”提要栏包含了计划随ASP.NET 2.0一起提供的一系列登录控件。 图3 Login控件 图3中所示的Login控件是登录控件系列的核心控件。除了提供具有高度可自定义性的UI以外,它还能够调用Membership.ValidateUser来验证用户名和密码。Login控件还可以调用FormsAuthentication.RedirectFromLoginPage,将用户重定向到他们在被重定向到登录页时尝试到达的页面。然后,FormsAuthentication.RedirectFromLoginPage将发出身份验证Cookie。在本文稍后的部分中,您将看到Login和其他登录控件的工作方式。 角色管理器 <profile>
<properties> <add name="Theme" /> <add name="Birthday" Type="System.DateTime" /> <add name="LoginCount" Type="System.Int32" defaultValue="0" /> </properties> </profile> 它定义了一个包含三个属性的配置文件:一个名为Theme的字符串,一个名为Birthday的DateTime值,以及一个名为LoginCount的整数。后面这个属性被赋予默认值0。 在运行时,您可以使用页面的Profile属性(该属性引用包含该配置文件中定义的属性的动态编译类的实例)来访问当前用户的这些属性。例如,下列语句可从当前用户的配置文件中读取属性值: string theme = Profile.Theme;
DateTime birthday = Profile.Birthday; int logins = Profile.LoginCount; 还可以将值赋予配置文件属性: Profile.Theme = "SmokeAndGlass";
Profile.Birthday = new DateTime (1959, 9, 30); Profile.LoginCount = Profile.LoginCount + 1; 个性化服务的一个明显优势是强类型化。另一个优势在于个性化数据是按需读写的。请将此与会话状态(无论是否使用,都会将其加载并保存到每个请求中)进行对比。但是,个性化服务的最大优势可能在于您不必显式地将数据存储在任何位置;系统会替您完成该工作,并且它会永久性地存储数据,以便数据在您需要时随时可用。配置文件不会像会话那样超时。 那么,个性化数据存储在哪里呢?这要依具体情况而定。个性化服务基于提供程序,因此您可以将其配置为使用任何可用的提供程序。ASP.NET 2.0将至少附带两个个性化提供程序:一个用于Access,另一个用于SQL Server。如果您不另行指定,则个性化服务将使用Access提供程序,默认情况下,该提供程序会将个性化数据存储在本地Data\AspNetDB.mdb中。您可以通过修改Web.config(手动或使用Webadmin.axd)来改用SQL Server数据库。如果您不希望将个性化数据存储在Access数据库或SQL Server数据库中,则可以编写自己的提供程序。 默认情况下,ASP.NET使用经过身份验证的用户名作为所存储的个性化数据的键,但您也可以将其配置为支持匿名用户。首先,通过将以下语句添加到Web.config中来启用匿名标识: <anonymousIdentification enabled="true" /> 然后,将allowAnonymous="true"添加到您要为匿名用户存储的配置文件属性中: <name="Theme" allowAnonymous="true" /> 现在,Theme属性可以作为个性化设置使用,而无论站点的调用方是否经过了身份验证。 默认情况下,匿名标识使用Cookie来标识回返用户。由支持的属性可以用各种方式来配置这些Cookie。例如,您可以指定Cookie名称,并指明是否应该将该Cookie的内容加密。您还可以将个性化服务配置为使用无Cookie的匿名标识,因此它将依靠URL Munging来标识回返用户。甚至还存在一个自动检测选项:如果请求浏览器支持Cookie,则使用Cookie;如果不支持,则使用URL Munging。 要查看个性化的工作方式,请运行本文随附的下载资料中的Personalize.aspx示例。它会让站点的每个访问者选择一个主题,然后记录该主题,并且每当该访问者返回时都将应用该主题。请注意,该主题是在页面的PreInit事件(它是一个新事件,它的激发时间甚至早于Init)中以编程方式应用于该页面的。 在您运行该示例之前,需要启用匿名标识,并定义一个包含名为Theme的字符串属性的配置文件。以下代码行显示了执行上述两项任务的Web.config文件: <configuration>
<system.web> <anonymousIdentification enabled="true" /> <profile> <properties> <property name="Theme" allowAnonymous="true" /> </properties> </profile> </system.web> </configuration> SQL缓存依赖性 ASP.NET 1.x中令人遗憾地缺少的另一项功能是数据库缓存依赖性。可以将ASP.NET应用程序缓存中放置的项目与其他缓存项目联系起来,或者与文件系统中的对象联系起来,但不能与数据库实体联系起来。ASP.NET 2.0通过引入SQL缓存依赖性来纠正这一由于疏忽而造成的错误。 SQL缓存依赖性由新的SQLCacheDependency类的实例表示。它们的用法非常简单。下面的语句将一个名为ds的数据集插入到应用程序缓存中,并且在该数据集和Northwind数据库的Products表之间创建依赖性: Cache.Insert ("ProductsDataSet", ds,new SqlCacheDependency ("Northwind", "Products");
如果Products表的内容改变,则ASP.NET会自动删除该数据集。 SQL缓存依赖性还可以与ASP.NET输出缓存配合使用。下面的指令指示ASP.NET缓存来自包含页面的输出,直至Products表的内容改变或者满60秒为止(满足任一条件即可): <%@ OutputCache Duration="60" VaryByParam="None"
SqlDependency="Northwind:Products" %> SQL缓存依赖性适用于SQL Server 7.0、SQL Server 2000和即将问世的SQL Server 2005。对于SQL Server 2005,无需进行任何准备;但必须将SQL Server 7.0和SQL Server 2000数据库配置为支持SQL缓存依赖性。准备工作涉及到创建数据库触发器,以及创建一个特殊的表,以供ASP.NET在确定是否已经发生更改时参考。该表由一个后台线程使用可配置的轮询间隔(默认为5秒钟)来定期轮询。在SQL Server 2005中,要检测更改,既不需要特殊的表,也不需要轮询。此外,SQL Server 2005缓存依赖性可以在行级应用,而SQL Server 7.0和SQL Server 2000缓存依赖性在表级工作。您可以使用Aspnet_regsqlcache.exe工具或Webadmin.axd来准备数据库,以使其支持SQL缓存依赖性。 新的动态编译模型 Hello.aspx <%@ Page CompileWith="Hello.aspx.cs" ClassName="MyPage" %> <html> <body> <form runat="server"> <asp:TextBox ID="Input" RunAt="server" /> <asp:Button Text="Test" OnClick="OnTest" RunAt="server" /> <asp:Label ID="Output" RunAt="server" /> </form> </body> </html> Hello.aspx.cs using System; partial class MyPage { void OnTest (Object sender, EventArgs e) { Output.Text = "Hello, " + Input.Text; } } 代码7 Codebehind模型 客户端回调管理器 ASP.NET 2.0中我最喜欢的功能之一就是由新的客户端回调管理器提供的“轻量级回发”功能。在过去,ASP.NET页面必须回发给服务器才能调用服务器端代码。回发是低效的,因为它们将包含由页面控件生成的所有回发数据。它们还强制页面刷新,从而导致不雅观的闪烁。 ASP.NET 2.0引入了客户端回调管理器,它使页面无需完全回发就可以回调到服务器。回调是异步的,并且通过XML-HTTP来完成。它们不包含回发数据,并且不会强制页面刷新。(在服务器端,页面像平常一样执行至PreRender事件,但在即将呈现任何HTML之前停止。)它们确实需要支持XML-HTTP协议的浏览器(这通常意味着Microsoft Internet Explorer 5.0或更高版本)。 使用客户端回调管理器涉及三个步骤。首先,调用Page.GetCallbackEventReference以获取对某个特定函数(可以从客户端脚本中调用该函数,以执行到服务器的XML-HTTP回调)的引用。ASP.NET提供了该函数的名称和实现。其次,在客户端脚本中编写一个将在回调返回时调用的方法。方法名称是传递给GetCallbackEventReference的参数之一。第三,在页面中实现ICallbackEventHandler接口。该接口包含一个方法—RaiseCallbackEvent,当回调发生时,该方法将在服务器端调用。RaiseCallbackEvent所返回的字符串将被返回到第二步所述的方法。 代码8中的代码显示了客户端回调的工作方式,并且演示了它们的一个非常实际的用途。该页面显示了一个请求姓名和地址的窗体。在Zip Code字段中键入378xx或379xx邮政编码,然后单击Autofill按钮,City字段中将显示一个名称。值得注意的是,该页面会返回到服务器以获取城市名称,但它使用客户端回调而不是完全回发来完成此工作。在实际操作中,它可以找到某个数据库以将邮政编码转换为城市名称。请注意,该页面并不像页面在回发到服务器时通常所做的那样进行重新绘制。相反,更新是快速且简洁的! <%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>
<html> <body> <h1>Please Register</h1> <hr> <form runat="server"> <table> <tr> <td>First Name</td> <td><asp:TextBox ID="FirstName" RunAt="server" /></td> <td></td> </tr> <tr> <td>Last Name</td> <td><asp:TextBox ID="LastName" RunAt="server" /></td> <td></td> </tr> <tr> <td>Address 1</td> <td><asp:TextBox ID="Address1" RunAt="server" /></td> <td></td> </tr> <tr> <td>Address 2</td> <td><asp:TextBox ID="Address2" RunAt="server" /></td> <td></td> </tr> <tr> <td>City</td> <td><asp:TextBox ID="City" RunAt="server" /></td> <td></td> </tr> <tr> <td>State</td> <td><asp:TextBox ID="State" RunAt="server" /></td> <td></td> </tr> <tr> <td>Zip Code</td> <td><asp:TextBox ID="Zip" RunAt="server" /></td> <td><asp:Button ID="AutofillButton" Text="Autofill" RunAt="server" /></td> </tr> </table> </form> </body> </html> <script language="javascript"> // Function called when callback returns function __onCallbackCompleted (result, context) { // Display the string returned by the server's RaiseCallbackEvent // method in the input field named "City" document.getElementById ('City').value = result; } </script> <script language="C#" runat="server"> void Page_Load (Object sender, EventArgs e) { // Get callback event reference (e.g., "__doCallback (...)") string cbref = GetCallbackEventReference (this,"document.getElementById ('Zip').value", "__onCallbackCompleted", "null", "null"); // Wire the callback event reference to the Autofill button with // an onclick attribute (and add "return false" to event reference // to prevent a postback from occurring) AutofillButton.Attributes.Add ("onclick",cbref + "; return false;"); } // Server-side callback event handler string ICallbackEventHandler.RaiseCallbackEvent (string arg) { if (arg.StartsWith ("378")) return "Oak Ridge"; else if (arg.StartsWith ("379")) return "Knoxville"; else return "Unknown"; } </script> 代码8callback.aspx 验证组 <html>
<body> <form runat="server"> <h1>New Users</h1> <table> <tr> <td>User Name</td> <td><asp:TextBox ID="NewUserName" RunAt="server" /></td> <td><asp:RequiredFieldValidator ValidationGroup="NewUsers" ControlToValidate="NewUserName" ErrorMessage="Required" RunAt="server" /></td> </tr> <tr> <td>Password</td> <td><asp:TextBox ID="NewPassword1" TextMode="Password" RunAt="server" /></td> <td><asp:RequiredFieldValidator ValidationGroup="NewUsers" ControlToValidate="NewPassword1" ErrorMessage="Required" RunAt="server" /></td> </tr> <tr> <td>Retype Password</td> <td><asp:TextBox ID="NewPassword2" TextMode="Password" RunAt="server" /></td> <td><asp:RequiredFieldValidator ValidationGroup="NewUsers" ControlToValidate="NewPassword2" ErrorMessage="Required" RunAt="server" /></td> </tr> <tr> <td>E-Mail Address</td> <td><asp:TextBox ID="NewEMail" RunAt="server" /></td> <td><asp:RequiredFieldValidator ValidationGroup="NewUsers" ControlToValidate="NewEMail" ErrorMessage="Required" RunAt="server" /></td> </tr> <tr> <td></td> <td><asp:Button ValidationGroup="NewUsers" Text="Create Account" OnClick="OnCreateAccount" RunAt="server" /></td> <td></td> </tr> </table> <hr> <h1>Existing Users</h1> <table> <tr> <td>User Name</td> <td><asp:TextBox ID="UserName" RunAt="server" /></td> <td><asp:RequiredFieldValidator ValidationGroup="ExistingUsers" ControlToValidate="UserName" ErrorMessage="Required" RunAt="server" /></td> </tr> <tr> <td>Password</td> <td><asp:TextBox ID="Password" TextMode="Password" RunAt="server" /></td> <td><asp:RequiredFieldValidator ValidationGroup="ExistingUsers" ControlToValidate="Password" ErrorMessage="Required" RunAt="server" /></td> </tr> <tr> <td></td> <td><asp:Button ValidationGroup="ExistingUsers" Text="Log In" OnClick="OnLogIn" RunAt="server" /></td> <td></td> </tr> </table> </form> </body> </html> <script language="C#" runat="server"> void OnCreateAccount (Object sender, EventArgs e) {} void OnLogIn (Object sender, EventArgs e) {} </script> 代码9 ValidationGroups2.aspx 跨页面发送 有关ASP.NET 1.x的最多抱怨是只允许页面回发到其本身。在版本2.0中,这一点通过引入跨页面发送而得到改变。要设置跨页面发送,您需要使用导致回发发生的控件的PostBackUrl属性来指定目标页面,如PageOne.aspx中的以下代码所示: <html>
<body> <form runat="server"> <asp:TextBox ID="Input" RunAt="server" /> <asp:Button Text="Test" PostBackUrl="PageTwo.aspx" RunAt="server" /> </form> </body> </html> 当被单击时,PageOne.aspx中的按钮将回发到PageTwo.aspx: <html>
<body> <asp:Label ID="Output" RunAt="server" /> </body> </html> <script language="C#" runat="server"> void Page_Load (Object sender, EventArgs e) { TextBox input = (TextBox) PreviousPage.FindControl ("Input"); Output.Text = "Hello, " + input.Text; } </script> PageTwo.aspx使用Page类的新PreviousPage属性来获取对起始页面的引用。对FindControl的简单调用将返回对PageOne.aspx中声明的TextBox的引用,以便可以检索用户的输入。 默认情况下,System.Web.UI.Page.PreviousPage返回对引起回发的页面的弱类型化引用。但是,如果PageOne.aspx是唯一能够向PageTwo.aspx发送的页面,则PageTwo.aspx可以使用新的@ PreviousPageType指令来获取对PageOne.aspx的强类型化访问,如下面的代码所示: <%@ PreviousPageType TypeName="ASP.PageOne.aspx" %>
... 小结 ASP.NET 2.0还包含其他我尚未讨论的新功能。例如,内置的站点计数器服务使您能够记录站点使用情况的统计信息,并且在Webadmin.axd中或者在您自己的自定义GUI中查看它们。新的Web组件子系统提供了一个用于构建SharePoint服务器样式门户的框架。 现在正是学习ASP.NET 2.0的最佳时机,因为要在目前规划能够在将来轻松升级的体系结构,需要知道哪些功能即将问世(以及哪些功能不会问世)。您的ASP.NET 1.x应用程序无需修改就可以在2.0版本上运行,因为Microsoft已经允诺新平台将向后兼容旧平台。但是,未来将属于ASP.NET 2.0,而这一未来将意味着更加丰富的功能和更少的代码。有什么理由不接受它呢? |
请发表评论