Legends Never Die

   
说实话,游戏只是自个儿的一个个人爱好的另一方面,他不会是活着的方方面面,可是或许在某一转眼,在某一个足以打动到技惊四座的moment,在一个足以让我们呐喊和流泪的minute,它就是全世界。

原文:http://www.microsoft.com/china/msdn/library/webservices/asp.net/WebAppFollies.mspx?mfr=true

   
跟所有的体育运动一样,电子比赛的魅力是巨大的。老话说“音乐不分国界”,其实有着具有感染力的东西都是这样,电竞也不例外。再狭隘的民族主义者也无从否认Faker对LOL的贡献和意义,大家既然喜欢竞赛,就该学会分享高品位的竞技。队员的国籍所属并无法改变竞赛本身的精良程度,一味鼓吹血统论只好让LPL陷入倒退的窘况。有人说,SKT终于是在鸟巢被三星给击倒了,他们的朝代也算是是停止了,于是理所应当的,Faker也是跌下了神坛,这终究是王朝的宿命,也是比赛的魅力所在。没有人能永远一枝独秀,没有人能生机勃勃,有的间接都是强者居上,新的记录和新的神话再持续被刷新和创立,同时,这也是竞赛将直接存在和持续上扬更上一层楼的因由所在。

ASP.NET 成功的内部一个原因在于它降低了 Web
开发人士的门路。即使你不是总计机科学大学生也足以编制 ASP.NET
代码。我在工作中碰着的重重 ASP.NET 开发人士都是自学成材的,他们在编排
C# 或 Visual Basic® 此前都在编制 Microsoft® Excel®
电子表格。现在,他们在编排 Web
应用程序,总的来说,他们所做的工作值得陈赞。

   
前些天要讲的东家,是LOL界最光辉的人,而且尚未之一。近来通常听到legends
never
die这首歌,总会想起这个在半决赛舞台上哭泣的男孩,即便她一度21了,但本身想,输掉竞技的那一刻,他必然就是个孩子,无助、失落、懊恼、不甘这一个有着类似于悲伤的心态交织在她左右,彻底粉碎了他这颗曾经最为强大的心。很多少人说,三十年河东,三十年河西,曾经的李相赫打哭那么三人,此刻可是是物换星移,主角也换了个人而已。对于观众而言,没有人甘愿只见到一个朝代,人们无形中里面,激荡的就是抵抗,抗拒一个神话最好的格局——不过就是创办一个新的神话,因为只有一个神话终究是会让人厌倦的。

唯独与能力随之而来的还有责任,固然是经验丰硕的 ASP.NET
开发人士也难免会出错。在多年的 ASP.NET
项目咨询办事中,我发觉某些错误特别容易导致缺陷不断发出。其中一些错误会潜移默化属性。其他错误会避免可伸缩性。有些错误还会使开发团队耗费宝贵的光阴来跟踪错误和出人意料的行事。

   
但对于,faker而言,他绝没有倒下。作为一个出道就终端,而且在其世界登上世界之巅的人,世界历史上也找不出好多少个,所以他肯定是万幸的这个,中国人笃信“天选之人”,认为“命由天定”,强如孟子,开篇也是“天将降大任于是人也”。倘诺有,那么李相赫他必然是。但我们掌握,电子比赛是实力说话,空谈理想,一定会让投机离开最初的轨道。出道的第二个赛季,也就是收获最高的雅观后,faker他碰着到了远大的破产和失败,他的私有情状第一次有了起降,随之他的军队也分崩离析,最终留下来的,唯有苦苦坚持不渝的她和她的亲密无间战友bengi,这么些王的老公。接下来的故事也许我们都如数家珍了,卷土重来的SKT,又接二连三两年囊括了S系列赛和几乎所有大小赛事的光彩。可是,二〇一九年,他们又倒下了,但肯定,二零一九年faker的上演相对不止算职业生涯的第二春,应该只可以用精妙绝伦来形容。作为已经跌落过神坛的丈夫,没有什么比这一回更能让她感到轻松和极端的安静了,他早就经历过两次大的挫折,那两次,他只需要持续学习,以更成熟的态度归来。因为只要他是faker,他就绝不会倒下。

