Cuyahoga添加模块

Cuyahoga

国外的开源CMS一般都是基于模块设计的 ,好处是可以随意定制自己的页面和模块,这样在以后的应用中就能够灵活的满足变化的功能需求. 一个模块齐全的CMS如DNN , Rainbow就可以快速搭建符合需求的系统.

下面就来介绍如何为Cuyahoga这个著名的开源网站框架加入具有后台管理的公告模块.可以参考这篇如何在Cuyahoga中新增一个简单的功能模块了解基础的步骤.

为Cuyahoga开发自定义模块时,你可以选择任何数据访问策略.然而Cuyahoga本身是使用NHibernate作为数据持久层,可以做到支持多数据库. 采用Castle.Windsor进行依赖注入,降低模块之间的耦合. 我们的数据访问层也将用NHibernate实现.

最终项目的目录结构如下:

主要步骤如下
1 .创建一个Sql文件(Install.sql)用来安装数据表及添加模块的相关信息 , 该sql文件会在安装模块时,由Cuyahoga自动执行.也可以手工执行进行安装.

install.sql
<!–<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
–>IF NOT EXISTS (SELECT * FROM sysobjects WHERE id = OBJECT_ID(N[cm_Announcements]AND OBJECTPROPERTY(id, NIsUserTable= 1)
 
BEGIN
CREATE TABLE [cm_Announcements] (
    
[AnnouncementsID] [int] IDENTITY (1,1)NOT NULL ,
    
[sectionid] [int] NOT NULL ,
    
[createdby] [nvarchar] (100NULL ,//公告作者
    
[Title] [nvarchar] (150NULL ,//公告标题
    inserttimestamp 
datetime DEFAULT current_timestamp NOT NULL,
    updatetimestamp 
datetime DEFAULT current_timestamp NOT NULL,
    
    
CONSTRAINT [PK_cm_Announcements] PRIMARY KEY  NONCLUSTERED 
    (
        
[AnnouncementsID]
    ),
    
CONSTRAINT [FK_cm_Announcements_cm_Modules] FOREIGN KEY 
    (sectionid) 
REFERENCES cuyahoga_section (sectionid)
)
END
GO
/*加入模块信息*/
INSERT INTO cuyahoga_moduletype ([name], assemblyname, classname, path, editpath, inserttimestamp, updatetimestamp) VALUES 
(
AnnouncementsCuyahoga.Modules.AnnouncementsCuyahoga.Modules.Announcements.AnnouncementsModule
Modules/Announcements/Announcements.ascxModules/Announcements/EditAnnouncements.aspxcurrent_timestampcurrent_timestamp)
GO
/*加入模块版本信息*/
INSERT INTO cuyahoga_version (assembly, major, minor, patch) VALUES (Cuyahoga.Modules.Announcements150);
go

2.创建域模型 在本例中是实体类

Announcement.cs
<!–<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
–>using System;
using Cuyahoga.Core.Domain;

namespace Cuyahoga.Modules.Announcements.Domain
{
    public class Announcement
    {
        private 
int _id;
        private string _title;
        private string _content;
        private 
DateTime _expiredate;
        private Section _section;
        private 
User _createdBy;
        private 
DateTime _updateTimestamp;

        /// <summary>
        
/// Property Id (int)
        
/// </summary>
        
public int Id
        {
            get { 
return this._id; }
            
set { this._id = value; }
        }
        
/// <summary>
        
/// Property Title (string)
        
/// </summary>
        
public string Title
        {
            get { 
return this._title; }
            
set { this._title = value; }
        }
        
/// <summary>
        
/// Property Section (Section)
        
/// </summary>
        
public Section Section
        {
            get { 
return this._section; }
            
set { this._section = value; }
        }
        
/// <summary>
        
/// Property CreatedBy (User)
        
/// </summary>
        
public User CreatedBy
        {
            get { 
return this._createdBy; }
            
set { this._createdBy = value; }
        }
        
/// <summary>
        
/// Property UpdateTimestamp (DateTime)
        
/// </summary>
        
public DateTime UpdateTimestamp
        {
            get { 
return this._updateTimestamp; }
            
set { this._updateTimestamp = value; }
        }
        
public Announcement()
        {
            this._id 
= 1;
        }
    }
}

3.创建映射文件

Announcement.hbm.xml
<!–<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
–>xml version=”1.0″ encoding=”utf-8″  >
<hibernate-mapping xmlns=”urn:nhibernate-mapping-2.0″>
  
<class name=”Cuyahoga.Modules.Announcements.Domain.Announcement, Cuyahoga.Modules.Announcements” table=”cm_Announcements”>
    
<id name=”Id” column=”Announcementsid” type=”Int32″ unsaved-value=”-1″>
      
<generator class=”native”>
        
<param name=”sequence”>cm_Announcements_Announcementsid_seq</param>
      
</generator>
    
</id>
    
<timestamp name=”UpdateTimestamp” column=”updatetimestamp” />
    
<property name=”Title” column=”title” type=”String” length=”150″ />
    
<many-to-one name=”Section” class=”Cuyahoga.Core.Domain.Section, Cuyahoga.Core” column=”sectionid” not-null=”true” />
    
<many-to-one name=”CreatedBy” class=”Cuyahoga.Core.Domain.User, Cuyahoga.Core” column=”createdby” not-null=”true” />
  
</class>
</hibernate-mapping>

4.创建公告模块的核心控制类

AnnouncementsModule.cs
<!–<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
–>using System;
using System.Collections;
using System.Xml;
using System.Xml.XPath;
using System.Net;
using System.Web;
using System.Text;
using System.IO;
using System.Threading;

using NHibernate;
using Castle.Services.Transaction;
using Castle.Facilities.NHibernateIntegration;

using log4net;

using Cuyahoga.Core;
using Cuyahoga.Core.Domain;
using Cuyahoga.Core.Service;
using Cuyahoga.Core.Util;
using Cuyahoga.Web.Util;
using Cuyahoga.Web.Components;
using Cuyahoga.Modules.Announcements.Domain;

namespace Cuyahoga.Modules.Announcements
{
    
//采用Facilities管理事务
    [Transactional]
    
public class AnnouncementsModule : ModuleBase, INHibernateModule
    {
        
private static readonly ILog log = LogManager.GetLogger(typeof(AnnouncementsModule));
        
private int _cacheDuration;
        
private ISessionManager _sessionManager;

        //该模块需要用到NHibernate session manager提供的服务 进行依赖注入
        public AnnouncementsModule(ISessionManager sessionManager)
        {
            
this._sessionManager = sessionManager;
        }

        public override void ReadSectionSettings()
        {
            
base.ReadSectionSettings();
            
// Set dynamic module settings
            this._cacheDuration = Convert.ToInt32(base.Section.Settings[CACHE_DURATION]);
        }

        ///不创建子事务
        [Transaction(TransactionMode.RequiresNew)]
        
public virtual IList GetAllAnnouncements()
        {
            ISession session 
= this._sessionManager.OpenSession();
            
string hql = from Announcement f where f.Section.Id = :sectionId;
            IQuery q 
= session.CreateQuery(hql);
            q.SetInt32(
sectionIdbase.Section.Id);
            
return q.List();
        }

        [Transaction(TransactionMode.RequiresNew)]
        public virtual Announcement GetAnnouncementsById(int AnnouncementsID)
        {
            ISession session 
= this._sessionManager.OpenSession();
            
return (Announcement)session.Load(typeof(Announcement), AnnouncementsID);
        }

        [Transaction(TransactionMode.RequiresNew)]
        public virtual void SaveAnnouncement(Announcement announcements)
        {
            ISession session 
= this._sessionManager.OpenSession();
            session.SaveOrUpdate(announcements);
        }

        [Transaction(TransactionMode.RequiresNew)]
        public virtual void DeleteAnnouncements(Announcement announcements)
        {
            ISession session 
= this._sessionManager.OpenSession();
            session.Delete(announcements);
        }
    }
}

5.创建用于前台显示的用户控件 用来显示公告的标题 作者和发布时间.

Announcements.ascx
<!–<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
–><%@ Control Language=C# AutoEventWireup=true Codebehind=Announcements.ascx.cs
    Inherits
=Cuyahoga.Modules.Announcements.Web.Announcements %>
<asp:repeater id=rptAnnouncementItems runat=server enableviewstate=False>
    
<itemtemplate>
            
<div class=genericdetails style=width:100%>
            
<marquee  direction=left >
                
<asp:label id=lblTitle runat=server><%# DataBinder.Eval(Container.DataItem, Title)%></asp:label>
                
<asp:label id=lblAuthor runat=server>作者:<%# DataBinder.Eval(Container.DataItem, CreatedBy.FullName)%></asp:label>
                
<asp:label id=lblTime runat=server>发布时间:<%# DataBinder.Eval(Container.DataItem, UpdateTimestamp)%></asp:label>
            
</marquee>
            
</div>
    
</itemtemplate>
</asp:repeater>

Announcements.ascx.cs
<!–<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
–>using System;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

using Cuyahoga.Core.Util;
using Cuyahoga.Web.UI;
using Cuyahoga.Modules.Announcements.Domain;

namespace Cuyahoga.Modules.Announcements.Web
{
    
public partial class Announcements : BaseModuleControl
    {
        
private AnnouncementsModule _module;
        
protected void Page_Load(object sender, EventArgs e)
        {
            
if (!this.IsPostBack && !base.HasCachedOutput)
            {
                
this._module = base.Module as AnnouncementsModule;
                
this.rptAnnouncementItems.DataSource = this._module.GetAllAnnouncements();
                
this.rptAnnouncementItems.DataBind();
            }
        }
    }
}

6.创建公告管理的列表页面

EditAnnouncements.aspx
<!–<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
–><%@ Page Language=C# AutoEventWireup=true Codebehind=EditAnnouncements.aspx.cs
    Inherits
=Cuyahoga.Modules.Announcements.Web.EditAnnouncements %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
    
<title>公告管理页面</title>
</head>
<body>
    
<form id=”Form1″ method=”post” runat=”server”>
        
<div id=”moduleadminpane”>
            
<h1>
                公告管理
</h1>
            
<table class=”tbl”>
                
<asp:Repeater ID=”rptAnnouncements” runat=”server” OnItemDataBound=”rptFiles_ItemDataBound”>
                    
<HeaderTemplate>
                        
<tr>
                            
<th>
                                公告标题
</th>
                            
<th>
                                作者
</th>
                            
<th>
                                发布日期
</th>
                            
<th>
                            
</th>
                        
</tr>
                    
</HeaderTemplate>
                    
<ItemTemplate>
                        
<tr>
                            
<td>
                                
<%# DataBinder.Eval(Container.DataItem, Title%>
                            
</td>
                            
<td>
                                
<%# DataBinder.Eval(Container.DataItem, CreatedBy.FullName)%>
                            
</td>
                            
<td>
                                
<asp:Literal ID=”litDateModified” runat=”server”></asp:Literal></td>
                            
<td>
                                
<asp:HyperLink ID=”hplEdit” runat=”server”>修改</asp:HyperLink>
                            
</td>
                        
</tr>
                    
</ItemTemplate>
                
</asp:Repeater>
            
</table>
            
<br />
            
<input id=”btnNew” type=”button” value=”新的公告” runat=”server” name=”btnNew”/>
        
</div>
    
</co

(英文转载)最热门的HTML5教程

Most Wanted HTML 5 Tutorials

Posted by Jillz on January 18th, 2010

 

原文地址:http://smashingwebs.com/ p=217

 

 

We just got some fabulous CSS3 tutorials.. Now all you need is to have some HTML 5 Tutorials. HTML 5 is the most modern version of Html that you must learn. So here I have them for you guys.. :) I hope this will help you to understand more. Your comments are very essential for my improvement. So Kindly do comment here.

1. Create a simple web page layout with HTML 5!

2. HTML 5 Visual Cheat Sheet by Woork

3. Web Designers’ Browser Support Checklist

4. webOS HTML5 Database Storage Tutorial

5. HTML5 Doctor, helping you implement HTML5 today

6. Rounded corners on HTML 5 elements

7. Designing a Blog with HTML5

8. HTML 5 Cheat Sheet

9. Designing a Blog with HTML 5

10. Coding an HTML 5 Layout From Scratch

11. Preparing for HTML 5 with Semantic Class Names

12. HTML 5: Nav Ambiguity Resolved

13.  A Basic HTML 5 Tutorial To Show Simple Page Structure

14. HTML 5 Visual Cheat Sheet by Woork

15. HTML 5 Pocket Book

You can also suggest some nice HTML 5 tutorials if you have some. Lets make it large :)

 

FreeTextBox使用详解

版本: FreeTextBox 3.1.1 ASP.NET1.1
1.下载 FreeTextBox 3.1.1 (released 2005/11/08)
http://www.freetextbox.com/downloads.aspx
2. 安装
FreeTextBox 3.0以上版本均支持内部模式,即图片资源和javascript都集成在dll中,
本文仅探讨内部模式(Internal Resources).
1) 把FTBv3-1-1\Framework-1.1\FreetextBox.dll拷入bin目录.
2) 在项目中添加FreetextBox.dll的dll引用
3) Web.config加入如下代码
< xml version=”1.0″ encoding=”utf-8″  >
<configuration>
<httpHandlers>
<add verb=”GET” path=”FtbWebResource.axd” type=”FreeTextBoxControls.AssemblyResourceHandler, FreeTextBox” />
</httpHandlers>
</system.web>
</configuration>
3. 使用FreeTextBox
1) aspx页面顶上
<%@ Register TagPrefix=”FTB” Namespace=”FreeTextBoxControls” Assembly=”FreeTextBox” %>
2) 调用
<FTB:FreeTextBox id=”FreeTextBox1″ runat=”Server” />
3)工具栏皮肤
ToolbarStyleConfiguration = Offoce2003/OfficeXP/Office2000/MAC
4) 得到保存编辑的内容
private void InitializeComponent()
{
this.FreeTextBox1.SaveClick += new System.EventHandler(this.FreeTextBox1_SaveClick);
this.Button1.Click += new System.EventHandler(this.FreeTextBox1_SaveClick);
this.Load += new System.EventHandler(this.Page_Load);
}
private void FreeTextBox1_SaveClick(object sender, System.EventArgs e)
{
divshow.InnerHtml = FreeTextBox1.Text;
}
5) 从客户端中检测到有潜在危险的 Request.Form 值
<%@ Page language=”c#” … ValidateRequest=”false”%>
4 图片上传
1) 工具栏上添加ImageGallery按钮.
<FTB:FreeTextBox ..ToolbarLayout=” ..,InsertImageFromGallery,.. />
2) 拷贝 “ftb.imagegallery.aspx” 文件到同一目录下
http://wiki.freetextbox.com/default.aspx/FreeTextBoxWiki.ImageGallery
3) FreeTextBox 属性设置
ImageGalleryPath = “~/image/upload” 上传默认路径
ImageGalleryUrl = “ftb.imagegallery.aspx rif={0}&cif={0}” ftb.imagegallery.aspx的目录, 只能用相对目录,不可以用”~”
4) ImageGallery 的设置
ftb.imagegallery.aspx文件里
<FTB:ImageGallery id=”ImageGallery1″
JavaScriptLocation=”InternalResource”
UtilityImagesLocation=”InternalResource”
SupportFolder=”~/aspnet_client/FreeTextBox/”
AllowImageDelete=true AllowImageUpload=true
AllowDirectoryCreate=false AllowDirectoryDelete=false
runat=”Server” />
AllowDirectoryCreate – 能否建立文件夹
AllowDirectoryDelete – 能否删除文件夹
AllowImageUpload – 能否上传图片
AllowImageDelete – 能否删除图片
AcceptedFileTypes – 可以上传文件扩展名的数组(array)
为开发者提供的2个属性
CurrentDirectories – a string[] array of directories to allow the user to navigate toward
CurrentImages – a FileInfo[] array of files the user should be able to insert.

