一 : asp.net2.0 URL重写以及urlMappings问题(2)
由于一旦进行了URL重写,原先的WEBFORM中的Action会发生改变,容易造成:请求的资源不存在问题具体怎么样?各位DX看看就清楚了!!!
所有才有了这个ResponseFilter了,实现如下:
public class ResponseFilter : System.IO.Stream public override bool CanSeek public override bool CanWrite public override long Length public override long Position public override long Seek(long offset, System.IO.SeekOrigin direction) public override void SetLength(long length)
{
public ResponseFilter(System.IO.Stream sink, string _str)
{
_sink = sink;
//
// TODO: 在此处添加构造函数逻辑
//
this.str = _str;
}
private string str = "";
private System.IO.Stream _sink;
private long _position;
private System.Text.Encoding end = System.Text.Encoding.GetEncoding("GB18030");
private System.Text.StringBuilder oOutput = new System.Text.StringBuilder();
// The following members of Stream must be overriden.
public override bool CanRead
{
get { return true; }
}
{
get { return true; }
}
{
get { return true; }
}
{
get { return 0; }
}
{
get { return _position; }
set { _position = value; }
}
{
return _sink.Seek(offset, direction);
}
{
_sink.SetLength(length);
}
public override void Close() public override void Flush() public override int Read(byte[] buffer, int offset, int count) // The Write method actually does the filtering. byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(szBuffer);
{
_sink.Close();
}
{
_sink.Flush();
}
{
return _sink.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
string szBuffer = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count);
string ap = "action="";
int pos = -1;
if ((pos = szBuffer.IndexOf(ap)) != -1)
{
int epos = szBuffer.IndexOf(""", pos + ap.Length + 1);
if (epos != -1)
{
szBuffer = szBuffer.Remove(pos + ap.Length, epos - pos - ap.Length);
}
szBuffer = szBuffer.Insert(pos + ap.Length, this.str);
_sink.Write(data, 0, data.Length);
}
else
{
oOutput.Append(szBuffer);
}
//下面的这一段可以用来修改之间的内容;
//Regex oEndFile = new Regex("", RegexOptions.IgnoreCase|RegexOptions.Compiled);
//if (oEndFile.IsMatch(szBuffer))
//{
// //Append the last buffer of data
// //附加上缓冲区中的最后一部分数据
// oOutput.Append(szBuffer);
// //Get back the complete response for the client
// //传回完整的客户端返回数据
// string szCompleteBuffer = oOutput.ToString().ToLower();
// int ipos = szCompleteBuffer.IndexOf("",ipos+7);
// string sp = szCompleteBuffer.Substring(ipos+7, epos - ipos );
// szCompleteBuffer = szCompleteBuffer.Remove(ipos+7,sp.Length-7);
// szCompleteBuffer = szCompleteBuffer.Insert(ipos + 7, "dhz");
// // szCompleteBuffer = szCompleteBuffer.Replace(sp, "dhz");
// //No match, so write out original data
// //没有匹配,因此写入源代码
// byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(szCompleteBuffer);
// _sink.Write(data, 0, data.Length);
//}
//else
//{
// oOutput.Append(szBuffer);
//}
}
}
二 : 深入解读ADO.NET2.0的十大最新特性
篇文章概述了.NET Framework 2.0里的ADO.NET2.0的最新特性。在以下叙述中将附带一些简单的例子来讨论这些特性的细节。以下便是ADO.NET新增的特性:
1. 批量复制操作(Bulk Copy Operation)
将数据从一个数据源批量复制到另一个数据源是ADO.NET 2.0的一个新特性。批量复制类提供了最快的方法把数据从一个数据源迁移到另一个数据源。每个ADO.NET的数据提供者都会提供相应的批量复制类。例如,在SQL.NET数据提供者里,批量复制操作是由一个叫SqlBulkCopy的类来完成的,它可以读取一个DataSet, DataTable, DataReader或XML 对象。
2.批量更新(Batch Update)
如果数据库服务器支持批量更新特性,Batch update代替了几个短周期提交请求的方式,从而大大改善在一个短周期内向服务器产生多个批量更新时的性能。UpdateBatchSize属性提供在一批更新里要更新行数。这个属性值能被限制到小数位。
3.数据分页
现在command对象具有一个新的执行方法叫做ExecutePageReader。这个方法有三个参数——CommandBehavior, startIndex, 和 pageSize。如果你想获得数据行数是101-200,你可以通过调用这个方法设置startIndex为101和pageSize为100而轻易完成这个功能。
4.数据连接(Connection)明细
现在你可以通过设置连接的StatisticsEnabled属性为真来获取一个连接更多的信息。Connection对象提供了两个新方法——RetrieveStatistics 和 ResetStatistics。RetrieveStatistics方法返回一个HashTable对象来填充连接信息,如:数据转移,用户明细,游标明细,缓存信息和事务处理。
5.DataSet.RemoringFormat属性
当DataSet.RemoringFormat设置为二进制时, DataSet的序列化格式由二进制格式代替了原有的XML标记格式,这种改变能显著改善序列化和还原序列化操作的性能。
6. DataTable的加载(Load)与保存(Save)方法
在以前版本的ADO.NET中,只有DataSet具有Load和Save的方法。Load方法可以把诸如XML等对象中的数据加载到一个DataSet对象中,同时Save方法可以保存数据到一个持久化存储媒体里。现在DataTable也支持这两种方法了。
7.新的数据控件
在工具箱中,你将看到如图1所示的新的控件——DataGridView, DataConnector和DataNavigator。利用这些控件,你能在数据绑定控件中提供数据导航(分页)功能。
图1:数据绑定控件
8. DbProvidersFactories类
这个类能提供当前机器里的现有数据提供者(providers)列表。在写数据库依赖程序时,你能利用这个类及其成员为你的数据库查找最适合的数据提供者。
9.自定义数据提供者(Provider)
通过提供工厂类,现在ADO.NET可以扩展支持自定义数据提供者功能。你无需编写一个数据提供者支持代码。你可以用数据提供者基类以及连接字符串帮助你完成这些功能。
10. DataReader新的执行方法
现在command对象支持更多的执行方法了,除了旧的ExecuteNonQuery, ExecuteReader, ExecuteScaler和 ExecuteXmlReader方法,还加了新的执行方法,它们是:ExecutePageReader, ExecuteResultSet和 ExecuteRow。图2展示了Command对象在ADO.NET2.0支持的所有执行方法。
图2:Command的执行方法
总结
ADO.NET 2.0为开发者提供了许多新的、改良过的特性以改善性能和减少代码量。
三 : ASP.NET2.0的控件状态和视图状态探讨
基本概念
控件状态-为了让控件正常工作,有时需要存储控件状态数据。例如,如果编写了一个自定义控件,其中具有显示不同信息的不同选项卡,为使该控件如预期一样工作,控件需要知道在往返过程中选择的是哪个选项卡。ViewState 属性可用于此目的,但开发人员可能在页级别关闭了视图状态,从而有效地中断控件。为解决此问题,ASP.NET 页框架在 ASP.NET 2.0 版中公开了一种称为控件状态的新功能。
ControlState 属性允许保持特定于控件的属性信息,不像 ViewState 属性一样可以关闭。若要使用控件状态,控件必须在初始化过程中调用 RegisterRequiresControlState 方法,然后重写 SaveControlState 和 LoadControlState 方法。
视图状态-视图状态是 ASP.NET 页框架默认情况下用于保存往返过程之间的页和控件值的方法。当呈现页的 HTML 形式时,需要在回发过程中保留的页的当前状态和值将被序列化为 Base64 编码的字符串,并输出到视图状态的隐藏字段中。通过实现自定义的 PageStatePersister 类以存储页数据,您可以更改默认行为并将视图状态存储到另一个位置(如 SQL Server 数据库)。有关将页状态存储到流上而不是隐藏的页字段中的示例,请参见 视图状态持久性机制的示例。
您可以通过使用页的 ViewState 属性将往返过程中的数据保存到 Web 服务器来利用自己的代码访问视图状态。ViewState 属性是一个包含密钥/值对(其中包含视图状态数据)的字典。
各自的优势与劣势
视图状态
使用视图状态的优点:
·不需要任何服务器资源 视图状态包含在页代码内的结构中。
·实现简单 视图状态无需使用任何自定义编程。默认情况下对控件启用状态数据的维护。
·增强的安全功能 视图状态中的值经过哈希计算和压缩,并且针对 Unicode 实现进行编码,其安全性要高于使用隐藏域。
使用视图状态的缺点
·性能注意事项 由于视图状态存储在页本身,因此如果存储较大的值,用户显示页和发送页时的速度可能会减慢。尤其是对移动设备,其带宽通常是有限的。
·设备限制 移动设备可能没有足够的内存容量来存储大量的视图状态数据。
·潜在的安全风险 视图状态存储在页上的一个或多个隐藏域中。虽然视图状态以哈希格式存储数据,但它可以被篡改。如果直接查看页输出源,可以看到隐藏域中的信息,这导致潜在的安全性问题。
控件状态
使用控件状态的优点:
·不需要任何服务器资源 默认情况下,控件状态存储在页上的隐藏域中。
·可靠性 因为控件状态不像视图状态那样可以关闭,控件状态是管理控件的状态的更可靠方法。
·通用性 可以编写自定义适配器来控制如何存储控件状态数据和控件状态数据的存储位置。
使用控件状态的缺点:
·需要一些编程 虽然 ASP.NET 页框架为控件状态提供了基础,但是控件状态是一个自定义的状态保持机制。为了充分利用控件状态,您必须编写代码来保存和加载控件状态。
控件状态与视图状态示例
此示例演示如何创建一个名为 IndexButton 的自定义控件,该控件使用控件状态在多个页请求间维护关键状态信息。在 ASP.NET 2.0 版中引入的控件状态与视图状态类似,但功能上独立于视图状态。网页开发人员可能会出于性能原因而禁用整个页面或单个控件的视图状态,但他们不能禁用控件状态。控件状态是专为存储控件的重要数据(如一个页面控件的页数)而设计的,回发时必须用到这些数据才能使控件正常工作(即便禁用视图状态也不受影响)。默认情况下,ASP.NET 页框架将控件状态存储在页的一个隐藏元素中,视图状态也同样存储在此隐藏元素中。即使禁用视图状态,或是使用 Session 管理状态时,页面中的控件状态仍会传输至客户端,然后返回到服务器。在回发时,ASP.NET 会对隐藏元素的内容进行反序列化,并将控件状态加载到每个注册过控件状态的控件中。
此示例阐释了一个同时在控件状态和视图状态中保存状态的自定义控件。在此示例中,IndexButton 控件派生自 Button 类,还定义了一个 Index 属性,并将该属性保存在控件状态中。为了进行比较,IndexButton 还定义了一个 IndexInViewState 属性,该属性存储在 ViewState 字典中。为了了解控件状态和视图状态之间的差异,请使用本文附带的程序来演示 IndexButton 控件。
IndexButton控件源码
using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CustomerControls
{
[
AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),
ToolboxData("<{0}:IndexButton runat="server"> </{0}:IndexButton>")
]
public class IndexButton : Button
{
private int indexValue;
[
Bindable(true),
Category("Behavior"),
DefaultValue(0),
Description("The index stored in control state.")
]
public int Index
{
get
{
return indexValue;
}
set
{
indexValue = value;
}
}
[
Bindable(true),
Category("Behavior"),
DefaultValue(0),
Description("The index stored in view state.")
]
public int IndexInViewState
{
get
{
object obj = ViewState["IndexInViewState"];
return (obj == null) ? 0 : (int)obj;
}
set
{
ViewState["IndexInViewState"] = value;
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Page.RegisterRequiresControlState(this);
}
protected override object SaveControlState()
{
//调用基类的方法,从基类得到控件状态的基值
//如果indexValue不等于并且基类的控件状态不为null
//使用Pair作为便利的数据结构来高效保存(和在LoadControlState方法中还原)
//由两部分组成的控件状态
object obj = base.SaveControlState();
if (indexValue != 0)
{
if (obj != null)
{
return new Pair(obj, indexValue);
}
else
{
return (indexValue);
}
}
else
{
return obj;
}
}
protected override void LoadControlState(object state)
{
if (state != null)
{
Pair p = state as Pair;
if (p != null)
{
base.LoadControlState(p.First);
indexValue = (int)p.Second;
}
else
{
if (state is int)
{
indexValue = (int)state;
}
else
{
base.LoadControlState(state);
}
}
}
}
}
}
代码讨论
IndexButton 控件的实现阐释了三个任务,必须执行这三个任务才能使控件参与控件状态:
· 重写 OnInit 方法并调用 RegisterRequiresControlState 方法向页面注册,以参与控件状态。必须针对每个请求完成此任务。
· 重写 SaveControlState 方法,以在控件状态中保存数据。
· 重写 LoadControlState 方法,以从控件状态加载数据。此方法调用基类方法,并获取基类对控件状态的基值。如果 indexValue 字段不为零,而且基类的控件状态也不为空,Pair 类便可作为方便的数据结构使用,用来保存和还原由两部分组成的控件状态。
分析总结
从MSDN上的一系列的技术参考来看,ControlState应该是主要在自定义控件上使用,“ASP.NET 页框架提供了 ControlState 属性作为在服务器往返过程中存储自定义控件数据的方法”,这是MSDN上的原句,ASP.NET2.0只是为ControlState提供了一个基础,当ControlState是一个自定义的状态保持机制,也就是说保持状态的机制需要你开发人员自己去完成,而不像ViewState,它有自己默认的状态保持机制。在自定义控件使用ControlState也许才是微软本意了,为的就避免在页面级别禁用掉ViewState后,自定义控件还能正常运行。当然这里的意思就是,某些控件的正确运行是依赖于它的状态信息的,在ASP.NET1.1中,如果禁用了ViewState,这样的控件就无法正确运行了。但引入了ControlState后就不同了,因为ControlState是禁用不掉的。
所以微软才提醒开发人员“请仅对那些在回发过程中对控件至关重要的少量关键数据使用控件状态,而不要将控件状态作为视图状态的备用选项使用”。明确说出,ControlState和ViewState完全是两个东西,虽然它们可以完成相同的任务,新推出的ControlState既不是用来替代ViewState也不是用来做ViewState的替补。它的使命是弥补ViewState的所不能完成的任务,让开发人员开发出更加健壮的控件。例如说,开发的自定义控件某个状态是至关重要的,缺少它就自定义控件不能正常工作,那么ControlState就该上场了。而且ControlState是自定义的状态保持机制,也限制了ControlState自由的使用,你不但要在OnInit 方法并调用 RegisterRequiresControlState 方法向页面注册,而且要重写SaveAdapterControlState(),LoadAdapterControlState(object state)两个方法自己去实现要保存什么,怎样保存。根据我现在的理解,如果你需要保存该控件的10种不同状态,那你就得一一保存,再一一加载上去。从这点也就看出了微软的初衷了,那不是很明显吗,如果不需要ControlState那就不使用它吧,否则怎么它什么都让我们开发人员去做呢?
这只是基础了,刚才我说了,似乎微软也是这么说的,ControlState针对的是自定义控件,其实我们真的要去开启基本控件例如Label控件的ControlState,微软也是允许的,这就是稍深的内容了,这就涉及到控件适配器了(ControlAdapter)。如果需要了解这方面的内容,请看用控件适配器开启基本控件的ControlState。
附录
为了更加充分理解上面的内容,需要对以下内容有个了解:
Pair 类
用作存储两个相关对象的基本结构。它是在整个 ASP.NET 中(在如页面状态管理任务期间或配置节处理程序的过程中)有多种用法的实用工具类。可以在自己的代码中需要包含两个相关对象的结构的任意位置和不一定需要数据绑定的位置使用 Pair 类。Pair 类不将其对象引用 First 和 Second 封装在属性中;该类直接将它们作为公共类字段公开到所有调用代码。
Pair 类在页状态保留实现中有多种用法。最常见的用法是同时作为 ViewState 和 ControlState 集合的容器。在这种情况下,First 属性用于 ViewState,而 Second 用于 ControlState。
PageStatePersister 类
HTTP 请求和响应原本是无状态的。要在 HTTP 请求之间保持状态信息,ASP.NET 服务器页可以存储 Page 状态。此状态称为视图状态,它包含页和控件设置及数据,这些设置和数据使得页和控件看起来就像在上一次将它们提交到服务器然后又返回到客户端时,用户所看到并与之交互的页和控件一样。有几种机制可在对相同页的连续请求之间存储视图状态。PageStatePersister 抽象类表示这些状态信息存储机制的基类。
要在不能支持现有视图状态持久性机制的客户端上保留视图状态,可以扩展 PageStatePersister 类,引入您自己的视图状态持久性方法,并且可以使用页适配器将 ASP.NET 应用程序配置为根据为其提供页的客户端的类型使用不同的视图状态持久性机制。从 PageStatePersister 类派生的类必须重写 Save 抽象方法,以便在持久性介质中存储视图状态和控件状态,同时重写 Load 方法以提取状态信息。如果想知道如何写PageStatePersister的派生类,请参考视图状态持久性机制。
四 : Asp.Net2.0技巧(续)
1. 在开发web控件时,如果控件必须放在服务器端的form内,可以通过Page.VerifyRenderingInServerForm(Control) 方法来保证。
2. 使用Control类的ResolveClientUrl(string)方法可以将类似“~/abc/ab.aspx”这样的路径转换为正确的url路径,这在.Net1.0中是一个内部方法,而在2.0中是公开的方法
3. Button控件有两个事件,分别是OnClick和OnCommand,在点击button之后这两个事件都会被触发,两者的区别是后者可以接受commanArgs参数,而前者不可以。
4. 在写Web控件时可以通过Themable特性指定某属性是否可以在Skin文件中指定值。
5. .Net2.0的验证控件多了一个SetFocusOnError属性,可以指定发生错误的时候是否让焦点移动到要验证的控件上。
6. 在Aspx页面上可以使用<%$AppSettings: settingKey%>获得配置文件appSettings配置节中指定key的值
7. 当将textbox控件的ReadOnly属性设置为true时,如果在客户端用js脚本改变了这个textbox的值,提交之后在服务器端是得不到改动后的值的,可以通过Request.Form[textbox.ClientID]获得改动後的值。
8. 在.Net1.0中只有一个html input的上传文件控件,而在2.0中有了一个WebControl:FileUpload,在验证用户时候选择文件并上传时,可以通过它的HasFile属性来判断,而不必这样来判断FileUpload1.PostFile != null && FileUpload1.PostFile.ContentLength > 0。
本文标题:net2.0-asp.net2.0 URL重写以及urlMappings问题(2)61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1