下边是会造成 ASP.NET 生产应用程序的发布过程中出现问题的 10
个缺陷以及可避免它们的章程。所有示例均来自自身对实际的小卖部构建真正的 Web
应用程序的亲身感受,在好几境况下,我会通过介绍 ASP.NET
开发社团在支付进程中境遇的片段题目来提供相关的背景。

   
假使把faker的史事换来任何领域,他都应该是大家的典范,他既谦虚又傲慢;忠于自己的老东家不丢掉不抛弃;失败时候首先找自己原因,而不是从来指责队友;他有礼貌,话即使不多,但充满智慧;他重视她的每一个挑衅者,充满职业精神。像她如此的人,你要知道,也才21岁。传奇在于拼搏,至高的体面不是各样人都能企及的,强如UZI,pray,没有人质疑他们的实力,去终无法防止于无冠。拼搏,不仅是电竞精神,更是人活在世上应有的情态。Legends
never die,嗯,这就是传奇永不灭,这句话肯定是为faker量身定做的。

LoadControl 和出口缓存

极少有不使用用户控件的 ASP.NET
应用程序。在产出母版页在此以前,开发人士使用用户控件来领取公用内容,如页眉和页脚。即使在
ASP.NET 2.0
中,用户控件也提供了有效的主意来封装内容和表现以及将页面分为四个区域,这些区域的缓存能力可以单独于作为完全的页面进行支配(一种叫做段缓存的特种输出缓存情势)。

用户控件可以应用表明的主意加载,也得以强制加载。强制加载依赖于
Page.LoadControl,它实例化用户控件并回到控件引用。假诺用户控件包含自定义类型的成员(例如,公共属性),则您可以转移该引用并从你的代码访问自定义成员。
1

中的用户控件实现名为 BackColor 的性质。以下代码加载用户控件并向
BackColor 分配一个值:

protected void Page_Load(object sender, EventArgs e)
{
// 加载用户控件并将其添加到页面中
Control control = LoadControl("~/MyUserControl.ascx");
PlaceHolder1.Controls.Add(control);
// 设置其背景色
((MyUserControl)control).BackColor = Color.Yellow;
}

如上代码实际上很简短,但却是一个等待粗心的开发人士掉进去的骗局。您能找出其中的破碎吗?

假使你猜到该问题与输出缓存有关,那么您是科学的。正如你所观察的等同,上述代码示例编译和周转都健康,但是假如尝试将以下语句(完全合法)添加到
MyUserControl.ascx 中:

<%@ OutputCache Duration="5" VaryByParam="None" %>

则当你下两次运行该页面时,您将见到 InvalidCastException (oh joy!)
和以下错误音讯:

“无法将类型为‘System.Web.UI.PartialCachingControl’的对象转换为类型‘MyUserControl’。”

故此,此代码在并未 OutputCache 指令时运行正常,但万一添加了 OutputCache
指令就会出错。ASP.NET
不应有以这种方法运行。页面(和控件)对于出口缓存应该是不可知的。那么,这象征怎样意思?

题目在于为用户控件启用输出缓存时,LoadControl
不再归来对控件实例的引用;相反,它回到对 PartialCachingControl
实例的引用,而 PartialCachingControl
可能会也恐怕不会卷入控件实例,具体取决于控件的输出是否被缓存。因而,假使开发人员调用
LoadControl
以动态加载用户控件并且为了访问控件特定的形式和性质而更换控件引用,他们不可能不小心举办该操作的办法,以便不管是不是有所
OutputCache 指令,代码都可以运作。


2

表达动态加载用户控件以及转换重临的控件引用的正确性方法。以下是其行事原理概要:

如果 ASCX 文件缺少 OutputCache 指令,则 LoadControl 返回一个 MyUserControl 引用。Page_Load 将该引用转换为 MyUserControl 并设置控件的 BackColor 属性。

如果 ASCX 文件包括一个 OutputCache 指令并且控件的输出没有被缓存,则 LoadControl 返回一个对 PartialCachingControl 的引用,此 PartialCachingControl 的 CachedControl 属性包含对基础 MyUserControl 的引用。Page_Load 将 PartialCachingControl.CachedControl 转换为 MyUserControl 并设置该控件的 BackColor 属性。

如果 ASCX 文件包括一个 OutputCache 指令并且控件的输出被缓存,则 LoadControl 返回一个对 PartialCachingControl(其 CachedControl 属性为空)的引用。注意,Page_Load 不再继续执行操作。无法设置控件的 BackColor 属性,因为该控件的输出来源于输出缓存。换句话说,根本没有要设置属性的 MyUserControl。

不论是 .ascx 文件中是否具有 OutputCache 指令,
2
中的代码都将运行。即便看起来复杂一点,但它会避免烦人的荒谬。简单并不连续代表容易维护。