建议: 删掉Page_Load事件可以显著回避上传图片不能即时显示的问题. 不要重写Page_Load
补充
========================================================================
Freetextbox是一个免费的.net mshtml 编辑器。
我所用的免费的freetextbox版本是中文版本1.6.3的汉化的freetextbox。
获得的地址。http://www.percyboy.com/w/ftb/
下载之后仔细看看其中的说明,你就可以使用这个完美的编辑器。
其中示例是在内联代码方式下,如果在代码后置下使用Freetextbox 呢。
1、首先我们把 FreeTextBox.dll 文件copy到我们的项目中的bin目录里。
然后在我们的项目里添加新的引用,在添加引用对话框选择项目标签,
浏览/选择你的FreeTextBox.dll/打开/确定。应用就添加完成了。
2、如何获得FreeTextBox.dll 中所使用到的名字空间,本中文版本1.6.3 有3个名字空间。
using FreeTextBoxControls;
using FreeTextBoxControls.Design;
using FreeTextBoxControls.Common;
可以在引用的FreeTextBox.dll 查看对象浏览。
点开树型目录就可以清晰的看到,上面所说的名字空间了。
其他的版本类似可以获得。
3、在aspx文件添加freetextbox
<%@ Register TagPrefix=”ftb” Namespace=”FreeTextBoxControls” Assembly=”FreeTextBox” %>
具体的方法和内联一样的。
同时cs文件中会有如下代码:
protected FreeTextBoxControls.FreeTextBox FreeTextBox1;产生
添加完后,运行一下就可以看到结果了。
在设计模式下我们还可以查看FreeTextBox 属性。
4、如何把FreeTextBox 内容写到数据库,我们在aspx文件中添加一个bottom
其的onclick=“my_add”
cs文件
protected void my_add(object sender, System.EventArgs e)
{
// 在此处放置用户代码以初始化页面
Response.Write(FreeTextBox1.Text);
}
此处是输出内容,可以改成我们需要方法。

FreeTextBox使用方法集合

作者:刘一 时间:2005-6-16
我在此网站http://www.percyboy.com/w/ftb/down/下载了
FreeTextBox 1.6.3 中文版 [307KB]
FreeTextBox 1.6.3 中文版源代码 [420KB]
1.先把freetextbox.dll添加到项目中

2.把 – ftb.colorpicker.aspx
– ftb.imagegallery.aspx
– ftb.inserttable.aspx
从文件夹HelperScripts复制出来,放到外面与 – test.aspx (测试)同等级目录,
(不这么做,插入背景色,图片,表格就不好使)

3.把images文件夹放到test.aspx (测试)同等级目录下,来存放上传的图片.

4.在test.aspx 中,加图片的路径
<FTB:FreeTextBox id=”FreeTextBox1″ runat=”server” Width=”700″ ButtonPath=”\images\ftb\office2003\”/>

this.FreeTextBox1.Text 这个就是FTB中你输入的文本的内容,这是带HTML标记的

this.FreeTextBox1.HtmlStrippedText 这个是将HTML标记去掉的文本

