ASP.NET

Asp.net 中 Password 型 TextBox 在服务器赋值[转]

出于安全性考虑,Asp.net 中 Password 型 TextBox 不允许从服务器赋值;

解决方法:this.txtPassword.Attributes.Add("value",Request.Cookies["pwd"].Value);

Web Application Project 模式下的 ProfileCommon 类的问题

  假如我们在 ASP.NET 程序中使用了用户配置文件(Profile),也就是应用程序配置文件(web.config)中包含了配置文件的属性(<profile>节)的定义,那么 ASP.NET 会自动生成一个名为 ProfileCommon 的类,继承于 System.Web.Profile.ProfileBase 类,MSDN 有如下说明:

    ASP.NET 使用 ProfileBase 类创建用于用户配置文件的类。在启动启用了用户配置文件的应用程序时,ASP.NET 会创建一个类型为 ProfileCommon 的新类,该类从 ProfileBase 类继承。强类型访问器被添加到 profile 配置节中为每个属性定义的 ProfileCommon 类中。

  我们在类视图可以看到 ProfileCommon 类的定义,打开一看,看路径,它不放在我们自己程序的目录下,而是放在 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files 目录下的某个目录(和你的项目名称同名)里,Temporary ASP.NET Files 目录是 asp.net 在编译和调试时的临时目录,一般是放那些 ASP.NET 自动生成的代码或 DLL 文件,像上面所说的 ProfileCommon 类文件就放在里面。

  当程序运行时,ProfileCommon 类的一个实例被设置为 ASP.NET 应用程序的 Profile 属性的值。也就是 HttpContext.Profile 属性的值,并为每一个 .aspx 页和 .ascx 页添加了一个 Profile 属性,我们在 Temporary ASP.NET Files 目录下就可在相应页的 .cs 文件找到这些代码:

    // WebUserControl.ascx
    public partial class WebUserControl {
        protected ProfileCommon Profile {
            get {
                return ((ProfileCommon)(this.Context.Profile));
            }
        }

        protected System.Web.HttpApplication ApplicationInstance {
            get {
                return ((System.Web.HttpApplication)(this.Context.ApplicationInstance));
            }
        }
    }

  然后,我们就可以在页上用 Profile 属性来访问用户的配置文件属性的值了:

    protected void Page_Load(object sender, EventArgs e)
    {
        Profile.CartInfo = "Good";

        string user = Profile.UserInfo;
    }

    要注意的是,以上所说的情况只适应于 Web Site 模式,在 Web Application Project 模式里是不支持的。


    Web Application Project 模式也自动生成 ProfileCommon 类(可从 Temporary ASP.NET Files 目录下找到),但是以 Web Site 模式生成,在类视图也不到,也没自动为每一个 .aspx 页和 .ascx 页添加了 Profile 属性,这么一来显示是没法通过页的 Profile 属性去访问配置文件的属性值,通过手工方式把 Temporary ASP.NET Files 目录里的 ProfileCommon 类的代码加到自己的程序里,也同样无法解决这个问题。Visual Studio 2005 SP1 在12月14日已经发布,SP1 已包经含了 Web Application Project!但不知有没把这个特性加上去(今天弄了一天还没把 SP1 装,也有人说 VS 2005 SP1 是 MS 最差劲的补丁程序,安装时间比原版的要长,空间占的多!)。

    还是说说上面所说的问题吧。ASP.NET 没自动生成就得靠自己手工生成了,可以到:

    http://www.gotdotnet.com/workspaces/workspace.aspx?id=406eefba-2dd9-4d80-a48c-b4f135df4127

    下载一个 ASP.Net WebProfile Generator,它是个 VS IDE 外接程序,它会根据你的 Web.config 文件里的<profile>配置节的配置,自动生成类似于 ProfileCommon 类的一个类 WebProfile(具体如何操作看里面的 readme.txt)。生成后最好不要手工去改动这个类,当你的配置文件有改动<profile>节时,只要重新生成一次就行了,更不要把类名改为 ProfileCommon,因为 ASP.Net 一见到有 ProfileCommon 就高兴,就会自动给每个 .aspx 页和 .ascx 页添加一个 Profile 属性,但又没去理会 WebProfile Generator 的意思,最终导致运行时还是有错误。

    自动生成 WebProfile 后,还要在需要读取到配置文件属性的页添加一个属性,以便操作用户配置文件属性:

    public partial class WishList : System.Web.UI.Page
    {
        // 手动添加此属性 **************
        private WebProfile Profile
        {
            get { return new WebProfile(Context.Profile); }
        }
        // **************

        protected void Page_Load(object sender, EventArgs e)
        {
            Profile.UserInfo = "pcvc.net";
        }
    }

    也可以这样:

    string s = WebProfile.Current.MyProperty;
    WebProfile.Current.MyGroup.MyProperty = "value";


    注意,ASP.Net WebProfile Generator 只能用于 Visual Studio 2005 英文版的 Web Application Project 模式下。