图片 1回去页首

   
最后有的话,送给我原先的战友们,比起体育的篮球足球网球之类,LOL一定有走到尽头的那一天,人都有透支自己喜好的那一天,一个嬉戏终究只好承载一代人的追忆,老玩家的熄灭,没有新鲜血液的融入,更面临新兴娱乐的挑衅,这就是他脚下的窘境。有人说,玩lol的人少了,是因为刚初始接触这批游戏的人都老了,他们也许都有了友好的做事和家园,有了生存中更值得讲究的事物和更值得爱的人。世界的满贯事物,都是在动态发展着的,盛衰之势常有,我们不用惋惜,他将离大家而去,渐渐淡出我们的视野和生存。但作为体育的电子竞技,其旺盛是绝不会倒下的。这才是legends
never die的末梢奥义,或许。

对话和出口缓存

谈到输出缓存,ASP.NET 1.1 和 ASP.NET 2.0
都设有一个隐秘的题材,该问题会潜移默化在 Windows Server™ 2003 和 IIS 6.0
上运行的服务器中的输出缓存页。我一度亲眼看到该问题在 ASP.NET
生产服务器中出现过一回,这一次都是经过关闭输出缓冲来解决的。后来自己打听到有一个比禁用输出缓存更好的化解方案。以下是自己先是次遇上该问题时的情事。

当时的气象是这么的,某个网站(我们在此称呼 Contoso.com,它在小型 ASP.NET
Web
领域中运作公共电子商务应用程序)与自身的团体交换,抱怨他们遭遇了“跨线程”错误。使用
Contoso.com
网站的客户平常突然遗失已经输入的数额,但却看到另一用户的相关数据。稍做分析即发现,跨线程那些描述并不精确;“跨会话”错误越来越适合。看起来
Contoso.com
是在对话状态中贮存数据的,由于一些原因,用户会偶尔随机地接连到其他用户的对话。

自家的一个社团成员编写了一个诊断工具,用来将每个 HTTP
请求和响应的根本因素(包括 Cookie
标头)记录到日志中。然后,他将该工具安装在 Contoso.com 的 Web
服务器上,并让其运行了几天。结果丰硕明显。大概每 100000
个请求中会发生三遍那样的动静:ASP.NET 正确地为全新会话分配一个会话 ID
并赶回 Set-库克(Cook)ie 标头中的会话
ID。然后,它会在下一个紧相邻的呼吁中回到相同的对话 ID(即,相同的
Set-Cookie 标头),即便该请求已经与一个实用的对话相关联并且正确提交了
库克(Cook)ie 中的会话 ID。实际上,ASP.NET
是不管三七二十一将用户从她们友善的对话中切换出去并将他们总是到其他会话。

大家很奇异,于是从头找寻原因。我们第一检查了 Contoso.com
的源代码,让大家感到宽慰的是,问题不在这。接着,为了保险问题与应用程序宿主在
Web
领域无关,大家只保留一个服务器在运作,而关门了拥有其他服务器。问题仍然存在,那并不意外,因为我们的日记显示匹配的
Set-库克ie 标头绝不会来自五个不同的服务器。ASP.NET
意外地生成了再度的对话 ID,那令人怀疑,因为它采取 .NET Framework
RNGCrypto瑟维斯(Service)Provider 类生成这一个 ID,并且会话 ID 的尺寸可以保证同等的
ID 决不会生成一遍(至少在下一个万亿年内不会变动一回)。除此之外,即便RNGCrypto瑟维斯(Service)(Service)Provider 错误地生成了重新的自由数字,也不能解释 ASP.NET
为什么不堪设想地将使得的对话 ID 替换为新的 ID(不唯一)。

凭直觉,大家决定看一下出口缓存。当 OutputCacheModule 缓存 HTTP
响应时,它必须小心不要缓存了 Set-库克(Cook)ie 标头;否则,包含新会话 ID
的缓存响应会将缓存响应的具备接收者(以及其请求生成了缓存响应的用户)连接到同一会话。我们检查了源代码;Contoso.com
在三个页面中启用了出口缓存。大家关闭了出口缓存。结果,应用程序运行数天而从不暴发一个跨会话问题。此后,它运行了两年多都并未生出任何不当。在所有不同应用程序和一组不同
Web 服务器的另一家店铺中,我们见到完全相同的题目也无影无踪了。就像在
Contoso.com 一样,消除输出缓存就能迎刃而解问题。