5.写入数据库
在CSDN上看到朋友们说怎么把FreeTextBox内容写入数据库中
我做了一下.就是把所有产生的HTML代码都插入数据库的一个字段中
可以做一个新闻表
news
字段ID(自增) content addtime(getdate)

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
if (!IsPostBack)
{
SqlConnection myConn = new SqlConnection(“server=(local);database=mm;uid=sa;pwd=123”);
SqlCommand myCmd = new SqlCommand(“select * from test where id=2”,myConn);
myConn.Open();
SqlDataReader myDr;
myDr=myCmd.ExecuteReader();
myDr.Read();
Response.Write(myDr[“content”].ToString());
myDr.Close();
myConn.Close();
}
}

private void Button1_Click(object sender, System.EventArgs e)
{
SqlConnection myConn = new SqlConnection(“server=(local);database=mm;uid=sa;pwd=123”);
SqlCommand myCmd = new SqlCommand(“insert into test (content) values(‘”+FreeTextBox1.Text+”‘)”,myConn);
myConn.Open();
myCmd.ExecuteNonQuery();
myConn.Close();
}

[注]web.config
在system.web节加入:
<pages validateRequest=”false”/>

—————————————————————————————————–
这里还有3.0的版本,不过是外文的哟! The no.1 free ASP.NET HTML Editor for IE and Mozilla.

FreeTextBox 3.0
FreeTextBox 3.0, with over 150,000 downloads, is the most popular cross-browser HTML editor for ASP.NET. To start using the control, do the following

Download FreeTextBox 3.0.4
Read FreeTextBox Wiki for installation instructions
Report problems to the forums
Purchase a Pro license (49) or source code/distribution license (199).
Current Version (3.0.4) Information

———另外补上一文章————————-
Freetextbox是一个免费的.net mshtml 编辑器。
我所用的免费的freetextbox版本是中文版本1.6.3的汉化的freetextbox。
获得的地址。http://www.percyboy.com/w/ftb/
下载之后仔细看看其中的说明,你就可以使用这个完美的编辑器。
其中示例是在内联代码方式下,如果在代码后置下使用Freetextbox 呢。
1、首先我们把 FreeTextBox.dll 文件copy到我们的项目中的bin目录里。
然后在我们的项目里添加新的引用,在添加引用对话框选择项目标签,浏览/选择你的FreeTextBox.dll/打开/确定。应用就添加完成了。

2、如何获得FreeTextBox.dll 中所使用到的名字空间,本中文版本1.6.3 有3个名字空间。
using FreeTextBoxControls;
using FreeTextBoxControls.Design;
using FreeTextBoxControls.Common;
可以在引用的FreeTextBox.dll 查看对象浏览。
点开树型目录就可以清晰的看到,上面所说的名字空间了。
其他的版本类似可以获得。
3、在aspx文件添加freetextbox
<%@ Register TagPrefix=”ftb” Namespace=”FreeTextBoxControls” Assembly=”FreeTextBox” %>
具体的方法和内联一样的。
同时cs文件中会有如下代码:
protected FreeTextBoxControls.FreeTextBox FreeTextBox1;产生
添加完后,运行一下就可以看到结果了。
在设计模式下我们还可以查看FreeTextBox 属性。
4、如何把FreeTextBox 内容写到数据库,我们在aspx文件中添加一个bottom
其的onclick=“my_add”
cs文件
protected void my_add(object sender, System.EventArgs e)
{
// 在此处放置用户代码以初始化页面
Response.Write(FreeTextBox1.Text);
}
此处是输出内容,可以改成我们需要方法。

—-心得——————————————————-
在使用FreeTextBox控件进行文本编辑后,进行保存时需要取编辑内容对应的HTML文本内容。
取编辑内容使用my_freetextbox.ViewStateText属性会比使用my_freetextbox.Text属性,
在后续的字符串内容处理上会方便一些。
在所取出的字符串中,系统自动加上了“\r\n”的回车换行字符串标示,在存储内容到数据库之前最
好将这些“\r\n”字符串用空串“”替换掉(如:my_str=my_str.Replace(“\r\n”,””)),否则在将
来调用时会导致不正常显示。
在所取出的字符串中,系统还把编辑文本中的双引号“用转义字符\进行了处理,如原字符串为
“wangshixin said “hello!””,所取得的字符串实际为“wangshixin said \”hello!\””,因此需要
将所获得的字符串中的全部“\””用特定的字符串替换掉。在将来提取显示时,再将特定字符串替换为
“\””(如:my_str=my_str.Replace(“\””,”wangshixin750920″))。
—–还有,再加上————————————————————————–
FreeTextBox1.Text 取得内容(带html标签的)
FreeTextBox1.HtmlStrippedText 也是取得内容(不带Html标签的)
——关于WORD中过来的内容,出错解决————————————————————
把从word复制的文本粘贴到freetextbox里,提交到数据库的时候会提示有危险代码,也就是单引号,这是为什么?
在Dottext里的freetextbox,同一篇word文档,提交时就没有问题。
我现在找到的原因是dottext里的freetextbox在提交的时候会把危险代码重新编码好像,而在我的项目里的freetextbox就不会。
查看包含freetextbox控件的页面源文件,又发现license不同,是不是有

把页面中的validateRequest指令设成false即可,或者直接改web.config:<pages validateRequest=”false” buffer=”true”/>

编写高性能WEB应用程序的10个技巧

