DetailsView控件

以至于让ASP.NET开发人员不满足于此,而是希望它能提供更多功能。DataGrid控件在ASP.NET 2.0中并没有发生太大变化,只是添加了两个分别名为GridView和DetailsView的新控件,它们提供了通常要求DataGrid控件所具有的功能,并且还加入了一些属于它们自己的新功能。

    GridView呈现HTML表的方式与DataGrid一样,但与DataGrid不同的是,GridView可以完全依靠自己来分页和排序。GridView还支持比DataGrid种类更为丰富的列类型(在GridView用语中称为字段类型),并且它们具有更为智能的默认呈现行为,能够自动呈现Boolean值(例如,通过复选框)。GridView也可以容易地与DetailsView搭配使用,以创建主-从视图。GridView控件的主要缺陷是:像DataGrid一样,它通过将信息传回到服务器来完成它该做的大部分工作。

    图6 中的页面结合使用了GridView和DetailsView,以创建Pubs数据库的Titles表的简单主-从视图。SqlDataSource控件为其他控件提供数据,而绑定到DetailsView控件的SqlDataSource中的SelectParameter使DetailsView能够显示GridView中当前选择的记录。可以通过单击GridView的Select按钮(该按钮因标记中的AutoGenerateSelectButton="true"属性而存在)来选择记录。

<%@ 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控件中的元素。图7 列出了受支持的字段类型。特别重要的是ImageField和DropDownListField,它们都可以有效地削减目前开发人员为在DataGrid中包含图像和数据绑定下拉列表而编写的大部分代码。

字段类型描述
AutoGeneratedField默认字段类型
BoundField绑定到数据源指定列
ButtonField显示一个按钮、图片按钮或者链接按钮
CheckBoxField显示一个复选框
CommandField显示一个用于选择或者编辑的按钮
DropDownListField显示一个下拉列表
HyperLinkField显示一个超级链接
ImageField显示一个图片
TemplateField内容由HTML模板来定义

图7 GridView and DetailsView字段类型

新增的管理功能

    ASP.NET 1.x的另一个明显的缺陷(已经在ASP.NET 2.0中得到修复)是根本没有用于管理Web站点的接口(无论是声明性接口还是编程接口)。在过去,更改配置设置意味着启动记事本并编辑Machine.config或Web.config,但现在不再需要这么做了。ASP.NET 2.0具有一个完善的管理API,它简化了读取和写入配置设置的任务。它还包括一个管理GUI,您可以通过在浏览器中请求Webadmin.axd来显示该GUI,如图8所示。


图8 管理GUI

    尽管在撰写本文时尚不完善,但Webadmin.axd被设计为使您可以配置ASP.NET 2.0中包含的各种服务(如成员身份和角色管理服务)、查看Web站点统计信息以及应用安全设置。

成员身份服务

    ASP.NET 2.0中新增的最佳功能之一是新的成员身份服务,它提供了用于创建和管理用户帐户的易于使用的API。ASP.NET 1.x大规模引入了窗体身份验证,但仍然要求您编写相当数量的代码来执行实际操作中的窗体身份验证。成员身份服务填补了ASP.NET 1.x窗体身份验证服务的不足,并且使实现窗体身份验证变得比以前简单得多。

    成员身份API通过两个新的类公开:Membership和MembershipUser。前者包含了用于创建用户、验证用户以及完成其他工作的静态方法。MembershipUser代表单个用户,它包含了用于检索和更改密码、获取上次登录日期以及完成类似工作的方法和属性。例如,下面的语句采用用户名和密码作为参数,并返回true或false来指示它们是否有效。它取代了对ASP.NET 1.x应用程序中、使用Active Directory?或后端数据库来验证凭据的简易方法的调用,如下所示:

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一起提供的一系列登录控件。


图9 Login控件

    图9中所示的Login控件是登录控件系列的核心控件。除了提供具有高度可自定义性的UI以外,它还能够调用Membership.ValidateUser来验证用户名和密码。Login控件还可以调用FormsAuthentication.RedirectFromLoginPage,将用户重定向到他们在被重定向到登录页时尝试到达的页面。然后,FormsAuthentication.RedirectFromLoginPage将发出身份验证Cookie。在本文稍后的部分中,您将看到Login和其他登录控件的工作方式。