Microsoft 后来认可此行为来自 OutputCacheModule
中的问题。(当你读书本文时,可能曾经发表了翻新。)当 ASP.NET 与 IIS 6.0
一起使用并且启用内核情势缓存时,OutputCacheModule 有时无法从它传递给
Http.sys 的缓存响应中去除 Set-库克(Cook)ie
标头。下面是促成出现错误的一定事件顺序:

最近没有访问网站(因此也没有对应的会话)的用户请求一个启用了输出缓存的页面,但是其输出当前在缓存中不可用。

该请求执行用于访问用户最新创建的会话的代码,从而导致会话 ID Cookie 在响应的 Set-Cookie 标头中返回。

OutputCacheModule 向 Http.sys 提供输出,但是无法从响应中删除 Set-Cookie 标头。

Http.sys 在后续的请求中返回缓存响应,误将其他用户连接到会话。

故事的寓意又是什么样呢?会话状态和基础情势输出缓存不能够混合使用。假设您在启用输出缓存的页中使用会话状态,并且应用程序在
IIS 6.0
上运行,则您需要关闭内核情势输出缓存。您仍将收益于出口缓存,可是因为基本情势输出缓存比经常输出缓存快得多,所以缓存不会雷同有效。有关此题材的详细音讯,请参见
support.microsoft.com/kb/917072

你可以因此在页面的 OutputCache 指令中蕴含 VaryByParam=”*”
属性来关闭单个页面的根本方式输出缓存,虽然这样做可能引致内存需求剧增。另一种更安全的模式是由此在
web.config 中蕴藏下列元平素关闭所有应用程序的基石形式缓存:

<httpRuntime enableKernelOutputCache="false" />

你仍能使用注册表设置来全局性地剥夺内核格局输出缓存,即禁用所有服务器的基础形式输出缓存。有关详细音信,请参见
support.microsoft.com/kb/820129

历次自我听见客户报告会话发生了费解的问题,我都会精晓他们是不是在另外页面中利用了出口缓存。尽管真的使用了出口缓存,并且宿主操作系统是
Windows Server
2003,我会提议她们禁用内核情势输出缓存。问题普通就会缓解。假设问题没有解决,则错误存在于代码中。警惕!

图片 2回来页首

Forms 身份验证票证生存期

你能找出以下代码的题目啊?

FormsAuthentication.RedirectFromLoginPage(username, true);

此代码看似没有问题,但未能在 ASP.NET 1.x
应用程序中运用,除非应用程序中此外地点的代码抵消了此语句的负面功用。假使您无法确定原因,请继续阅读。

FormsAuthentication.RedirectFromLoginPage 执行三个任务。首先,当
FormsAuthenticationModule
将用户重定向到登录页时,FormsAuthentication.RedirectFromLoginPage
将用户重定向到她们原来请求的页面。其次,它发布一个身份验证票证(经常引导在
库克ie 中,而且在 ASP.NET 1.x 中老是引导在 Cookie
中),这些单子允许用户在预约的一段时间内保障已经过身份验证状态。

题材就在于那一个刻钟段。在 ASP.NET 1.x 中,向 RedirectFromLoginPage
传递另一个为 false 的参数会时有暴发一个临时身份验证票证,该票证默认意况下在
30 分钟之后到期。(您可以运用 web.config 的 元素中的 提姆(Tim)eout
属性来更改超时期限。)可是,传递另一个为 true
的参数则会时有爆发一个永远身份验证票证,其有效期为 50
年!这样就会生出问题,因为只要有人窃取了该身份验证票证,他们就足以在票据的有效期内尔(Nell)y用受害者的身价访问网站。窃取身份验证票证有多种情势—
在公共无线访问点探测未加密的通信、跨网站编写脚本、以物理方法访问受害者的总结机等等
— 由此,向 RedirectFromLoginPage 传递 true
比禁用你的网站的安全性好持续多少。幸运的是,此问题早已在 ASP.NET 2.0
中取得领会决。现在的 RedirectFromLoginPage 以相同的方法接受在 web.config
中为临时和恒久身份验证票证指定的逾期。

一种缓解方案是毫不在 ASP.NET 1.x 应用程序的 RedirectFromLoginPage
的第二个参数中传递
true。但是这不切实际,因为登录页的特点一般是含有一个“将本身保持为记名境况”框,用户可以选中该框以收取永久而不是临时身份验证
Cookie。另一种缓解方案是使用 Global.asax(倘诺你愿意的话,也得以应用
HTTP 模块)中的代码段,此代码段会在蕴藏永久身份验证票证的 库克(Cook)ie
重临浏览器此前对其展开改动。


