返回首页

简介
本文侧重于提供程序模型设计模式,并介绍如何可以用来解决某些问题。为了帮助读者更好地理解或欣赏这种设计模式,我选择了视图状态管理作为一个例子来说明这种设计模式的实用性和实用性。因此,在本文中,我们会先了解视图状态所固有的问题是什么,然后我会解释为什么提供程序模型设计模式是重要的,我们可以利用它来解决上述问题。背景
视图状态 - 一个爱与恨的关系,与许多ASP.NET开发人员。开发人员喜欢它,因为它并不需要任何服务器状态资源,很容易实现。页和控件状态保留自动跨连续在同一页的实例,这使得神奇的Web窗体模型可能职位。此外,在视图状态中的值散列,压缩和编码的Unicode实现,从而代表了更高的安全性已经不是隐藏字段的状态。另一方面,几个热点问题环绕它的使用,主要涉及到安全性和性能。出于安全考虑,因为视图状态存储在页面上的隐藏字段。虽然视图状态存储在一个哈希格式的数据,在隐藏字段中存储的信息可以看出,如果直接查看页输出源,创建一个潜在的安全问题。为了提高性能,因为视图状态存储在页本身,存储较大的值可能会导致页面慢下来时,浏览器显示或邮寄。
对于那些新的,以ASP.NET,有很好的资源,了解更多有关ASP.NET视图状态。 书面苏珊沃伦。 书面斯科特米切尔。
幸运的是,Page类可以支持视图状态的替代存储计划。类包含几个保护的虚方法,运行时使用反序列化或序列化视图状态。 LoadPageStateFromPersistenceMedium是用于还原视图状态在页面生命周期的开始。相比之下,名为SavePageStateToPersistenceMedium方法用于保存之前呈现页面的视图状态:保护虚拟无效SavePageStateToPersistenceMedium(对象的ViewState);受保护的虚拟对象LoadPageStateFromPersistenceMedium();
覆盖两种方法,你可以在你的意志操纵的视图状态。 (请注意,您不能覆盖​​只有一个方法,你必须重写这两个),典型的解决方案是:压缩视图状态(性能)视图状态进行加密(安全)在服务器端的文件或数据库表中保存视图状态和读/写的视图状态时,该网页正在处理。 (安全性和性能)
每上述建议的解决方案有其优点和缺点。大家都知道,总有一个权衡安全性和性能之间做出选择。问题是我们如何能够在这样一种方式,它可以实现这些解决方案,但选择性地选择一个特定的问题域的最佳设计我们的应用程序。例如,你可能想为您的开发任务和一个不同的(比如Oracle数据库,这是按客户要求)生产的视图状态存储在一个Microsoft SQL Server数据库。因此,选择合适的解决方案是配合您的需求,如何能有效地解决问题方面的问题。岂不是巨大的,如果你能上一个仓库的顶部实施这些解决方案最适合您的需求,而在同一时间保持这种选择独立的应用程序的架构,设计和代码?提供程序模型设计模式简介
提供程序模型设计模式源于一个广泛接受的模式,并在2002年夏天正式命名。一个"提供者"定义为一个可插拔的组件,以扩展或完全取代现有系统功能。换句话说,供应商模式允许你拔掉的一个API的默认实现(例如,视图状态管理,会话状态管理,个性化,等等)和插件为特定系统通过编写您自己的供应商你自己的。支持模型的功能,你可以改变底层的实现,数据格式和存储介质,而不会中断应用程序的设计(保持完好的顶级接口)。更简单地说:它允许开发人员发布记录,很容易理解的API(对象模型),但同时给开发商对会发生什么时,这些API被称为内部的完全控制。
功能的实现,供应商必须在web.config(Web应用程序)或者app.config中(Windows应用程序)文件中定义配置节。它的目的是注册可用的"供应商",但选择一个作为默认提供程序。例如:LT - 视图状态提供程序配置 - >!LT,视图状态的defaultProvider ="SqlViewStateProviderquot; GT; LT;添加名称="; SqlViewStateProviderquot"; 类型="; System.Web.Configuration.Providers.SqlViewStateProvider"  60; ViewStateProvidersquot; 60; 的connectionString ="SERVER =(本地),数据库(数据库名); USERID = SA; PWD ="/ GT; LT;添加名称="; CompressionViewStateProviderquot"; 类型="; System.Web.Configuration.Providers.CompressionViewStateProvider" ViewStateProvidersquot; 的connectionString =""/ GT; LT; / providersgt;LT; / viewstategt;
根据上面显示的配置,下面概述了应遵循的几个重要的指导方针:的defaultProvider
每个功能配置应指定默认的提供者,它指示系统使用列出的供应商。例如:LT,视图状态的defaultProvider ="SqlViewStateProviderquot; GT;提供友好的名称
在定义范围内配置供应商,这是需要定义的name属性。此外,供应商名称应遵循一个模式很容易分辨出谁拥有的供应商。建议的模式是:[供应商造物主] [数据存储] [功能] Provider.lt; addname ="SqlViewStateProviderquot; 类型="; System.Web.Configuration.Providers.SqlViewStateProvider" &# 160; ViewStateProvidersquot; &# 160;的connectionString ="SERVER =(本地),数据库(数据库名),用户ID = SA; PWD = quot; / GT;
下表要求的通用名称和套管,一些应该使用不同的数据存储(的名称是[名称] [功能]供应商]。例如,SqlViewStateProvider应使用名称使用SQL Server的供应商作为数据存储。名称适用于SQL任何供应商使用的SQL Server作为数据存储。访问任何供应商使用的Access / Jet数据库作为数据存储。XML任何供应商,它使用一个XML文件作为数据存储。公元任何供应商使用的Active Directory作为数据存储。文件任何供应商使用一个文件作为数据存储。内存任何供应商使用内存中的数据存储。提供程序类型
在定义范围内配置一个供应商,它需要被定义为type属性。类型的值必须是一个完全合格的名称以下格式:类型= quot; [namespace.class],[程序集名称,版本= [版本]  60; 文化= [文化]于PublicKeyToken = [公共令牌]"
所需的强类型的名称是,但是,它也是合法使用较短的风格组装类型的名称。例如:类型="System.Web.Configuration.Providers.SqlViewStateProvider,ViewStateProvidersquot;
若要了解提供程序模型设计模式,请读,写人:Rob Howard。ViewState的供应商对象模型
该模型定义了一组类,以支持视图状态提供框架。如下所示的图描绘的ViewState Provider对象模型及其与页面的交互。
ViewStateManager - 它暴露了两个静态方法,LoadPageState和SaveViewState,是由应用程序(页,于我们而言)加载或保存其视图状态,分别。它不包含任何业务逻辑,而是简单地转发这些配置供应商的电话,说SqlViewStateProvider。这是责任SqlViewStateProvider提供商类来包含这些方法的实现,调用业务逻辑层(BLL)或数据访问层(DAL)来完成作业。 / / /公升; summarygt;/ / /加载任何从几乎任何保存当前页面的视图状态/ / /一个隐藏字段以外的存储介质/ / / SqlViewStateProvider提供商ViewStateProviderBase类继承,它使用的SQL Server作为数据存储来存储和检索的页面视图状态在页面的生命周期。该表用于存储视图状态的架构设计是为图如下所示的简单:字段名称数据类型说明vsKeyNVARCHAR(100)一个独特的键来标识一个特定的页面的视图状态vsValueNTEXT页面视图状态。时间戳DATETIME鉴于此状态的上次访问时间戳
前一个页面呈现其输出,SavePageState方法将被调用的框架页的视图状态保存。内部,它会检查,如果一个隐藏字段名为"__vsKey"(又名HtmlInputHidden控件)在页面的Controls集合中存在,将创建的隐藏字段,如果它不存在。简单的方法的代码创建LosFormatter对象的一个​​实例,并调用它的serialize()方法,序列化传递StringWriter作家在视图状态信息。之后,一个全局唯一标识符(GUID)将用作键生成并保存到数据库表中的某个特定页面的视图状态。最后,但并非最不重要,此GUID存储在此页面的隐藏字段。
页面回传时,LoadPageState方法将被调用框架来检索一个特定的页面保存的视图状态。这是通过使用上次访问"__vsKey"隐藏字段中存储的GUID来查询数据库中的表的视图状态,并通过的LosFormatter Derialize()方法返回反序列化的对象。
这里有一个问题,每次用户访问不同的页面,页面的视图状态,将数据库中的表创建一个新的记录。随着时间的推移,这将导致数百万条记录,这可能会严重影响性能的查找过程。将需要某种自动化的任务,定期清理出的视图状态比某一特定日期的记录。我作为读者的练习离开。
下图显示之前和之后使用SqlViewStateProvider供应商,而不是存储在一个隐藏字段名为"__VIEWSTATE"的页面视图状态存储在数据库中的差异。

视图状态存储在隐藏字段中(之前)

视图状态存储在数据库中(后)使用代码
本文附带两个视图状态提供商,可从本文开头的链接。提供商存储视图状态到一个SQL Server数据库表,这是整个本文所述,以及其他压缩视图状态的能力。如前所述,如果这些供应商的默认功能不符合您的需求,您可以创建自己的提供,并插入到框架。
ViewState中的地方供应商的框架,开发一个自定义的视图状态的供应商,如下面列出的几个步骤:创建一个新的类和来自ViewStateProviderBase类。 (切记provider类的命名模式)。实施LoadPageState SavePageState的API。LT; providersgt;节在Web.config文件中添加新类。设置defaultProvider属性的值LT; viewstategt;节在Web.config文件到新创建的提供者的名称。结论
提供程序的设计模式,使开发人员能够有一个灵活的设计和丰富的企业级的扩展性模型。更重要的是,你可以很容易地使用一个供应商为您的开发任务,并在生产中的应用不同的,只需通过改变一些配置。最后,但并非最不重要的是,这是一个重要的的新的设计模式在ASP.NET 2.0,它是广泛用于像网站的成员,角色管理,个性化等许多常见的Web应用程序的功能,启动应用程序中使用它今天,并和领先的曲线你会理解这种设计模式在ASP.NET 2.0的明天。

回答

评论会员:hAshishNangla 时间:2011/12/03
我降落写一个类似的类,使用ASP.NET 2.0"的PageStatePersister,并在页面上传递出一个GUID键/

Ashish Nangla的博客ASP.NET的ViewState大小减少的WebForms通过写一个自定义ViewState的供应商/的PageStatePersister
已经尝试过的代码,在我看来,每次SqlViewStateProvider进入SavePageState方法无法找到隐藏的输入控制访问它的值。
是它的意图
评论会员:本Lewies 时间:2011/12/03
伟大的文章和概念,但不幸的是落实在文章中描述的解决方案后,一些麻烦。笔者不讨论解决方案的副作用。

实施这一方案后,一些标准的ASP.Net控件检正常工作,因上"嵌入"(客户端)的Viewstate的依赖。

修改,2009年9月17日,日(星期四)上午7:19
评论会员:本Lewies 时间:2011/12/03
喜埃尔文

神奇的文章(和一些伟大的编码方式)!

我实现了上述的解决方案。然而,不幸的是有似乎是一个问题后,实施解决方案与标准的ASP.Net GridView控件:GridView的视图状态启用,在RowCommand事件产生的索引范围的异常。它似乎是无法检索存储的ViewState值。
这工作完全使用默认asp.net视图状态时。
我迄今无法找出问题的根源,或找到一个解决方案。我不怕,我将被迫放弃尝试,如果我无法解决的问题后急速。这将是一个巨大的耻辱,因为我希望其他一些相当不错的令人印象深刻的功能为出发点。

希望有人能够帮助有点?我会继续大家张贴任何新的发展。

预先感谢

修改日(星期二),2009年8月4日,日7:04
评论会员:本Lewies 时间:2011/12/03
OK,这样的DataGrid项目的ViewState是没有客户端上了,和DataGrid会导致问题的根源是的JavaScript doPostback方法在嵌入视图状态(视图状态存储内页)的项目执行和参考,从而导致空引用异常。

你基本上得到同样的错误当您禁用GridView的视图状态与命令项。

问题仍然是 - 我该如何防止这种情况发生?
修改日(星期二),2009年8月11日,日7:27
评论会员:kirtiarora 时间:2011/12/03
喜的朋友,
我的ViewState包含331009 CHAR(约323 KB)。它是存储在数据库中的空。
viewstates其他网页都存储在数据库中。
如何可以存储冗长的....这mechanisim的Viewstate
评论会员:?r_nandrajog 时间:2011/12/03
如何产生,以表动态,以及如何从DataSet或DataTable添加记录。
评论会员:Pkpatel 时间:2011/12/03
非常好的供应商的解释模式

拉克什Nandrajog
评论会员:GaneshParam 时间:2011/12/03


我米使用的GridView的ASP.NET2.0控制和实施后,我有一个问题"的NewPageIndex不获取更新的PageIndexChanging事件"

而这个问题的根源是GridView的PageIndex存储使用
ASP.NET 2.0的新功能,称为"ControlState"。

是否有任何解决这个问题。

请回答我的ASAP

谢谢你

关于
Piyush
评论会员:匿名 时间:2011/12/03
你的文章是非常丰富的。但有一篇文章,让我建立一个供应商,其中我可以使用甲骨文数据库,而不是SQL Server的。这将是巨大的,如果已经有提供Oracle提供的DLL。


Ganesh神
评论会员:Rooc 时间:2011/12/03
嗨,我很想看到了这方面的工作范例在VB.Net中,我试图转换在我的项目,但失败。


评论会员:本Lewies 时间:2011/12/03
我想保存我的ViewState性能的目的,我可以改变SQL数据库到XML文件用于保存视图状态,而不是SQL数据库到XML文件?
评论会员:拉金 时间:2011/12/03
,这将是很方便的,如果SqlProvider第一次调用初始化数据库

存储过程和表creationscript也得心应手。

伟大的工作虽然!
评论会员:manishgour 时间:2011/12/03
下载演示源,它包含SQL创建脚本。 (Setup.SQL)
评论会员:rboarman 时间:2011/12/03
是提供程序模型设计模式或一个应用程序框架?你提出的解决方案,有趣的是,有几个值得商榷的点。但我不会调用提供模型设​​计模式,只是因为MS乡亲这样说。这是一个插入式infastructure instintiated对象提供的设计模式,结合。

[www.ipattern.com你呢?]