导读:
  文章出处:CnXHacker.Net 作者: 发布时间:2005-11-03
  
  本文讨论
    常见 ASP.NET 性能难点
    面向 ASP.NET 的有用性能提示和技巧
    在 ASP.NET 中使用数据库的建议
    使用 ASP.NET 进行缓存和后台处理
  本文使用了以下技术:
  ASP.NET、.NET Framework 和 IIS
  本页内容
  数据层性能
  技巧 1 — 返回多个结果集
  技巧 2 — 分页的数据访问
  技巧 3 — 连接池
  技巧 4 — ASP.NET 缓存 API
  技巧 5 — 每请求缓存
  技巧 6 — 后台处理
  技巧 7 — 页输出缓存和代理服务器
  技巧 8 — 运行 IIS 6.0(只要用于内核缓存)
  技巧 9 — 使用 Gzip 压缩
  技巧 10 — 服务器控件视图状态
  小结
  使用 ASP.NET 编写 Web 应用程序的简单程度令人不敢相信。正因为如此简单,所以很多开发人员就不会花时间来设计其应用程序的结构,以获得更好的性能了。在本文中,我将讲述 10 个用于编写高性能 Web 应用程序的技巧。但是我并不会将这些建议仅局限于 ASP.NET 应用程序,因为这些应用程序只是 Web 应用程序的一部分。本文不作为对 Web 应用程序进行性能调整的权威性指南 — 一整本书恐怕都无法轻松讲清楚这个问题。请将本文视作一个很好的起点。
  成为工作狂之前,我原来喜欢攀岩。在进行任何大型攀岩活动之前,我都会首先仔细查看指南中的路线,阅读以前游客提出的建议。但是,无论指南怎么好,您都需要真正的攀岩体验,然后才能尝试一个特别具有挑战性的攀登。与之相似,当您面临修复性能问题或者运行一个高吞吐量站点的问题时,您只能学习如何编写高性能 Web 应用程序。
  我的个人体验来自在 Microsoft 的 ASP.NET 部门作为基础架构程序经理的经验,在此期间我运行和管理 www.ASP.NET,帮助设计社区服务器的结构,社区服务器是几个著名 ASP.NET 应用程序(组合到一个平台的 ASP.NET Forums、.Text 和 nGallery)。我确信有些曾经帮助过我的技巧对您肯定也会有所帮助。
  您应该考虑将应用程序分为几个逻辑层。您可能听说过 3 层(或者 n 层)物理体系结构一词。这些通常都是规定好的体系结构方式,将功能在进程和/或硬件之间进行了物理分离。当系统需要扩大时,可以很轻松地添加更多的硬件。但是会出现一个与进程和机器跳跃相关的性能下降,因此应该避免。所以,如果可能的话,请尽量在同一个应用程序中一起运行 ASP.NET 页及其相关组件。
  因为代码分离以及层之间的边界,所以使用 Web 服务或远程处理将会使得性能下降 20% 甚至更多。
  数据层有点与众不同,因为通常情况下,最好具有专用于数据库的硬件。然而进程跳跃到数据库的成本依然很高,因此数据层的性能是您在优化代码时首先要考虑的问题。
  在深入应用程序的性能修复问题之前,请首先确保对应用程序进行剖析,以便找出具体的问题所在。主要性能计数器(如表示执行垃圾回收所需时间百分比的计数器)对于找出应用程序在哪些位置花费了其主要时间也非常有用。然而花费时间的位置通常非常不直观。
  本文讲述了两种类型的性能改善:大型优化(如使用 ASP.NET 缓存),和进行自身重复的小型优化。这些小型优化有时特别有意思。您对代码进行一点小小的更改,就会获得很多很多时间。使用大型优化,您可能会看到整体性能的较大飞跃。而使用小型优化时,对于某个特定请求可能只会节省几毫秒的时间,但是每天所有请求加起来,则可能会产生巨大的改善。
  数据层性能
  谈到应用程序的性能调整,有一个试纸性的测试可用来对工作进行优先级划分:代码是否访问数据库?如果是,频率是怎样的?请注意,这一相同测试也可应用于使用 Web 服务或远程处理的代码,但是本文对这些内容未做讲述。
  如果某个特定的代码路径中必需进行数据库请求,并且您认为要首先优化其他领域(如字符串操作),则请停止,然后执行这个试纸性测试。如果您的性能问题不是非常严重的话,最好花一些时间来优化一下与数据库、返回的数据量、进出数据库的往返频率相关的花费时间。
  了解这些常规信息之后,我们来看一下可能会有助于提高应用程序性能的十个技巧。首先,我要讲述可能会引起最大改观的更改。
  技巧 1 — 返回多个结果集
  仔细查看您的数据库代码,看是否存在多次进入数据库的请求路径。每个这样的往返都会降低应用程序可以提供的每秒请求数量。通过在一个数据库请求中返回多个结果集,可以节省与数据库进行通信所需的总时间长度。同时因为减少了数据库服务器管理请求的工作,还会使得系统伸缩性更强。
  虽然可以使用动态 SQL 返回多个结果集,但是我首选使用存储过程。关于业务逻辑是否应该驻留于存储过程的问题还存在一些争议,但是我认为,如果存储过程中的逻辑可以约束返回数据的话(缩小数据集的大小、缩短网络上所花费时间,不必筛选逻辑层的数据),则应赞成这样做。
  使用 SqlCommand 实例及其 ExecuteReader 方法填充强类型的业务类时,可以通过调用 NextResult 将结果集指针向前移动。图 1 显示了使用类型类填充几个 ArrayList 的示例会话。只从数据库返回您需要的数据将进一步减少服务器上的内存分配。
  技巧 2 — 分页的数据访问
  ASP.NET DataGrid 具有一个很好的功能:数据分页支持。在 DataGrid 中启用分页时,一次会显示固定数量的记录。另外,在 DataGrid 的底部还会显示分页 UI,以便在记录之间进行导航。该分页 UI 使您能够在所显示的数据之间向前和向后导航,并且一次显示固定数量的记录。
  还有一个小小的波折。使用 DataGrid 的分页需要所有数据均与网格进行绑定。例如,您的数据层需要返回所有数据,那么 DataGrid 就会基于当前页筛选显示的所有记录。如果通过 DataGrid 进行分页时返回了 100,000 个记录,那么针对每个请求会放弃 99,975 个记录(假设每页大小为 25 个记录)。当记录的数量不断增加时,应用程序的性能就会受到影响,因为针对每个请求必须发送越来越多的数据。
  要编写性能更好的分页代码,一个极佳的方式是使用存储过程。图 2 显示了针对 Northwind 数据库中的 Orders 表进行分页的一个示例存储过程。简而言之,您此时要做的只是传递页索引和页大小。然后就会计算合适的结果集,并将其返回。
  在社区服务器中,我们编写了一个分页服务器控件,以完成所有的数据分页。您将会看到,我使用的就是技巧 1 中讨论的理念,从一个存储过程返回两个结果集:记录的总数和请求的数据。
  返回记录的总数可能会根据所执行查询的不同而有所变化。例如,WHERE 子句可用来约束返回的数据。为了计算在分页 UI 中显示的总页数,必须了解要返回记录的总数。例如,如果总共有 1,000,000 条记录,并且要使用一个 WHERE 子句将其筛选为 1000 条记录,那么分页逻辑就需要了解记录的总数才能正确呈现分页 UI。
  技巧 3 — 连接池
  在 Web 应用程序和 SQL Server  之间设置 TCP 连接可能是一个非常消耗资源的操作。Microsoft 的开发人员到目前为止能够使用连接池已经有一段时间了,这使得他们能够重用数据库连接。他们不是针对每个请求都设置一个新的 TCP 连接,而是只在连接池中没有任何连接时才设置新连接。当连接关闭时,它会返回连接池,在其中它会保持与数据库的连接,而不是完全破坏该 TCP 连接。
  当然,您需要小心是否会出现泄漏连接。当您完成使用连接时,请一定要关闭这些连接。再重复一遍:无论任何人对 Microsoft .NET Framework 中的垃圾回收有什么评论,请一定要在完成使用连接时针对该连接显式调用 Close 或 Dispose。不要相信公共语言运行库 (CLR) 会在预先确定的时间为您清除和关闭连接。尽管 CLR 最终会破坏该类,并强制连接关闭,但是当针对对象的垃圾回收真正发生时,并不能保证。
  要以最优化的方式使用连接池,需要遵守一些规则。首先打开连接,执行操作,然后关闭该连接。如果您必须如此的话,可以针对每个请求多次打开和关闭连接(最好应用技巧 1),但是不要一直将连接保持打开状态并使用各种不同的方法对其进行进出传递。第二,使用相同的连接字符串(如果使用集成身份验证的话,还要使用相同的线程标识)。如果不使用相同的连接字符串,例如根据登录的用户自定义连接字符串,那么您将无法得到连接池提供的同一个优化值。如果您使用集成身份验证,同时还要模拟大量用户,连接池的效率也会大大下降。尝试跟踪与连接池相关的任何性能问题时,.NET CLR 数据性能计数器可能非常有用。
  每当应用程序连接资源时,如在另一个进程中运行的数据库,您都应该重点考虑连接该资源所花时间、发送或检索数据所花时间,以及往返的数量,从而进行优化。优化应用程序中任何种类的进程跳跃都是获得更佳性能的首要一点。
  应用层包含了连接数据层、将数据转换为有意义类实例和业务流程的逻辑。例如社区服务器,您要在其中填充Forums 或 Threads集合,应用业务规则(如权限);最重要的是要在其中执行缓存逻辑。
  技巧 4 — ASP.NET 缓存 API
  编写应用程序代码行之前,一个首要完成的操作是设计应用层的结构,以便最大化利用 ASP.NET 缓存功能。
  如果您的组件要在 ASP.NET 应用程序中运行,则只需在该应用程序项目中包括一个 System.Web.dll 引用。当您需要访问该缓存时,请使用 HttpRuntime.Cache 属性(通过 Page.Cache 和 HttpContext.Cache 也可访问这个对象)。
  对于缓存数据,有几个规则。首先,如果数据可能会多次使用时,则这是使用缓存的一个很好的备选情况。第二,如果数据是通用的,而不特定于某个具体的请求或用户时,则也是使用缓存的一个很好的备选情况。如果数据是特定于用户或请求的,但是寿命较长的话,仍然可以对其进行缓存,但是这种情况可能并不经常使用。第三,一个经常被忽略的规则是,有时可能您缓存得太多。通常在一个 x86 计算机上,为了减少内存不足错误出现的机会,您会想使用不高于 800MB 的专用字节运行进程。因此缓存应该有个限度。换句话说,您可能能够重用某个计算结果,但是如果该计算采用 10 个参数的话,您可能要尝试缓存 10 个排列,这样有可能给您带来麻烦。一个要求 ASP.NET 的最常见支持是由于过度缓存引起的内存不足错误,尤其是对于大型数据集。
  图 3 ASP.NET缓存
  缓存有几个极佳的功能,您需要对它们有所了解。首先,缓存会实现最近最少使用的算法,使得 ASP.NET 能够在内存运行效率较低的情况下强制缓存清除 - 从缓存自动删除未使用过的项目。第二,缓存支持可以强制失效的过期依赖项。这些依赖项包括时间、密钥和文件。时间经常会用到,但是对于 ASP.NET 2.0,引入了一个功能更强的新失效类型:数据库缓存失效。它指的是当数据库中的数据发生变化时自动删除缓存中的项。有关数据库缓存失效的详细信息,请参阅 MSDN Magazine 2004 年 7 月的 Dino Esposito Cutting Edge 专栏。要了解缓存的体系结构,请参阅图 3。
  技巧 5 — 每请求缓存
  在本文前面部分,我提到了经常遍历代码路径的一些小改善可能会导致较大的整体性能收益。对于这些小改善,其中有一个绝对是我的最爱,我将其称之为“每请求缓存”。
  缓存 API 的设计目的是为了将数据缓存较长的一段时间,或者缓存至满足某些条件时,但每请求缓存则意味着只将数据缓存为该请求的持续时间。对于每个请求,要经常访问某个特定的代码路径,但是数据却只需提取、应用、修改或更新一次。这听起来有些理论化,那么我们来举一个具体的示例。
  在社区服务器的论坛应用程序中,页面上使用的每个服务器控件都需要个性化的数据来确定使用什么外观、使用什么样式表,以及其他个性化数据。这些数据中有些可以长期缓存,但是有些数据却只针对每个请求提取一次,然后在执行该请求期间对其重用多次,如要用于控件的外观。
  为了达到每请求缓存,请使用 ASP.NET HttpContext。对于每个请求,都会创建一个 HttpContext 实例,在该请求期间从 HttpContext.Current 属性的任何位置都可访问该实例。该 HttpContext 类具有一个特殊的 Items 集合属性;添加到此 Items 集合的对象和数据只在该请求持续期间内进行缓存。正如您可以使用缓存来存储经常访问的数据一样,您也可以使用 HttpContext.Items 来存储只基于每个请求使用的数据。它背后的逻辑非常简单:数据在它不存在的时候添加到 HttpContext.Items 集合,在后来的查找中,只是返回 HttpContext.Items 中的数据。
  技巧 6 — 后台处理
  通往代码的路径应该尽可能快速,是吗?可能有时您会觉得针对每个请求执行的或者每 n 个请求执行一次的任务所需资源非常多。发送电子邮件或者分析和验证传入数据就是这样的一些例子。
  剖析 ASP.NET Forums 1.0 并重新构建组成社区服务器的内容时,我们发现添加新张贴的代码路径非常慢。每次添加新张贴时,应用程序首先需要确保没有重复的张贴,然后必须使用“坏词”筛选器分析该张贴,分析张贴的字符图释,对张贴添加标记并进行索引,请求时将张贴添加到合适的队列,验证附件,最终张贴之后,立即向所有订阅者发出电子邮件通知。很清楚,这涉及很多操作。
  经研究发现,大多数时间都花在了索引逻辑和发送电子邮件上。对张贴进行索引是一个非常耗时的操作,人们发现内置的 System.Web.Mail 功能要连接 SMYP 服务器,然后连续发送电子邮件。当某个特定张贴或主题领域的订阅者数量增加时,执行 AddPost 功能所需的时间也越来越长。
  并不需要针对每个请求都进行电子邮件索引。理想情况下,我们想要将此操作进行批处理,一次索引 25 个张贴或者每五分钟发送一次所有电子邮件。我们决定使用以前用于对数据缓存失效进行原型设计的代码,这个失效是用于最终进入 Visual Studio  2005 的内容的。
  System.Threading 命名空间中的 Timer 类非常有用,但是在 .NET Framework 中不是很有名,至少对于 Web 开发人员来说是这样。创建之后,这个 Timer 类将以一个可配置的间隔针对 ThreadPool 中的某个线程调用指定的回调。这就表示,您可以对代码进行设置,使其能够在没有对 ASP.NET 应用程序进行传入请求的情况下得以执行,这是后台处理的理想情况。您还可以在此后台进程中执行如索引或发送电子邮件之类的操作。
  但是,这一技术有几个问题。如果应用程序域卸载,该计时器实例将停止触发其事件。另外,因为 CLR 对于每个进程的线程数量具有一个硬性标准,所以可能会出现这样的情形:服务器负载很重,其中计时器可能没有可在其基础上得以完成的线程,在某种程度上可能会造成延迟。ASP.NET 通过在进程中保留一定数量的可用线程,并且仅使用总线程的一部分用于请求处理,试图将上述情况发生的机会降到最低。但是,如果您具有很多异步操作时,这可能就是一个问题了。
  这里没有足够的空间来放置该代码,但是您可以下载一个可以看懂的示例,网址是 www.rob-howard.net。请了解一下 Blackbelt TechEd 2004 演示中的幻灯片和演示。
  技巧 7 — 页输出缓存和代理服务器
  ASP.NET 是您的表示层(或者说应该是您的表示层);它由页、用户控件、服务器控件(HttpHandlers 和 HttpModules)以及它们生成的内容组成。如果您具有一个 ASP.NET 页,它会生成输出(HTML、XML、图像或任何其他数据),并且您针对每个请求运行此代码时,它都会生成相同的输出,那么您就拥有一个可用于页输出缓存的绝佳备选内容。
  将此行内容添加页的最上端
  
  就可以高效地为此页生成一次输出,然后对它进行多次重用,时间最长为 60 秒,此时该页将重新执行,输出也将再一次添加到 ASP.NET 缓存。通过使用一些低级程序化 API 也可以完成此行为。对于输出缓存有几个可配置的设置,如刚刚讲到的 VaryByParams 属性。VaryByParams 刚好被请求到,但还允许您指定 HTTP GET 或 HTTP POST 参数来更改缓存项。例如,只需设置 VaryByParam=”Report” 即可对 default.aspx Report=1 或 default.aspx Report=2 进行输出缓存。通过指定一个以分号分隔的列表,还可以指定其他参数。
  很多人都不知道何时使用输出缓存,ASP.NET 页还会生成一些位于缓存服务器下游的 HTTP 标头,如 Microsoft Internet Security and Acceleration Server 或 Akamai 使用的标头。设置了 HTTP 缓存标头之后,可以在这些网络资源上对文档进行缓存,客户端请求也可在不必返回原始服务器的情况下得以满足。
  因此,使用页输出缓存不会使得您的应用程序效率更高,但是它可能会减少服务器上的负载,因为下游缓存技术会缓存文档。当然,这可能只是匿名内容;一旦它成为下游之后,您就再也不会看到这些请求,并且再也无法执行身份验证以阻止对它的访问了。
  技巧 8 — 运行 IIS 6.0(只要用于内核缓存)
  如果您未运行 IIS 6.0 (Windows Server  2003),那么您就错过了 Microsoft Web 服务器中的一些很好的性能增强。在技巧 7 中,我讨论了输出缓存。在 IIS 5.0 中,请求是通过 IIS 然后进入 ASP.NET 的。涉及到缓存时,ASP.NET 中的 HttpModule 会接收该请求,并返回缓存中的内容。
  如果您正在使用 IIS 6.0,就会发现一个很好的小功能,称为内核缓存,它不需要对 ASP.NET 进行任何代码更改。当请求由 ASP.NET 进行输出缓存时,IIS 内核缓存会接收缓存数据的一个副本。当请求来自网络驱动程序时,内核级别的驱动程序(无上下文切换到用户模式)就会接收该请求,如果经过了缓存,则会将缓存的数据刷新到响应,然后完成执行。这就表示,当您将内核模式缓存与 IIS 和 ASP.NET 输出缓存一起使用时,就会看到令人不敢相信的性能结果。在 ASP.NET 的 Visual Studio 2005 开发过程中,我一度是负责 ASP.NET 性能的程序经理。开发人员完成具体工作,但是我要看到每天进行的所有报告。内核模式缓存结果总是最有意思的。最常见的特征是网络充满了请求/响应,而 IIS 运行时的 CPU 使用率只有大约 5%。这太令人震惊了!当然使用 IIS 6.0 还有一些其他原因,但是内核模式缓存是其中最明显的一个。
  技巧 9 — 使用 Gzip 压缩
  虽然使用 gzip 并不一定是服务器性能技巧(因为您可能会看到 CPU 使用率的提高),但是使用 gzip 压缩可以减少服务器发送的字节数量。这就使人们觉得页速度加快了,并且还减少了带宽的用量。根据所发送数据、可以压缩的程度以及客户端浏览器是否支持(IIS 只会向支持 gzip 压缩的客户端发送经过 gzip 压缩的内容,如 Internet Explorer 6.0 和 Firefox),您的服务器每秒可以服务于更多的请求。实际上,几乎每当您减少所返回数据的数量时,都会增加每秒请求数。
  Gzip 压缩已经内置到 IIS 6.0 中,并且其性能比 IIS 5.0 中使用的 gzip 压缩要好的多,这是好消息。但不幸的是,当尝试在 IIS 6.0 中打开 gzip 压缩时,您可能无法在 IIS 的属性对话中找到该设置。IIS 小组在该服务器中置入了卓越的 gzip 功能,但是忘了包括一个用于启用该功能的管理 UI。要启用 gzip 压缩,您必须深入到 IIS 6.0 的 XML 配置设置内部(这样不会引起心脏虚弱)。顺便提一句,这归功于 OrcsWeb 的 Scott Forsyth,他帮助我提出了在 OrcsWeb 上宿主的 www.asp.net 服务器的这个问题。
  本文就不讲述步骤了,请阅读 Brad Wilson 的文章,网址是 IIS6 Compression。还有一篇有关为 ASPX 启用压缩的知识库文章,网址是 Enable ASPX Compression in IIS。但是您应该注意,由于一些实施细节,IIS 6.0 中不能同时存在动态压缩和内核缓存。
  技巧 10 — 服务器控件视图状态
  视图状态是一个有趣的名称,用于表示在所生成页的隐藏输出字段中存储一些状态数据的 ASP.NET。当该页张贴回服务器时,服务器可以分析、验证、并将此视图状态数据应用回该页的控件树。视图状态是一个非常强大的功能,因为它允许状态与客户端一起保持,并且它不需要 cookie 或服务器内存即可保存此状态。很多 ASP.NET 服务器控件都使用视图状态来保持在与页元素进行交互期间创建的设置,例如保存对数据进行分页时显示的当前页。
  然而使用视图状态也有一些缺点。首先,服务或请求页时,它都会增加页的总负载。对张贴回服务器的视图状态数据进行序列化或取消序列化时,也会发生额外的开销。最后,视图状态会增加服务器上的内存分配。
  几个服务器控件有着过度使用视图状态的趋势,即使在并不需要的情况下也要使用它,其中最著名的是 DataGrid。ViewState 属性的默认行为是启用,但是如果您不需要,则可以在控件或页级别关闭。在控件内,只需将 EnableViewState 属性设置为 false,或者在页中使用下列设置即可对其进行全局设置:
  
  如果您不回发页,或者总是针对每个请求重新生成页上的控件,则应该在页级别禁用视图状态。
  小结
  我为您讲述了一些我认为在编写高性能 ASP.NET 应用程序时有所帮助的技巧。正如我在本文前面部分提到的那样,这是一个初步指南,并不是 ASP.NET 性能的最后结果。(有关改善 ASP.NET 应用程序性能的信息,请参阅 Improving ASP.NET Performance。)只有通过自己的亲身体验才能找出解决具体性能问题的最好方法。但是,在您的旅程中,这些技巧应该会为您提供一些好的指南。在软件开发中,几乎没有绝对的东西;每个应用程序都是唯一的。