3

包含一个如此的代码段。假使此代码段位于 Global.asax 中,它会修改传出永久
Forms 身份验证 库克ie 的 Expires 属性,以使 Cookie 在 24
刻钟后过期。通过改动注释为“新的逾期日期”的行,您可以将过期设置为您喜爱的另外日期。

您或许会以为意外,Application_EndRequest 方法调用本地 Helper 方法
(Get库克(Cook)ieFromResponse) 来检查身份验证 库克(Cook)ie 的扩散响应。Helper
方法是解决 ASP.NET 1.1 中另一个破绽百出的办法,假若您使用
Http库克ieCollection 的字符串索引生成器来检查不设有的
Cookie,此错误会造成虚假 库克(Cook)ie 添加到响应中。使用整数索引生成器作为
GetCookieFromResponse 可以解决该问题。

图片 3回来页首

视图状态:无声的性质杀手

从某种意义上说,视图状态是有史以来最伟大的事体。毕竟,视图状态使得页面和控件可以在回发之间保持状态。因而,您不要像在价值观的
ASP
中这样编写代码,以预防在单击按钮时文本框中的文本消失,或在回发后再次查询数据库和再一次绑定
DataGrid。

不过视图状态也有瑕疵:当它增长得过大时,它便成为一个冷清的特性杀手。某些控件(例如文本框)会基于视图状态作出相应判断。其他控件(特别是
DataGrid 和 GridView)则依据显示的音信量确定视图状态。固然 GridView 显示200 或 300 行数据,我会望而生畏。固然 ASP.NET 2.0 视图状态大致是 ASP.NET
1 x 视图状态的一半轻重,一个糟糕的 GridView 也可以容易地将浏览器和 Web
服务器之间的连日的有效性带宽收缩 50% 或更多。

您可以经过将 EnableViewState 设置为 false
来关闭单个控件的视图状态,但某些控件(特别是
DataGrid)在无法使用视图状态时会失去一些功效。控制视图状态的更佳解决方案是将其保存在服务器上。在
ASP.NET 1.x 中,您能够重写页面的 LoadPageStateFromPersistenceMedium 和
SavePageStateToPersistenceMedium 方法并按您喜爱的点子处理视图状态。
4

中的代码显示的重写可预防视图状态保留在隐藏字段中,而将其保存在对话状态中。当与默认会话状态进程模型一起行使时(即,会话状态存储在内存中的
ASP.NET
襄助进程中时),在对话状态中贮存视图状态更是有效。相反,倘使会话状态存储在数据库中,则只有测试才能显得在对话状态中保存视图状态会增进或者回落性能。

在 ASP.NET 2.0 中接纳同一的点子,可是 ASP.NET 2.0
能够提供更简单的主意将视图状态保留在对话状态中。首先,定义一个自定义页适配器,其
GetStatePersister 方法再次回到 .NET Framework SessionPageStatePersister
类的一个实例:

public class SessionPageStateAdapter :
System.Web.UI.Adapters.PageAdapter
{
public override PageStatePersister GetStatePersister ()
{
return new SessionPageStatePersister(this.Page);
}
}

然后,通过将 App.browsers 文件按以下措施放入应用程序的 App_Browsers
文件夹,将自定义页适配器注册为默认页适配器:

<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.Page"
adapterType="SessionPageStateAdapter" />
</controlAdapters>
</browser>
</browsers>

(您可以将文件命名为您喜爱的其余名称,只要它的扩张名为 .browsers
即可。)此后,ASP.NET 将加载页适配器并应用再次来到的
SessionPageStatePersister 以保存所有页面状态,包括视图状态。

接纳自定义页适配器的一个败笔是它全局性地效用于应用程序中的每一页。若是您更乐于将中间部分页面的视图状态保留在对话状态中而不保留其他页面的视图状态,请使用
4

中呈现的法子。另外,要是用户在同一会话中创设三个浏览器窗口,您使用该形式也许会遇见题目。

图片 4回去页首

SQL Server 会话状态:另一个性能杀手

ASP.NET 使得在数据库中储存会话状态变得简单:只需切换 web.config
中的开关,会话状态就会轻松地移动到后端数据库。对于在 Web
领域中运作的应用程序来说,这是一项重大意义,因为它同意该领域中的每个服务器共享会话状态的一个公共库。添加的数据库活动降低了单个请求的特性,可是可伸缩性的增长弥补了性能的损失。

这看起来都还不易,不过你略微考虑一下下列几点,意况就会并驾齐驱:

即使在使用会话状态的应用程序中,大多数页也不使用会话状态。

默认情况下,ASP.NET 会话状态管理器对每个请求中的会话数据存储执行两个访问(一个读取访问和一个写入访问),而不管请求的页是否使用会话状态。

换句话说,当您使用 SQL Server™
会话状态选项时,您在各样请求中都要付出代价(三个数据库访问)—
甚至在与会话状态无关的页面的呼吁中。这会一直对所有网站的吞吐量造成负面影响。

 

图片 5

图 5 消除不必要的对话状态数据库访问

 

那么你应该咋做吧?很简短:禁用不利用会话状态的页中的会话状态。这样做总是一个好点子,然而当会话状态存储在数据库中时,该措施更加重点。图
5 彰显怎么禁用会话状态。假使页面根本不使用会话状态,请在其 Page
指令中带有 EnableSessionState=”false”,如下所示:

<%@ Page EnableSessionState="false" ... %>

该指令阻止会话状态管理器在各样请求中读取和写入会话状态数据库。尽管页面从会话状态中读取数据,但却不写入数据(即,不修改用户会话的内容),则将
EnableSessionState 设置为 ReadOnly,如下所示:

<%@ Page EnableSessionState="ReadOnly" ... %>

末尾,假如页面需要对会话状态举办读/写访问,则省略 EnableSessionState
属性或将其设置为 true:

<%@ Page EnableSessionState="true" ... %>

因而以这种办法控制会话状态,可以保证 ASP.NET
只在真的需要时才访问会话状态数据库。消除不必要的数据库访问是构建高性能应用程序的第一步。

顺便说一下,EnableSessionState 属性是公然的。该属性自 ASP.NET 1.0
以来就曾经进展了印证,然而我迄今仍很少见到开发人士利用该属性。也许是因为它对于内存中的默认会话状态模型并不特别重点。不过它对于
SQL Server 模型却很首要。

图片 6归来页首

未缓存的角色

以下语句平常现身于 ASP.NET 2.0 应用程序的 web.config 文件以及介绍
ASP.NET 2.0 角色管理器的示范中:

<roleManager enabled="true" />

但相比以上所示,该语句实在会对性能发生彰着的负面影响。您了解为何吧?

默认情形下,ASP.NET 2.0
角色管理器不会缓存角色数据。相反,它会在历次需要确定用户属于哪个角色(如若有)时参照角色数据存储。这象征一旦用户通过了身份验证,任何利用角色数据的页(例如,使用启用了广安缩短设置的网站图的页,以及利用
web.config 中基于角色的 URL
指令举办访问受到限制的页)将造成角色管理器查询角色数据存储。假设角色存储在数据库中,那么对于每个请求需要拜访两个数据库的情景,您可以轻松地铲除访问四个数据库。解决方案是安排角色管理器以在
Cookie 中缓存角色数据:

<roleManager enabled="true" cacheRolesInCookie="true" />

您可以使用其他<roleManager> 属性控制角色 Cookie 的性状 —
例如,库克(Cook)ie
应维持有效的时限(以及角色管理器因而回到角色数据库的效能)。角色 库克(Cook)ie
默认情状下是由此签字和加密的,因此安全风险即使不为零,但也享有缓解。

图片 7回来页首

布置文件属性体系化

ASP.NET 2.0
配置文件服务为保全每个用户的情状(例如个性化首选项和言语首选项)的题目提供了一个现成的缓解方案。要采取安排文件服务,您可以定义一个
XML 配置文件,其中含有要保留的表示单个用户的属性。然后,ASP.NET
编译一个蕴含相同属性的类,并由此抬高到页的布置文件属性提供对类实例的强类型访问。

部署文件灵活性很强,它甚至同意将自定义数据类型用作配置文件属性。然则,其中却存在一个题目,我亲眼看到该问题导致开发人士出差错。
6

包含一个名为 Posts 的大概类,以及将 Posts
用作安排文件属性的配置文件定义。可是,该类和该配置文件在运作时会发生出人意料的行为。您能找出里面的案由吧?

问题在于 Posts 包含一个名为 _count
的个体字段,该字段必须开展系列化和反序列化,才能完全冰冻和重复冻结类实例。但是
_count 却尚无经过序列化和反系列化,因为它是个体的,而且默认情状下
ASP.NET 配置文件管理器使用 XML
连串化对自定义类型举办系列化和反连串化。XML
体系化程序将忽略非公共成员。因此,会对 Posts
的实例举行体系化和反连串化,不过每一回反连串化类实例时,_count 都会重设为
0。