使用 Profile 时登录和注销的情况

    当用户有设定配置属性值的时候,Profile 就会向数据源中各数据表添加记录。若用户是第一次设置自定义属性的,会向 aspnet_Applications 表添加一些新记录,从名字就可以看出它是记录应用程序相关信息的,然后再向 aspnet_Users 表添加一条记录,从名字也可以看出它是记录用户信息的,然后再向 aspnet_Profile 表添加一条记录,用户的配置的属性值就存在在这表里面,普通类型(System.String)的值会存储在 PropertyValuesString 字段里,默认是以 XML 序列化格式存储的,复杂的用户自定义类型经二进制序列化后存储在 PropertyValuesBinary 字段里。当然,在定义自定义类型时就要指定其是可序列化的。这样一来,当用户在设定了自己的配置属性值后,就会操作以上三个表(或二个表)。

    在默认情况下,当用户登录的时候,Profile 对象会读取与登录名相对应的 Profile 属性值,也就是说匿名用户的属性值与登录用户的属性值是不同的,同样说明在数据库表里是不同记录的,用户登录后,Profile 会在上面所说到的三个表中添加或检索与登录名对应的属性值。当用户关闭浏览器,在下一次打开网页时就会以匿名用户去搜索属性值,若用户在此之前删除过 IE 浏览器的 Cookies,那么此时登录网页将会以没有设定用户配置属性的状态显示,为什么会这样呢,因为一开始在有启用 Profile 功能的网站中,用户 Profile 是与一个随机生成的号码相关联的,该号码是根据每个用户唯一生成的,它保存在浏览器的 Cookies 中,当你清除了 Cookies,Profile 就会重新生成一个新的号码,并保存在 IE 的 Cookies 里,遗憾的是,aspnet_Users 表和 aspnet_Profile 表不会删除之前的记录。

  那有没有办法在登录后把匿名用户的配置属性值迁移到登录用户去呢?答案是肯定的。可以利用 ProfileModule 类的 MigrateAnonymous事件完成该任务,该事件只能在 Global.asax 文件中进行处理。如:

    // Global.asax

    void Profile_MigrateAnonymous(Object s, ProfileMigrateEventArgs e)
    {
        ProfileCommon anonProfile = Profile.GetProfile(e.AnonymousID);
        Profile.FavoriteColor = anonProfile.FavoriteColor;

        // Clean up anonymous profile
        ProfileManager.DeleteProfile(e.AnonymousID);
        AnonymousIdentificationModule.ClearAnonymousIdentifier();

        // Save profile
        Profile.Save();
    }

    该示例演示在用户登录后将匿名用户的配置属性 FavoriteColor 的值赋给已登录用户的 FavoriteColor 配置属性。若在登录后有修改过 FavoriteColor 属性,在下在次登录时还会被匿名的属性值复盖。在用户注销后,由于原来的匿名用户配置已被清除,所以将处于没设定配置属性的状态,然后用户再修改配置属性,又会向 aspnet_Users 表和 aspnet_Profile 表各添加一条新记录了!

    还有一点就是,虽然匿名用户的配置属性被消除,但在 aspnet_Users 表的记录却没被删除,而只是删除了 aspnet_Profile 表的。

    最后,可以通过 ProfileManager 类来管理这些 Profile 或生成信息报表,如果你愿意也可以手工删除表里的记录,但要有个顺序:aspnet_Profile -> aspnet_Users -> aspnet_Applications。