本文转自
http://hi.baidu.com/superyhao/blog/item/80cd8b1870dd96b44bedbc18.html

上周技术关注:Flickr的幕后故事

  • [Flickr] Flickr的幕后故事 #
    Flickr 是全 CGI 的动态构架,并以一种 .gne 的脚本作为 CGI 程序语言。不管网站制作菜鸟还是高手都会疑惑:gne 是哪种语言?答案: gne 不是一种语言,Flickr 是以极为经典的 PHP MySQL 方式实现的,在被 Yahoo 收购服务器搬入美国之前,使用了 21 台(69.90.111.101-121) Apache/PHP 做 Web、23 台图片服务器、另有 MySQL 服务器组成的数据库集群的服务器数量未知。现在估计使用的是 Yahoo 的负载均衡系统,对外只有一个 Web 的 IP 和图片服务器的 IP 了。
  • [用户体验] 如何量化用户体验度UE(How To Quantify The User Experience) #
    量化用户体验有四个互相关联的重要因素:1. 品牌(branding) 2. 使用性(usability) 3. 功能性(functionality) 4. 内容(content)
  • [RSS] RSS3.0发布 #
    RSS 3 Homepage18号首次公开了它全新的通用标准。 新版本主要修改了Rss2.0的一些漏洞并去除掉一些内容,新版本Rss将能够完全向后兼容,这比再建一个全新的通用标准要好得多了。
  • [FLASH; map; Google] IceBin’s Blog-[发现]Flash Earth整合地图 #
    GOOGLE和MSN都开放了API,现在这个FLASH来了,整合完之后,相当成熟,显然带来的流畅感也是不言而喻的,如果你还在MSN和GOOGLE地图间游荡,就来这里游荡好了,可以瞬间切换。
  • [网络技术] RFC中文文档目录 #
    RFC文档目录
  • [.NET开发; ajax] AJAX初探 #
    经过了在网上大把大把的搜寻和筛选后,这里我向大家推荐我感觉比较好的一种AJAX .Net wrapper
  • [.NET开发; Web服务] Performance of ASP.NET Web Services, Enterprise Services, and .NET Remoting #
    Compare and contrast performance characteristics of real-life ASP.NET Web services, .NET Enterprise Services components, and .NET Remoting components, and get recommendations on how to best use these technologies.
  • [sql_server] SD Times – SQL Server Rules the Roost #
    Most developers are using relational databases; the preferred database interfaces are SQL and ODBC; and Microsoft’s SQL Server is most likely to be used for current projects. Those are some of the results from the 2005 Database, Access, Integration and Reporting study, conducted in July by BZ Research, a division of BZ Media, publisher of SD Times.
  • [网站设计; 易用性] Web交互界面易用性设计和验收的指导性原则 #
    本文试图阐述WEB交互页面设计的一些指导性原则,这些原则有利于避免发生不愉快的操作体验。这些原则是用户友好性的,是在完成同一种操作要求下,使用户最感到轻松、简单、舒适的WEB交互界面设计原则。我们假定我们讨论的WEB页面都是功能正常的,符合美学观点的。需要说明我们讨论的原则可能会和设计上的美学观点以及既有的功能设计有所冲突。如果发生这种情况,基于“实用的就是美的”观点,我们会建议您酌情放弃原先的美学观点与功能设计。
  • [web2.0; 电子商务; Web服务] 从网页到网络平台 网站开发模式正发生改变 #
    比如eBay,已经20%产品清单是由外部程序员开发出来的自动拍卖程序获得的。用户仍然可以使用eBay网站来进行商品搜索,但eBay 程序开发部门的主管Greg Isaacs认为,自动系统能够让卖家的效率更高。Isaacs透露,这种自动系统程序发展很快,其数量已经由 2003年的300个上升到现在的1.8万多个。
  • [ajax] AJAX, RemoteScripting.Net, Script Callbacks and Other Goodness #
    And finally, let’s try to remember that it’s not ‘Microsoft gets hip to AJAX’. Microsoft INVENTED AJAX, and its called Remote Scripting. In ASP.NET 2.0, they call it ‘Script Callbacks’. Do good things with it!
  • [程序人生] 成为技术传播者(二):Why and Why NOT #
    落到更为实际的层面上,“成为技术传播者”的动机也很容易理解,即《软件工艺》书所说的“声望”(reputation)。Pete McBreen认为,reputation是检验开发者能力的唯一标准。而reputation的度量,我认为大致是一个乘法式:声望 = 成功项目的经验 * 传播的人数 * 受众了解深入程度因此,更为广泛地传播自己的技术(也即“成功项目的经验”),虽然受众的平均了解深入度有所降低,却仍旧有可能提高声望。在我看来,这是成为技术传播者的利益原动力。当然,获得尊敬、出风头等心理因素也是促成动力之一,但我认为那些因素的驱动效果是非常不稳定、无法长久的。
  • [ajax] ASP.NET Podcast Show #11 – Intro to Ajax and the Ajax Library for .NET #
    Before looking at the code samples, understand that the client ids may not be 100% accurate in all situations. It is best to use the ClientId property of the necessary controls to get the appropriate property name.
  • [ajax] 突发奇想,抛砖引玉,大家探讨一下新型SMART Client 可行性! #
    没有想到这项技术现在有了这么长足的发展,能够实现.net服务器对象与javascript客户端对象的转换,甚至.net 2.0种作了更好的支持,可以保持服务器对象的状态。由此我突发奇想,其实未来的SMART Client可以更近一步,干脆直接用HTA来做,HTA可以实现SMART Client程序同样的offline效果,更加容易部署(根本不用安装),与本地的资源(比如MSDE)交互也可以通过COM组件完成。现在更是可以通过scriptcallback机制和服务器完成交互。
  • [javascript] dp.SyntaxHighlighter – free JavaScript syntax highlighting #
    60多K,很有价值。
    dp.SyntaxHighlighter is a free JavaScript tool for source code syntax highlighting. The script is meant to help a developer to post code snippets online with ease and without having to worry about applying format. People who use blogs like MovableType, .Text (dotText), dasBlog and any other system can easily add code to their posts.
  • [开源; blog] 商业能从开源中学到什么? #
    就象开源,书写blog是人们为自己所做的事情,它是免费的,是因为人们喜欢这么做。象开源的黑客、bloggers与那些为钱工作的人竞争,并且常常获胜。保证质量的方法是相同的:达尔文主义的。公司通过制定规则来防止雇员把事情搞得一团糟,但你不能把职员与职员间的通信也制止了。人们只是生产他们想要的东西;只传播好的材料,把坏的忽略掉。并且在以上两个例子中,人们从反馈中改进工作,使之变得更好。blog和开源的另一个共同之处就是Web。人们总是愿意不计报酬地完成伟大的工作,但是在Web诞生之前,它很难抵达观众的面前,也很难在项目中合作。我认为这些就是开源和书写blog教给商业的:(1)人们遇到他们喜爱的东西总会工作得更努力。(2)标准的办公室的工作环境很没有效率,还有(3)自底向上总是比自顶向下要好。
  • [Google] Google Maps API 簡易使用文件 #
    在 Google 推出 Google Maps 之後,網路上出現各種 hack 網站及文件,討論如何直接從 Google Maps 的 CGI 取得地圖圖檔並推出自己的地圖服務,但是這類的網站對 Google 的負荷很大,例如前不久的 Google Maps Wallpaper 即是,大量無節制的下載圖檔,Google 沒多久就將他封殺了,而且各式 hacking 的程式良莠不齊,所以 Google 就乾脆自己推出 API 程式庫讓全世界對 Google Maps 有興趣的程式設計師能夠自行開發 Google Maps 服務,而且 Google 也可以透過 API 來對這些服務做一個控管。
  • [搜索技术] 搜索引擎的缓存机制 #
    搜索引擎缓存策略也同搜索引擎的算法密切相连, 除了搜索缓存, 索引缓存也是一个好方法. 独立或者分布一些权重较高的文档也是一种提高效率的方法. 例如我们有1000万的网页的权重(可以简单的理解为pagerank)比较高, 那么这些网页的排序相比另外一些权重较低的网页相对较为稳定, 就不妨独立出来进行相对独立的索引缓存.关于缓存的分布, 一般的小型搜索引擎不会用到, 但是如果每天处理上亿次的搜索, 缓存的分布就应当有一定的分布规划, 例如根据提交的关键词构成hash table, 然后对应于不同的搜索服务器, 实现缓存的分布.
  • [ajax] Thinking in AJAX(二) —— 基于AJAX的WEB设计 #
    很多人都看好AJAX无刷新的技术,以至于认同AJAX就是用来做无刷新的。这个认识是错误的,什么是无刷新?无刷新就是页面无需重载,那什么又是异步交互?异步交互就是一个简单的多线程,当你在一个blog里看文章时,同时也可以利用AJAX进行无刷新的回复提交,看起来虽然也是无刷新,但这里最重要的是异步,即你能一边看文章,一边又能向服务器提交你的回复信息,利用好这个异步,才能算是掌握了AJAX的精髓。很多场合,无刷新是呈现给用户的视觉体验,而异步交互却是默默无闻的工作在台后,这种情况导致大多数人的错误理解了AJAX的权重之分。