一种缓解方案是使 _count
成为公共字段而非私有字段。另一种缓解方案是选择集体读/写属性封装
_count。最佳解决方案是将 Posts 标记为可连串化(使用
SerializableAttribute),并将配置文件管理器配置为利用 .NET Framework
二进制体系化程序对类实例举办连串化和反系列化。该解决方案可以保持类本身的筹划。与
XML
连串化程序不同的是,二进制类别化程序系列化字段,而无论是是否足以访问。
7

显示 Posts 类的修补版本并鼓起体现了改动的附带配置文件定义。

你应该记住的一些是,假若您使用自定义数据类型作为配置文件属性,并且该数据类型具有必须体系化才能完全系列化类型实例的非公共数据成员,则在性能阐明中行使
serializeAs=”Binary”
属性并保管项目我是可连串化的。否则,将无法展开一体化的系列化,并且您还将浪费时间来品尝确定安排文件不能工作的原因。

图片 8归来页首

线程池饱和

在实践数据库查询并等候 15
秒或更长日子来收获重临的查询结果时,我时常对看到的实在的 ASP.NET
页数感到很是诧异。(我也伺机了 15
分钟才来看查询结果!)有时,延迟是由于再次回到的数据量很大而致使的不可防止的没法结果;而有时,延迟则是由于数据库的宏图不好导致的。但无论是何许来头,长日子的数据库查询或任何类型的长日子
I/O 操作在 ASP.NET 应用程序中都会造成吞吐量的下落。

至于那些问题我原先曾经详细地叙述过,所以在此就不再作过多的辨证了。我只说一点就够了,ASP.NET
依赖于简单的线程池处理请求,假使持无线程都被占用来等待数据库查询、Web
服务调用或此外 I/O
操作完成,则在某个操作完成同时释放出一个线程往日,其他请求都必须排队等候。当呼吁排队时,性能会急剧下降。假诺队列已满,则
ASP.NET 会使随后的请求失利并冒出 HTTP 503 错误。这种场所不是我们愿目的在于Web 生产服务器的生育应用程序上所乐见的。

化解方案非异步页面莫属,这是 ASP.NET 2.0
中极品却鲜为人知的功力之一。对异步页面的乞求从一个线程上上马,不过当它开始一个
I/O 操作时,它将赶回该线程以及 ASP.NET 的 IAsyncResult
接口。操作完成后,请求通过 IAsyncResult 布告 ASP.NET,ASP.NET
从池中领取另一个线程并完成对请求的拍卖。值得注意的是,当 I/O
操作暴发时,没有占用线程池线程。这样可以透过阻止其他页面(不实施较长的
I/O 操作的页面)的呼吁在队列中等候,从而显明地增长吞吐量。

您可以在 MSDN®Magazine 的 2005 年 10
月刊
中阅读有关异步页面的装有消息。I/O
绑定而不是电脑绑定且需要很长日子执行的其他页面很有可能变成异步页面。

当自身将有关异步页面的新闻告知开发人员时,他们平日回答“这真是太棒了,可是自己的应用程序中并不需要它们。”对此我回复说:“你们的此外页面需要查询数据库吗?它们调用
Web 服务啊?您是否早已检查 ASP.NET
性能计数器中关于排队请求和平均等待时间的总括消息?虽然你的应用程序至今运行正常化,然而随着您的客户规模的增长,应用程序的载重可能会增多。”

实际,绝大多数实际的 ASP.NET 应用程序都亟需异步页面。请牢记这或多或少!

图片 9再次来到页首

模拟和 ACL 授权

以下是一个大概的布局指令,但是每当在 web.config
中来看它时都让自身赏心悦目:

<identity impersonate="true" />

此命令在 ASP.NET
应用程序中启用客户端模拟。它将意味客户端的访问令牌附加到拍卖请求的线程,以便操作系统执行的安全性检查针对的是客户端身份而不是支援进程身份。ASP.NET
应用程序很少需要效法;我的经验告诉自己,开发人士平常都是由于错误的原故而启用模拟的。以下是原因所在。

开发人员平时在 ASP.NET
应用程序中启用模拟,以便可以拔取文件系统权限来界定对页面的访问。如若 鲍勃没有翻动 Salaries.aspx
的权柄,则开发人员将会启用模拟,以便可以透过将访问控制列表 (ACL)
设置为拒绝 鲍勃 的读取权限,阻止 鲍伯 查看
Salaries.aspx。可是存在以下隐患:对于 ACL 授权来说,模拟是不必要的。在
ASP.NET 应用程序中启用 Windows 身份验证时,ASP.NET 会自动为呼吁的各种.aspx 页面检查 ACL
并驳回没有读取文件权限的调用者的呼吁。即便禁用了仿照,它仍会这样操作。