角色管理器

    如果不支持基于角色的安全性,那么成员身份服务和登录控件将是不完善的。在ASP.NET 1.x中,要将窗体身份验证与角色结合起来,需要编写代码以将角色信息映射到各个传入的请求。ASP.NET 2.0中新的角色管理器(它可以与成员身份服务配合使用,也可以不与其配合使用)取消了对此类代码的需求,并且简化了基于角色授予用户访问各种资源权限的任务。

    角色管理是基于提供程序的,它通过Web.config启用。角色管理器通过新的Roles类来公开API,该类公开了名为CreateRole、DeleteRole和AddUserToRole等的方法。值得注意的是,您或许永远不需要调用这些方法,因为Webadmin.axd完全能够创建角色、将用户分配给角色以及完成其他任务。一旦启用,基于角色的安全性就能够使用所提供的角色信息以及Web.config文件中的URL身份验证指令来工作—这与ASP.NET 1.x中您已经熟悉的URL身份验证相同。

    既然您已经熟悉了成员身份服务、登录控件以及ASP.NET角色管理器,那么您或许希望看到同时使用这三者的示例。本文可下载的代码示例包含一个两页的应用程序,它演示了Visual Studio 2005样式的窗体身份验证。要部署该应用程序并对其进行测试,请首先将PublicPage.aspx、LoginPage.aspx和Web.config复制到Web服务器的某个虚拟目录中。在该虚拟目录中创建一个名为Secure的子目录,然后将ProtectedPage.aspx和其他Web.config文件复制到该子目录中。

    启动Webadmin.axd,并且将站点配置为使用窗体身份验证,将成员身份和角色服务配置为使用您选择的提供程序。同时,还要创建名为Bob和Alice的用户以及名为Manager和Developer的角色。将Bob指定为Manager角色,将Alice指定为Developer角色。(我不会列出所有步骤,因为在您使用任一方法阅读本文之前,它们很可能会改变。幸运的是,Webadmin.axd相当直观,并且它具有向导,可以引导您完成设置过程。)

    接下来,在浏览器中激活PublicPage.aspx,并单击“View Secret Message”按钮以查看ProtectedPage.aspx。ASP.NET会将您重定向到LoginPage.aspx,该页面使用Login控件来请求用户名和密码。使用Bob的用户名和密码登录。ProtectedPage.aspx应该显示在浏览器窗口中,因为Bob是Manager,并且可以通过Secure目录中的Web.config文件将访问权授予经理。请注意LoginName控件显示的用户名以及LoginStatus控件显示的“Log out”链接。最后,关闭浏览器,然后重新打开它并重新激活PublicPage.aspx。单击“View Secret Message”并以Alice的身份登录。这一次,您将无法到达ProtectedPage.aspx,因为Alice不是经理。

    我使用了一个类似的应用程序来讲述ASP.NET 1.x中的窗体身份验证,但1.x版本要求编写非常多的代码。2.0版本因其简洁而不同寻常,尤其是没有任何用于验证在登录窗体中键入的凭据、或者将用户名映射到角色的代码。如果您仍然不相信,请尝试用ASP.NET 1.x实现同一应用程序!此外,请确保检验Webadmin.axd对Web.config所作的更改。除了其他内容以外,您还应该看到一个启用角色Manager并且可能会指定角色管理提供程序的元素。

    您可能很想知道角色Manager是否经过了到数据库(在其中,角色被存储到每个请求中)的往返行程。值得庆幸的是,答案是“否”。它将角色编码到Cookie中,并且为了保密而将它们加密。如果一个用户对应了众多的角色(这种情况不太可能发生),以至于无法将这些角色编码到一个Cookie中,则该Cookie将包含一个最近使用角色的列表,并且仅在迫不得已时才查询数据库。

个性化

    另一个新增的服务是个性化,它提供了一种现成的解决方案,用于解决存储站点用户的个性化设置问题。目前,此类设置通常存储在Cookie、后端数据库或这两者中。无论这些设置存储在何处,ASP.NET 1.x都不能提供什么帮助。这需要由您来设置和管理后端数据存储,以及使用经过身份验证的用户名、Cookie或其他某种机制来关联个性化数据。

    ASP.NET 2.0个性化服务使得存储各个用户的设置以及随意检索这些设置变得非常容易。该服务基于用户配置文件—您可以使用新的元素在Web.config中予以定义。下面的代码节选自Web.config:

<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缓存依赖性。

新的动态编译模型

    ASP.NET 1.x中引入的众多创新之一是:系统能够在首次访问您的代码时对其进行编译。但是,只有页面能够被自动编译,并且辅助类(如数据访问组件)必须单独编译。

    ASP.NET 2.0扩展了动态编译模型,以便能够自动编译几乎所有的组件。bin目录仍然保留以便实现向后兼容性,但它现在添加了名为Code和Resources的目录。Code目录中的C#和Visual Basic文件以及Resources目录中的RESX和RESOURCE文件被ASP.NET自动编译并缓存在系统子目录中。此外,落入Code目录中的Web服务描述语言(WSDL)文件被编译为Web服务代理,而XML架构定义语言(XSD)文件被编译为类型化数据集。通过Web.config,还可以扩展这些目录以支持其他文件类型。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值