365Key-天天网摘自动生成

更多新闻,请访问我的365KeyRSS),你可以通过365Key订阅

ASP.NET2.0中Page事件的执行顺序

Page执行中将按照如下顺序激活事件:

Page.PreInit
Page.Init
Page.InitComplite
Page.PreLoad
Page.Load
Page.LoadComplete
Page.PreRender
Page.PreRenderComplete

如果页面从令一个页面继承,如BasePage:System.Web.UI.Page,在BasePage中做了一些扩展,如权限检查,而其他页面从BasePage继承,则BasePage和最终Page的事件激活顺序是:

UI.PreInit
Page.PreInit
UI.Init
Page.Init
UI.InitComplite
Page.InitComplite
UI.PreLoad
Page.PreLoad
UI.Load
Page.Load
UI.LoadComplete
Page.LoadComplete
UI.PreRender
Page.PreRender
UI.PreRenderComplete
Page.PreRenderComplete

如果使用了MasterPage,则MasterPage中的事件和ContentPage中的事件按照下面顺序激活:

ContentPage.PreInit
Master.Init
ContentPage.Init
ContentPage.InitComplite
ContentPage.PreLoad
ContentPage.Load
Master.Load
ContentPage.LoadComplete
ContentPage.PreRender
Master.PreRender
ContentPage.PreRenderComplete