一对时候需要评释模拟的创建。但是你平日可以用精良的计划来制止它。例如,假定
Salaries.aspx
在数据库中询问只有管理人士才能清楚的工资新闻。通过模拟,您可以行使数据库权限拒绝非管理人员查询工资多少的能力。或者你可以不考虑模拟,并且经过为
Salaries.aspx 设置 ACL
以使非管理人员不拥有读取权限,从而限制对工资多少的访问。后一种办法提供的习性更佳,因为它完全防止了仿照。它也驱除了不必要的数据库访问。为何查询数据库仅出于安全原因被拒绝?

附带说一下,我早就匡助对一个观念的 ASP
应用程序举行故障排除,该应用程序由于内存占用不受限制而定期重新启航。一个一直不经验的开发人士将对象
SELECT 语句转换成了 SELECT
*,而从未考虑要询问的表包含图像,这多少个图像很大并且数量很多。问题由于未检测到内存泄漏而恶化。(我的托管代码领域!)多年来运行如常的应用程序开头突然停下工作,因为此前重回一两千字节数量的
SELECT
语句现在却重返了几兆字节。要是再加上不充足的版本控制,开发公司的活着将只好“亢奋起来”—
这里所谓的“亢奋”,就似乎当您在晚间要睡觉时,还只赏心悦目着你的子女玩令人深恶痛绝的足球游戏一样。

辩护上,传统的内存泄漏不会生出在一齐由托管代码组成的 ASP.NET
应用程序中。然而内存使用量不足会通过强制垃圾收集更频繁地发生而影响属性。即使是在
ASP.NET 应用程序中,也要小心 SELECT *!

图片 10回到页首

并非完全看重它 — 请设置数据库的部署文件!

作为一名顾问,我不时被问询怎么应用程序没有按预期执行。如今,有人打听自己的公司为什么ASP.NET 应用程序只完成请求文档所需吞吐量(每秒的请求数)的光景
1/100。我们在此之前所发现的题材是我们在无法健康运转的 Web
应用程序中发现的题目特有的 — 和我们所有人应该认真对待的训诫。

咱俩运行 SQL Server Profiler
并监视此应用程序和后端的数据库之间的彼此情形。在一个更可是的案例中,仅仅只是一个按钮单击,就招致数据库暴发了
1,500
五个错误。您无法那么构建高性能的应用程序。非凡的序列布局总是从理想的数据库设计开首。不管您的代码的效能有多高,假如它被编辑不好的数据库所牵连,就会不起效率。

不好的多寡访问连串布局平常来自下边的一个或两个地点:

拙劣的数据库设计(通常由开发人员设计,而不是数据库管理员)。

DataSets 和 DataAdapters 的使用 — 尤其是 DataAdapter.Update,它适用于 Windows 窗体应用程序和其他胖客户端,但是对于 Web 应用程序来说通常不理想。

具有拙劣编制计算程序、以及执行相对简单的操作需消耗很多 CPU 周期的设计糟糕的数据访问层 (DAL)。

总得先确定问题才能对其展开处理。确定数据访问问题的办法是运行 SQL Server
Profiler
或同一的工具以查看后台正在进行的操作。检查应用程序和数据库之间的通信之后,性能调整才成就。尝试一下
— 您或许会对您的觉察震惊。

图片 11回来页首

结论

现今您曾经通晓在生成 ASP.NET
生产应用程序过程中或许境遇的部分题目及其解决方案了。下一步是细心查阅您自己的代码并尝试避免自己在此概述的片段问题。ASP.NET
可能降低了 Web
开发人士的窍门,不过你的应用程序完全有理由灵活、稳定和快速。请认真考虑,制止出现新手易犯的荒唐。


8

提供了一个简易检查列表,您可以拔取它来避免本文中讲述的瑕疵。您可以创制一个接近的钦州缺陷检查列表。例如:

您是否已经对包含敏感数据的配置节进行加密?

您是否正在检查并验证在数据库操作中使用的输入,是否使用了 HTML编码输入作为输出?

您的虚拟目录中是否包含具有不受保护的扩展名的文件?

一经你重视网站、承载网站的服务器以及它们所依靠的后端资源的完整性,则这多少个题目特别关键。