使用 Profile 对象存储用户配置信息

    ASP.NET 中的 Profile 对象与 Cookie 很相似,都是用于存储持久型信息,但比 Profile 提供更多的功能。

    现在很多网站都提供个性化外观,也就是提供让用户自己定义网页的外观,哪每个用户的配置信息保存在哪呢?Profile 对象就是负责这方面的。默认的情况下,Profile 将这些信息保存在数据库中。在使用的时候只要调用当前 HttpContext 的 Profile 属性即可,Profile 属性是一个 ProfileBase 类实例,ASP.NET 使用 ProfileBase 类创建用于用户配置文件的类。在启动启用了用户配置文件的应用程序时,ASP.NET 会创建一个类型为 ProfileCommon 的新类,该类从 ProfileBase 类继承,所有用户配置属性就存储在这个类里面,同时该也被加载到 HttpContext 的 Profile 属性里。一般地,要实现 Profile 功能,需要二个条件,一是配置 web.config 文件,二是配置数据库。

    配置 web.config 文件

    网站设计者可以根据需要定义可以让用户自定义的属性,如:网页底色、字体大小等等,如:

    <connectionStrings>
      <add name="SqlServices" connectionString="server=(local);uid=sa;pwd=;database=TestProfile" />
    </connectionStrings>

    <profile defaultProvider="SqlProvider">
      <providers>
          <add name="SqlProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="SqlServices" applicationName="TestProfile" description="SqlProfileProvider for TestProfile" />
      </providers>
      <properties>
          <add name="FavoriteColor" allowAnonymous="true" defaultValue="Red" />
          <add name="FontSize" allowAnonymous="true" defaultValue="12px" />
      </properties>
    </profile>

    以上配置信息定义了两个配置属性,一个是 FavoriteColor,默认值为:Red,一个是 FontSize,默认值为:12px。

    配置数据库

    要使数据库支持 Profile 功能,需要向数据库添加一些表和存储过程,当然啦,肯定不用我们自己去定义,使用 aspnet_regsql 工具自动为数据库添加 Profile 的功能支持。该工具位于 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ 里,可以在命令行窗口下输入 aspnet_regsql,然后回车,用向导的方式配置数据库,配置过程很简单,只要选中要配置的数据库,然后一路 Next 就行了,完了看一看数据库,增加了很多表、存储过程和视图,都是以 aspnet_ 开头命名的,有 11 表,55个存储过程,9 个视图,当然啦,这么多东西不是仅仅为了支持 Profile 功能,还有其它功能同样用到这个东西,如:Membership、MemberRoles,这几个功能都是采用 Provider 模式设计的。

    只要配置好以上两项工作,就可以用 Profile 功能了,如:

    // Test.aspx

    <body bgcolor="<%= Profile.FavoriteColor %>">


    以上所存储的 Red、12px 数据都是简单类型(System.String,也是默认的类型),也可以存储自定义的复杂类型(类类型)。

让用户控件实现缓存依赖

用户控件的输出缓存的设置的编程访问主要通过 CachePolicy 属性,该属性获取对该用户控件的缓存参数集合的引用,该参数集合封装为一个 ControlCachePolicy 类。该类提供对 ASP.NET 用户控件的输出缓存的设置的编程访问。要使用 CachePolicy 属性,用户控件必需启用输出缓存,常用启用输出缓存的方法有两种,一是在用户控件中使用 @ OutputCache 指令来启用输出缓存,如:

<%@ OutputCache Duration="100" VaryByParam="none" %>

二是将用户控件嵌入在 PartialCachingControl 实例中,如:

PartialCachingControl pcc = LoadControl("SimpleControl.ascx") as PartialCachingControl;
Controls.Add(pcc);

下面主要说说利用 ControlCachePolicy.Dependency 属性来控制缓存数据过期的问题。

假如一个页面的内容是从数据库读出的,页面在缓存的时间为 100 秒,若数据库表在 100 秒发生的变将不会立即反应到页面上的,100 秒刷新到的数据都是旧的数据,而不是数据库最新的数据,这在一般的应用没有多大的影响,但在一些要求数据比较实时的情况下,是不允许的。然而我们可以通过输出缓存类 ControlCachePolicy 的 Dependency 属性,设置一个缓存依赖项,来监视数据库表的变化,从而使数据表的变化和缓存中的数据达到一致。Dependency 属性是一个 CacheDependency 类实例,CacheDependency 类监视依附性关系,以便在任何这些对象(依赖项)更改时,该缓存项都会自动移除。(未完待续……)

让 Web Application Project 支持中文 VS 2005[已过时]

  众所周知,Visual Studio 2005 的 Web Site 模式,实在有诸多不方便。于是 MS 推出了 Web Application Project,可以同VS 2003 一样,将网站当做一个项目来做,目前 VS 2005 Web Application Project V1.0 已经发布很久了,但还不能支持 VS 2005 中文版,这让像本人一样用惯了中文版(可悲)的朋友来说,还是只有羡慕的份。经过几番周折,终于找到临时的解决方法,也许是最愚蠢的方法吧:

  1. 先装好英文版,选自定义安装,最好是选安装一种语言工具(C#)就行,其它都不要装,反正要卸载的:)。

  2. 安装补丁 VS80-KB915364-X86-ENU.exe。

  3. 安装 WebApplicationProjectSetup.msi。

  4. 卸载英文版。

  5. 安装中文版,完毕。

  整个过程不用重新启动,只要安装英文版时组件不要选择太多,工程还不算大,谁让你喜欢用中文呢。


  注:VS 2005 SP1 已包含 Web Application Project

对字符串进行 MD5 加密

    在 asp 时代,对字符串进行 MD5 方法,均使用网上流行的 MD5 加密函数。

    用 .net 编写程序时,则可以使用 .Net 自带的 MD5 类,MD5 类在于 System.Security.Cryptography 命名空间里,该命名空间提供加密服务,包括安全的数据编码和解码,以及许多其他操作,例如散列法、随机数字生成和消息身份验证。其中包括 HashAlgorithm、MD5、MD5CryptoServiceProvider 等类。

    MD5 类继承于加密哈希算法基类(HashAlgorithm),表示 MD5 哈希算法的所有实现均从中继承的抽象类。

    一般地,使用 MD5 加密服务提供程序类(MD5CryptoServiceProvider)来对字符串进行 MD5 加密:

    public static string Md5(string strPassword, int code)
    {
        MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
        if (code == 16)
            return BitConverter.ToString(hashmd5.ComputeHash(Encoding.Default.GetBytes(strPassword))).Replace("-", "").ToLower().Substring(8, 16);
        else
            return BitConverter.ToString(hashmd5.ComputeHash(Encoding.Default.GetBytes(strPassword))).Replace("-", "").ToLower();
    }

    如果是用于 Web 的,还可以用 System.Web.Security.FormsAuthentication 类的 HashPasswordForStoringInConfigFile 方法:

    public static string Md5(string strPassword, int code)
    {
        if (code == 16)
            return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(strPassword,"MD5").ToLower().Substring(8, 16);
        else
            return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(strPassword,"MD5").ToLower();
    }

CommunityServer 读取 Blog 分析(一)

    首先,会建立 AggregatePostList 类的一个实例,先执行 AggregatePostList 类的构造函数,并执行类中有赋初值的所有语句,因为 AggregatePostList 是继承于 WeblogBaseTemplatedWebControl 类,而 WeblogBaseTemplatedWebControl 类又继承于 TemplatedWebControl 类,而 TemplatedWebControl 类又继承于 WebControl 类,且实现 INamingContainer 接口,所以,严格的说应该一开始是执行这四个类的构造函数(默认的构造函数,即没有参数的构造函数)和这四个类中所有有赋初值的语句。且执行顺序是从基类开始!好,第一个,WebControl的构造函数,输出HTML元素<span id="xxx"></span>,接下来看 TemplatedWebControl 类,该类没有构造函数,再接着看 WeblogBaseTemplatedWebControl 类的构造函数,只有一句:

    _currentUser = CSContext.Current.User;

    获取当前浏览者的各方面信息,详细见 CommunityServer.Components.User 类。

    最后看 AggregatePostList 类的构造函数,哈,空的,过!

    在这个过程中,要注意各类中赋初值的语句,因为有一些信息不知不觉已经初始化,而在后面分析代码却不知是从何而来。

    接下来,应该转到 AggregatePostList 类的 OnLoad 函数,第一句:

    base.OnLoad(e);

    此方法通知服务器控件应执行关联页的每个 HTTP 请求的共同操作,例如设置数据库查询。在页生存期的此阶段,创建并初始化层次结构中的服务器控件,还原视图状态,并且窗体控件反映客户端数据(这一段理解不是很深,不敢多写)。下一句:

    this.EnsureChildControls();

    EnsureChildControls 函数是System.Web.UI.Control类的一个protected virtual void 方法(虚拟方法,提供默认实现)。代码如下:

    protected virtual void EnsureChildControls()
    {

        if (!this.ChildControlsCreated && !this.flags[0x100])
        {
            this.flags.Set(0x100);
            try
            {
                this.ResolveAdapter();

                if (this._adapter != null)
                {
                    this._adapter.CreateChildControls();
                }
                else
                {
                    this.CreateChildControls();
                }
                this.ChildControlsCreated = true;
            }
            finally
            {
                this.flags.Clear(0x100);
            }
        }
    }

    MSDN:

    功能:确定服务器控件是否包含子控件。如果不包含,则创建子控件。

    该方法首先检查 ChildControlsCreated 属性的当前值。如果此值为假,则调用 CreateChildControls 方法。其中:

    ChildControlsCreated 属性:设置或指示是否已创建服务器控件的子控件。

    CreateChildControls 方法:一个 virtual(虚拟)方法,没提供默认实现,一般由开发复合服务器控件或模板服务器控件的用户重写此方法,用于创建自定义控件的子控件。WebControl 类没有重新此方法,那么其它三个类()中必定有一个重写此方法。确实,在 TemplatedWebControl 类就有如下的定义:

    protected override void CreateChildControls()
    {
        Controls.Clear();

        // 1) String Control

        Boolean _skinLoaded = LoadTextBasedControl();

        // 2) Inline Template

        if ( !_skinLoaded )
        {
            _skinLoaded = LoadSkinTemplate();
        }

        // 3) Themed Control

        if (!_skinLoaded)
        {
            _skinLoaded = LoadThemedControl();
        }

        // 4) Default Control

        if ( !_skinLoaded )
        {
            _skinLoaded = LoadDefaultThemedControl();
        }

        // 5) If none of the skin locations were successful, throw.

        if ( !_skinLoaded )
        {
            throw new CSException( CommunityServer.Components.CSExceptionType.SkinNotFound, this.GetType().ToString() );
        }

        if(_skinLoaded)
            AttachChildControls();
    }

    上面说了,CreateChildControls 方法是创建自定义控件的子控件(在此是某个 Web 用户控件)。首先,执行 Controls.Clear() 方法,从当前服务器控件的 ControlCollection 对象中移除所有控件。接着根据不同情况,调用不同的方法创建不同的控件,这些方法都以Load开头,每个方法都被设计为虚拟(virtual)方法。首先是LoadTextBasedControl() 方法,代码如下:

    protected virtual bool LoadTextBasedControl()
    {
        string text = ControlText();

        if(!Globals.IsNullorEmpty(text)) // text 为空或为 null 时 IsNullorEmpty 方法返回真。
        {//有指定 Web 用户控件名称

            Control skin = this.Page.ParseControl(text);

            skin.ID = "_";

            this.Controls.Add(skin);

            return true;
        }

        return false;
    }

    首先,执行 ControlText() 方法,该方法也被设计为虚拟方法,且默认实现是返回 null,代码如下:

    protected virtual string ControlText()
    {
        return null;
    }

    为什么要这样做呢?我认为是为了有更好的扩展性,如:我们要创建的 Web 用户控件的名称需要从数据库读取,那么就可以重写 ControlText() 方法,然后在 ControlText() 方法中从数据库读出并返回控件名称,或通过在 ControlText() 方法用其它方法返回控件名称。在此例,LoadTextBasedControl() 方法返回 false。而一旦调用某个方法创建好子控件后,其它情况将被忽略,直至调用 AttachChildControls() 方法。好,接下来分析调用 LoadSkinTemplate() 方法的情况,当用户控件有出现模板化属性的情况下将会调用 LoadSkinTemplate() 方法,模板的名称和用户控件的类的属性相关联,如 TemplatedWebControl 类就以下定义:

    public ITemplate SkinTemplate
    {
        get
        {
            return _skinTemplate;
        }
        set
        {
            _skinTemplate = value;

            ChildControlsCreated = false;
        }
    }

    private ITemplate _skinTemplate;

    说明 SkinTemplate 就是一个模板属性,在页面中就可以如下引用:

    <Blog:AggregatePostList runat="Server" id="Aggregatepostlist1" NAME="Aggregatepostlist1" EnablePaging="true">
    <SkinTemplate>
        Server control, data-binding syntax, other valid markup
    </SkinTemplate>
    </Blog: AggregatePostList>

Metabuilders.Webcontrols.Masterpages 应用的一点理解

Metabuilders.Webcontrols.Masterpages 由 4 个控件ContentContainer、Content、Region、NoBugForm组成。 ContentContainer 控件可以包含或不包含其它控件,但只能包含 Content 控件。如果包含了 Content 控件,则 Content 控件里的内容将填充一个 Region 控件,Region 控件必需声明在 ContentContainer 控件的 ThemeMasterFile 属性指定的用户用户控件里(或在该控件里有声明 ContentContainer 控件由其 MasterPageFile 指定的用户控件中--可无限循环)。在 Region 控件里可以指定默认内容,也可以不指定,但一定要声明一个 ID 和被包含的 Content 控件的 ID 相同的 Region 控件!如果包含的 Content 控件本身没有的内容,Region 控件是不会使用头尾标记中的内容的。

相关连接:http://www.learnasp.com/freebook/learn/masterpage.aspx

最最最简单的理解 .Net 程序是如何启动的

http://blog.csdn.net/abigfrog/archive/2003/06/09/12805.aspx 有感:


1. .Net 程序是一个拥有标准 PE 头和 IL(Intermediate Language) 代码的 Win32 程序

2. 要运行 .Net 程序,需要安装 .Net 运行期引擎,就是 MSCorEE.DLL (太天真了!)

3. 当运行程序时,操作系统通过 PE 文件里的入口点,判断系统是否安装 .Net Framework 并启动 .Net 运行期引擎

4. 随后将指示操作系统调用 MSCorEE.DLL 里的 _CorExeMain 函数

5. 随后 _CorExeMain 函数开始解析位于 PE 文件中的 IL 代码

6. 解析完,因为 IL 是不能被直接执行的,将指示 .Net 运行期引擎使用即时编译器将 IL 代码编译成本地 CPU 机器代码,并运行

页次:2/2   每页 10 条   共 20 条   9 1 2 :