更进一步,如果ContentPage继承BasePage,那么,各事件的执行顺序将变成:

UI.PreInit
ContentPage.PreInit
Master.Init
UI.Init
ContentPage.Init
UI.InitComplite
ContentPage.InitComplite
UI.PreLoad
ContentPage.PreLoad
UI.Load
ContentPage.Load
Master.Load
UI.LoadComplete
ContentPage.LoadComplete
UI.PreRender
ContentPage.PreRender
Master.PreRender
UI.PreRenderComplete
ContentPage.PreRenderComplete

AJAX到底带给了我们什么?

我是一个坚定的B/S的支持者,我也深信不疑Web将会统治未来,成为未来90%以上的信息发、布获取渠道[有人也许会说那是电视报纸,报纸我不敢攻击,不过电视未来很可能是IPTV)。未来大家不会在意操作系统这个平台,大家不会去争论你用Windows,我用Mac,他用Linux(虽然我用过两年的Linux并且很喜欢它,不过它真的对普通用户难有吸引力),或者是她用iPhone/gPhone。这些都不重要,重要的是我们都可以通过Web获取信息,获得应用。如果说未来有一个平台,那就是IP/HTTP/WEB/Browser。

 

      回想一下在AJAX流行之前的网页是什么样子的?可能大家不记得了,其实我也不记得了。不过那时候很难想象Web应用可以做到今天这种程度。虽然Web应用还是比桌面应用的交互性差,可是现在可以说使用起来已经很方便了。我觉得Google Office, Gmail这些应用的可用性,基本上我觉得可以称的上不错了。这些,其实都要感谢AJAX在背后的贡献。那么AJAX到底给我们带来了什么呢?

 

       通过这一个多月的开发经历,我深刻体会到AJAX给了你一种能力,让你的Browser表现的像一般地客户端,和服务器交互;不,还给了你一种全新的方式,来思考设计和开发你的Browser应用。其实,只不过以前我们做CS开发的时候,Client我们是跑在操作系统或者虚拟机上的,和服务器之间一般跑着私有的自己设计的协议。很多都是直接在Socket/TCP之上自己设计的协议。而AJAX,给了我们一种方法,让我们的Client跑在Browser里面,协议是在HTTP上自己设计的私有协议。

 

       也许,在开发方式上观念的转变远没有设计角度转变那么深远,我觉得AJAX带给我们的是一种全新的视角去设计我们的Web应用。随着JS框架对AJAX越来越强大的支持,我们可以将更多的精力放在用户体验上面。其实这就是AJAX或者说Web2.0的初衷,用户的体验。也是所有做软件人的终极目标,给人们更好的体验。

 

       也许空说大家没有什么感性的认识,那么我们来举个例子。我们有个简单的应用,就是要呈现给客户他的聊天记录。我们看过很多聊天记录的展现方式。譬如QQ/MSN,不过我发现他们有个共同的问题,就是是以Message为单位的。这样做固然很简单,可是,可是其实每条消息它都是有上下文的,所以最好的方法是以Conversation的方式来展示聊天记录。每个Conversation有参加者,时间(开始时间就可以了),Tag(Label)。然后你点开每个Conversation条目,就可以看到这个Conversation里面的聊天记录。如果是以前,我们可能需要每次点击Conversation条目,然后就需要后台返回一个新的页面。这样速度慢,流量大不说,关键是每次刷新的那种感觉对用户很糟糕。而有了AJAX,我们把所有的Conversation条目存在内存中,用户点击一个条目,通过AJAX获得这个Conversation的Message,然后存到内存中,然后展现给客户(我们可以用很漂亮的动画展现)。当客户点击下一个Conversation条目的时候,上一个条目的Message仍然保存在内存中,下一次如果它再点这个条目的时候,我们就不需要到服务器去取了。[当然要注意内存耗费太大的问题,可以定期清理]      

 

       不过AJAX也有一些缺点。首先就是复杂,大家可别小看这个缺点,复杂就意味着更容易犯错误,更多的Bug,对老板来说就意味这要花更多的Cost;其次就是不能滥用。这有两方面的意思。一就是不要一个页面N多地方都不定时的给后台发送请求,你可以重构这样的设计;二就是要让AJAX真得提高用户的体验,而不是你在那里眩酷,这没有意思;三,我们是在浏览器里面做东西,和客户端还是不一样。譬如一个case,有些应用客户端需要注销。如果你自己做得Client,你可以在点击关闭按钮的时候,做注销的事情。如果服务器那边返回注销成功,你就让客户端退出;如果不成功,你就可以让客户端再注销一次。可是这个在Browser里面你就不可能了,客户关闭窗口,你是可以得到Window.onunload事件,可是你没有机会去判断你的结果;最后一个缺点也是天然的缺点,Http是单向的,也就是服务器没办法以中断的方式给Browser发消息(我知道AJAX PUSH, COMET, Web Socket,可是他们本质上还是单向的Http)。

 

         接着这篇文章,我想说,可能未来Flash/SilverLight, WAP这种过度产品也会go to hell。HTML5(据说还要10年,不过我觉得有Google在,估计4年左右会现端倪)会是我们的未来。

 

 

Vs2010下asp.netmenu控件分隔图片显示问题

今天用Menu控件设计一个横向菜单,在设置分隔符图片时,发现显示不正常,图片跑到文字的下方。

  更奇怪的是,在另一个旧的项目里设计就是好的!

  没办法,仔细比较,最后终于发现,在旧项目的Web.config中有一句

<!–<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />–><pagescontrolRenderingCompatibilityVersion=”3.5″>
</pages>

  MSDN的解释是”指定将与任何呈现的 HTML 兼容的 ASP.NET 版本。”。这才想起来,旧项目是从2008升级过来的,Visual Studio 自动将 Web.config 文件中的 controlRenderingCompatibilityVersion 特性设置为 3.5。

  如果以后大家也碰到控件显示的问题,试试这个方法吧。

用ASP.NET开发Web服务的五则技巧

文章来源:仙人掌工作室

一、禁用HTTP POST/GET协议

  除非另外指定,否则,.NET将试图把Web服务绑定到三种协议:HTTP/POST、HTTP/GET和SOAP。之所以说“试图”,是因为依赖于服务的参数和返回类型,HTTP/GET协议可能不可用。.NET生成的WSDL文件将自动包含绑定这三种协议的指令,客户程序可以自由选择使用哪种协议与服务通信。

  只要在Web.config文件中加入下列内容,就可以方便地删除对HTTP/POST和HTTP/GET协议的绑定:

<webservices>
<protocols>
<remove name=”HttpPost” />
<remove name=”HttpGet” />
</protocols>
</webservices>

  为什么要避免通过HTTP/POST和HTTP/GET协议引出Web服务呢?主要的两个原因是安全和互操作性。HTTP/GET的安全性不如SOAP,而且由于HTTP/GET常见于Web链接,怀有恶意的人可能利用它实施欺骗,使别人在不知不觉中用自己的安全标识调用Web服务,却还以为自己在点击Web链接。

  就互操作性而言,SOAP是广泛应用的Web服务通信标准,而HTTP/GET和HTTP/POST不是。因此,对于.NET生成的WSDL文档中默认包含的HTTP/GET和HTTP/POST绑定,许多自动生成代理服务器的工具不会理解。因此,如果你的Web服务不是非绑定到HTTP/GET和HTTP/POST协议不可,最好取消这两种绑定。

  二、用tcpTrace查看SOAP请求/应答消息

  对于开发Web服务应用的人来说,调试可能是件异乎寻常的难事,因为无论是.NET SDK还是VS.NET,都没有提供工具来查看客户端和服务器之间的SOAP消息。

  如果.NET和非.NET的客户端、服务器端的交互过程出现了问题,要想找出问题的根源,拥有查看SOAP消息的能力就尤为重要,因为这类问题往往与SOAP消息的格式有关(例如,“消息中包含了SOAPAction 吗?”)。

  tcpTrace(www.pocketsoap.com/tcptrace)是一个查看这类消息交换过程的优秀工具,它通过设置一个客户端和服务器端之间的隧道工作。启动tcpTrace时,它会要求输入目标URL和端口号,以及tcpTrace监听的本地端口号。这样,你就可以通过设置代理stub的Url属性,把stub指向这个本地端口(例如,localhost:8080)。tcpTrace能够记录所有的请求和应答HTTP消息。

  tcpTrace的一个局限是,它在消息流程中所处的位置决定了它不能用来查看通过SSL发送的消息。如果你要查看通过SSL发送的SOAP消息,只能编写一个定制的ISAPI过滤器。

  三、简化接口设计

  在众多有关n-层应用设计的论述中,简化接口设计这一设计要诀可以说是随处可见。但是,对于Web服务这样的分布式计算环境,简化接口设计的重要性更加突出。

  在设计分布式应用时,出于性能和可伸缩性的考虑,应当保证客户端和服务器端之间的调用尽可能地少。减少网络调用不仅有利于减少通信开销(如果只用一个SOAP消息可以达到目标,就绝对不要发三个消息),降低网络流量,而且提高了应用的性能。显然,这一切都是开发者梦寐以求的目标。那么简化的接口到底有何特征呢?

  首先来看一个复杂接口的例子:

namespace ChattyService {
public class ChattyService : WebService {
private string username;
private string password;

public string Username {
[WebMethod]
set {
username = Username;
} }

public string Password {
[WebMethod]
set {
password = Password;
} }

[WebMethod]
public bool Logon() {
// 验证身份
return true;
}
}
}

  在这个例子中,username和password是两个属性,调用logon()方法之前首先必须设置这两个属性。有一个问题光看这段代码不太容易注意到,这就是username和password都作为Web方法引出。这就是说,每次对属性的get/set操作都会导致一个对服务的调用。

  按照简化接口设计的要求,改进后的代码如下:

namespace ChattyService {
public class ChattyService : WebService {
[WebMethod]
public bool Logon(string Username, string Password) {
// 验证身份
return true;
}
}
}

  现在,username和password成了logon()方法的参数。修改之后的代码的优点在于,它把登录操作对服务器的三次调用降低到了一次。另一方面,如果参数的个数太多,这个方法可能看起来很不像样。这时,可能要把方法的参数整理成几个复杂类型,例如,把username和password两个参数封装到一个credential(证书)对象里面。

  四、在Web.Config中保存应用私有的数据

  用ASP.NET开发的Web服务能够发挥出.aspx应用的所有特长,包括用web.config文件保存应用私有数据的能力(例如,数据库连接字符串、文件路径等)。用Web.config而不是global.asax文件的好处在于修改配置之后不必重新构造应用。

  五、避免使用ASP.NET会话状态

  .NET实现的会话状态管理功能解决了它的前辈ASP 3.0存在的许多问题,例如请求串行化等,但仍存在一些局限。应当认识到,.NET的会话状态管理功能不是专门为Web服务环境中的会话状态而设计,而是为了在范围更广泛的ASP.NET应用中管理会话状态而设计,它依赖于HTTP Cookie(有一种通过改写URL实现的不需要Cookie的模式,但不适用于Web服务)。

  Cookie是HTTP独有的。在Web上,所有的浏览器都支持HTTP,所以Cookie非常适合在Web应用中使用。但是,在Web服务中应用Cookie却把服务限定到了HTTP协议上。另一方面,SOAP协议的运行是独立于传输协议的,因此如果把Web服务应用限制到HTTP协议上,应用的灵活性也受到了限制,一旦要通过非HTTP的传输协议(例如SMTP)提供服务,事情会变得很麻烦。

ASP.NET-SubstitutionWeb服务器控件概述

您可以使用 Substitution 控件,在网页上创建可动态更新并可随后集成到缓存页中的区域。

一、方案

使用 Substitution 控件可以在要缓存输出的网页上指定要显示动态内容的部分。对于多数内容都要进行缓存的页,Substitution 控件提供了进行部分页缓存的简化的解决方案。您可以缓存整个页的输出,然后使用 Substitution 控件来指定页中不进行缓存的部分。缓存区域仅执行一次,且将一直从缓存读取,直至该缓存条目到期或被清除。动态区域则在每次请求页时都会执行。此缓存模型简化了其内容主要是静态内容的网页的代码,因为您不必在 Web 用户控件中对这些静态内容进行封装,以将它们放入缓存。例如,对于包含静态内容(如新闻故事)和显示广告的 AdRotator 控件的网页,此缓存模型就非常有用。新闻故事不会经常更改,这意味着可以将它们放入缓存。您可能会希望在用户每次请求该网页时显示一条新广告。AdRotator 控件直接支持缓存后替换,无论是否缓存了网页,它都会在网页每次回发时呈现一个新广告。

二、背景

缓存 ASP.NET 网页时,默认情况下,会缓存该网页的全部输出。在第一次请求时,该页将运行并缓存其输出。对于后续的请求,将通过缓存来完成,该页上的代码不会运行。

在某些情况下,您可能不但希望缓存 ASP.NET 网页,还希望在每次请求该网页时更新该网页上的选定部分。例如,您可能要缓存某页的很大一部分,但需要动态更新该页上的与时间高度相关的信息。

可以使用 Substitution 控件将动态内容插入到缓存页中。Substitution 控件不会呈现任何标记。因此,您需要将该控件绑定到网页或父级用户控件中的方法。您需要创建可返回要插入到网页中的信息的静态方法。由 Substitution 控件调用的方法必须符合下面的标准:

·必须为静态方法(在 Visual Basic 共享)。

·必须接受类型为 HttpContext 的参数。

·必须返回类型为 String 的值。

Substitution 控件无法访问网页上的其他控件,也就是说,您无法检查或更改其他控件的值。但代码却可使用传递给它的参数来访问当前网页的上下文。

在页运行时,Substitution 控件会调用该方法,然后用从该方法的返回值替换页上的 Substitution 控件。

代码示例

下面的示例演示如何使用 Substitution 控件在缓存页上创建可动态更新的内容。页的 Load 事件中的代码用当前时间来更新 Label 控件。因为页的缓存持续时间已设置为 60 秒,所以 Label 控件的文本不会更改,即使在 60 秒的时间内多次请求了该页。页上的 Substitution 控件调用静态方法 GetTime,该方法将以字符串的形式返回当前时间。每次刷新网页时,都会更新 Substitution 控件表示的值。

<%@ Page Language=”C#” %>

<%@ OutputCache Duration=60 VaryByParam=”None” %>

<script runat=”server”>

void Page_Load()

{

Label1.Text = DateTime.Now.ToString();

}

public static String GetTime(HttpContext context)

{

return DateTime.Now.ToString();

}

</script>

<html>

<head runat=”server”></head>

<body>

<form id=”form1″ runat=”server”>

<div>

<p>

<asp:Label runat=”server” ID=”Label1″ />

</p>

<p>

<asp:Substitution runat=”server”

ID=”Substitution1″

MethodName=”GetTime” />

</p>

<p>

<asp:Button runat=”server” ID=”Button1″ Text=”Submit”/>

</p>

</div>

</form>

</body>

</html>

三、Substitution

使用 Substitution 控件指定输出缓存网页上要以动态内容替换该控件的部分。Substitution 控件为要缓存大部分内容的页提供了一种缓存局部页的简化解决方案。可以对整页进行输出缓存,然后使用 Substitution 控件指定页中免于缓存的部分。需要缓存的区域只执行一次,然后从缓存读取,直至该缓存项到期或被清除。动态区域则在每次请求页时执行。由于不必对这些部分进行封装以缓存在 Web 用户控件中,因此,此缓存模型简化了主要是静态内容的页的代码。例如,如果页包含静态内容(如新闻报道)和显示广告的 AdRotator 控件,这种情况下,此缓存模型就很有用。新闻报道不会更改,这意味着它们可以缓存。但是,您希望在用户每次请求该页时都显示一条新广告。AdRotator 控件直接支持缓存后替换,无论页是否缓存,都在该页回发时呈现一个新广告。

说明: 在缓存页包含的用户控件中可以放置 Substitution 控件。但是,在输出缓存用户控件中不能放置 Substitution 控件。

Substitution 控件执行时,会调用一个返回字符串的方法。该方法返回的字符串即为要在页中的 Substitution 控件的位置上显示的内容。使用 MethodName 属性指定要在 Substitution 控件执行时调用的回调方法的名称。指定的回调方法必须是包含 Substitution 控件的页或用户控件的静态方法。回调方法的签名必须与接受 HttpContext 参数并返回字符串的 HttpResponseSubstitutionCallback 委托的签名匹配。

若要操作页的输出缓存,可使用 @ OutputCache 指令、HttpCachePolicy 类或 Cache 属性。

Substitution 控件的另一种使用方法是,使用 HttpResponseSubstitutionCallback 委托实现缓存替换行为。此外,还可以在直接支持缓存替换功能的控件(如 AdRotator 控件)上实现缓存替换行为。

示例

下面的代码示例演示如何以声明方式将 Substitution 控件添加到输出缓存网页。加载页面时,将在一个标签中向用户显示当前的日期和时间。页面中的此区域仅 60 秒便缓存和更新一次。当 Substitution 控件执行时,将调用 GetCurrentDateTime 方法。GetCurrentDateTime 返回的字符串将显示给用户。每次刷新页时,都不会缓存和更新页中的这一部分。

<%@ outputcache duration=”60″ varybyparam=”none” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”

“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<script runat=”server” language=”C#”>

void Page_Load(object sender, System.EventArgs e)

{

// Display the current date and time in the label.

// Output caching applies to this section of the page.

CachedDateLabel.Text = DateTime.Now.ToString();

}

// The Substitution control calls this method to retrieve

// the current date and time. This section of the page

// is exempt from output caching.

public static string GetCurrentDateTime (HttpContext context)

{

return DateTime.Now.ToString ();

}

</script>

<html >

<head runat=”server”>

<title>Substitution Class Example</title>

</head>

<body>

<form id=”form1″ runat=”server”>

<h3>Substitution Class Example</h3>

<p>This section of the page is not cached:</p>

<asp:substitution id=”Substitution1″

methodname=”GetCurrentDateTime”

runat=”Server”>

</asp:substitution>

<br />

<p>This section of the page is cached:</p>

<asp:label id=”CachedDateLabel”

runat=”Server”>

</asp:label>

<br /><br />

<asp:button id=”RefreshButton”

text=”Refresh Page”

runat=”Server”>

</asp:button>

</form>

</body>

</html>