RSS 2.0 Feed
2006-11 Entries
摘要:【原文地址】 Extending the ASP.NET 2.0 Localization Model with a Database Resource Provider 【原文发表日期】 Wednesday, November 29, 2006 10:04 PM 今春早些时候,Michèle Leroux Bustamante 在MSDN上写了一篇题为《ASP.NET 2.0本地化特性:本地化Web应用的一个新颖方法》的精彩文章。它讨论了如何使用ASP.NET 2.0中的新本地化特性来建造本地化的,culture-aware的Web应用的基本知识。 想观看如何尽快地运用这些本地化技巧,我也强烈建议你看一下这个13分钟的免费录像:《我该如何使用本地化来创建多语言网站?》。这个录像是非常精彩的《ASP.NET 2.0 How Do I 》录像系列中的一部,演示了如何按步就班地从头建造起和本地化一个ASP.NET应用,以及如何根据来自客户端的user-agent字符串来动态地选择语言,和让用户通过一个语言下拉框来直接选择语言。 在过去的几个月内大家常问的一个问题是哪里有更好的文档,描述了如何在内置于ASP.NET 2.0 和 VS2005中默认的基于XML的RESX 方案之外的资源提供器里存储本地化的资源字符串。上个月,Michelle在MSDN上发表了另一篇题为《扩展ASP.NET 2.0资源提供器模型》的精彩文章。这篇文章集中介绍了那些允许开发人员从另外的存储地方获取资源,以及与页面分析,编译,以及运行时执行集成的特性。该文还包含了演示如何使用数据库储存本地化资源内容的细节和样例代码。 Michelle在今后还会发表本地化系列中的另外2篇文章,这些文章将讨论如何进一步与VS 2005集成资源提供器,以及如何处理复杂的资源层次结构等。 希望本文对你有所帮助, Scott 标签: ASP.NET, .NET...[阅读全文]

posted @ | Feedback (0) | Filed Under [ ASP.NET .NET ]

摘要:【原文地址】 Tip/Trick: Implement "Donut Caching" with the ASP.NET 2.0 Output Cache Substitution Feature 【原文发表日期】 Tuesday, November 28, 2006 12:17 AM 一些背景: ASP.NET中一个强大无比,但往往未被充分利用的功能是它丰富的缓存设施。ASP.NET的缓存功能允许你在服务端避免为来自客户端的每一个新请求做重复的工作,而是,你可以一次生成HTML内容或数据结构,然后在服务器端ASP.NET中缓存或存储其结果,在以后的web请求中重用这些结果。这可以极大地提高你应用的性能,降低对象数据库这样的关键后台资源的负载。 Steve Smith 几年前曾在MSDN上写过一篇很好的关于ASP.NET 1.1 中缓存的文章,讨论了ASP.NET 1.1 缓存功能的一些基本知识,并且对如何使用它们提供了一个很好的总结。如果你以前从没有用过ASP.NET 缓存的话,我建议你先读一下这篇文章,并对其中的每个特性都尝试一下。我也非常建议你观看一下ASP.NET 2.0 免费录像系列中的这个15分钟的关于ASP.NET缓存的“How Do I”录像,这个录像实战演示了ASP.NET 缓存。 ASP.NET 2.0添加了2个非常重要的改进,使得缓存功能更加完善: 1) 对SQL缓存失效的支持 - 这允许你在缓存的页面或数据结构所依赖的数据表或记录行被更新时,使缓存内容自动失效然后重新生成缓存内容。例如,你可以在一个电子商务网站上输出缓存你所有的产品列表网页,然后确信在数据库中的产品价格一旦有所变动,这些网页就会在下一个请求时重新生成,这样就不会向用户显示过期的价格数据了。 2) 输出缓存的替换 - 这个奇妙的特性允许你实现我有时称之为“甜圈缓存(donut caching)” 的功能,在这里,你输出缓存页面上的所有东西,但除了几个包含在缓存区域内的动态区域外。这允许你更积极地实现整页输出缓存,不用为了实现局部页面缓存而把你的页面分成多个.ascx用户文件。下面这个技巧/诀窍指南更好地解释了这个特性的促动因素以及其实现。 实战中的场景: 你要在你的网站上实现一个产品列单网页,在上面列出在某个指定产品分类下的所有产品。你也想要输出缓存这个网页,这样,你就不用在每次请求时都访问数据库。你在Products.aspx 网页的顶部用声明的方式添加一个 <%@ OutputCache %> 指令就可以很轻松地达成这个目的,该网页上包含一个绑定到从你的中间层返回的产品数据的 <asp:datalist> 控件。 注意下面该网页是如何设置输出缓存它的内容 100,000 秒或者直到northwind数据库中的 products数据表为新的价格数据所更新为止,在后面这个情形下,下一个请求时,它就会重新生成页面。OutputCache 指令还有一个VaryByParam 属性,它告诉 ASP.NET 为每个独特的categoryID 单独储存一份缓存页面。譬如,Products.aspx?categoryId=1,Products.aspx?categoryId=2等等各有一个单独的缓存页面。 Products.aspx: <%@ Page Language="VB" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="Products.aspx.vb" Inherits="Products" %><%@ OutputCache Duration="100000" VaryByParam="CategoryID" SqlDependency="northwind:products" %><asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"><div class="catalogue">    <asp:DataList ID="DataList1" RepeatColumns="2" runat="server">        <ItemTemplate>                    <div class="productimage">                <img src="images/productimage.gif" />            </div>                    <div class="productdetails">                            <div class="ProductListHead">                    <%#Eval("ProductName")%>                </div>                                <span class="ProductListItem">                    <strong>Price:</strong>                    <%# Eval("UnitPrice", "{0:c}") %>                </span>                            </div>                </ItemTemplate>    </asp:DataList>        <h3>Generated @ <%=Now.ToLongTimeString()%></h3></div></asp:Content> Products.aspx.vb: Partial Class Products    Inherits System.Web.UI.Page    Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load        Dim products As New NorthwindTableAdapters.ProductsTableAdapter        DataList1.DataSource = products.GetProductsByCategoryID(Request.QueryString("categoryId"))        DataList1.DataBind()    End SubEnd Class 浏览器访问时,从服务器端返回下面这个页面: 注意,页面底部的时间戳每隔100,000秒,或者当products数据表里的价格数据被更新时,才会被更新。它将会被缓存起来以应付所有其他的 HTTP 请求,允许我们在生产服务器上每秒处理1000个请求,避免了不必要的数据库访问,从而使得访问的速度极快。 问题: 我们在上面的例子中将会遇到的一个问题,跟我们在页面右上方输出的欢迎消息和用户名字(在上面红圈中)有关。目前这是在我们的Site.Master母板页文件中通过使用一个新的ASP.NET 2.0 <asp:loginname> 控件来生成的,象这样: <div class="header">    <h1>Caching Samples</h1>                <div class="loginstatus">        <asp:LoginName FormatString="Welcome {0}!" runat="server" />    </div>        </div> 我们将撞上的问题是,因为我们给我们的页面加了整页输出缓存,第一个访问网站的用户的名字将被保存到页面的缓存输出中,这意味着,在默认情形下,在初始请求之后的 100,000 秒之内访问网站的用户将收到一个错误的欢迎消息,更糟糕的是,显示的是错误的用户名字! 解决方案: 有2个方法可以解决这个问题。 第一个方案是将整个页面做成动态的,即去除顶层的 <%@ OutputCache......[阅读全文]

posted @ | Feedback (10) | Filed Under [ ASP.NET Tips and Tricks ]

摘要:【原文地址】 Tip/Trick: How to Register User Controls and Custom Controls in Web.config 【原文发表日期】 Sunday, November 26, 2006 12:57 PM 去年我一直把这个技巧包含在我的ASP.NET 技巧/诀窍讲座里,但倘若有这么多人总是为它的存在而感到惊讶的话,我想值得用一个专属的技巧/诀窍帖子来提高它的可见度 (点击这里阅读我的ASP.NET 技巧/诀窍系列里的其他帖子)。 问题: 在ASP.NET 的早先版本里,开发人员通过在页面的顶部添加 <%@ Register %> 指令来引入和使用自定义服务器控件和用户控件时,象这样: <%@ Register TagPrefix="scott" TagName="header" Src="Controls/Header.ascx" %><%@ Register TagPrefix="scott" TagName="footer" Src="Controls/Footer.ascx" %><%@ Register TagPrefix="ControlVendor" Assembly="ControlVendor" %><html><body>    <form id="form1" runat="server">        <scott:header ID="MyHeader" runat="server" />    </form></body></html> 注意到上面的前两个注册指令是用来注册用户控件的(是在.ascx文件里实现的),最后这个是用来注册编译进一个程序集 .dll 文件里的自定义控件的。注册完后,开发人员可以在页面的任何地方用设定好的 tagprefix (标识前缀)和标识符号名( tagname)来声明这些控件。 这行之有效,但管理起来会很痛苦,当你要在你的网站的许多页面上使用控件的话,尤其是,假如你移动了.ascx 文件,需要更新所有的注册声明的话。 解决方案: ASP.NET 2.0 使得控件声明极其干净而且管理起来极其容易。不用在你的页面上重复这些声明,只要在你的应用的web.config 文件的新的 pages->controls 部分声明一次即可: <?xml version="1.0"?><configuration>  <system.web>        <pages>      <controls>        <add tagPrefix="scottgu" src="~/Controls/Header.ascx" tagName="header"/>        <add tagPrefix="scottgu" src="~/Controls/Footer.ascx" tagName="footer"/>        <add tagPrefix="ControlVendor" assembly="ControlVendorAssembly"/>      </controls>    </pages>  </system.web></configuration> 你可以用这种方式同时声明用户控件和编译好的自定义控件。当你使用这个技巧时,Visual Studio是完全支持这两者的,而且 VS 2005 Web Site 项目 和 VS 2005 Web Application 项目也都支持这两者。Visual Studio会在设计器里以所见即所得(WYSIWYG)模式显示这些控件,也会在后台编码文件里提示控件字段的声明。 需要注意的是,上面用户控件中“~”句法的使用。对那些不熟悉这个符号的人,ASP.NET中“~”符号意思是“从应用的根路径来定位”,它提供了一个很好的方法来避免在你的编码里到处使用“..\”。在web.config文件里声明用户控件时,你总是应该使用它,因为页面也许会使用在不同子目录里的控件,所以你应该总是始终如一地从应用的根路径开始定位这些控件。 一旦你在web.config 文件中声明好这些控件后,你就可以在你网站上的任何一个页面,母板页或者用户控件中使用它们了,象这样(不再需要注册指令): <html><body>    <form id="form1" runat="server">        <scottgu:header ID="MyHeader" runat="server" />    </form></body></html> 希望本文对你有所帮助, Scott 附注:特别感谢 Phil Haack ,他在这个月的早先时候也曾在博客里讨论过这个技巧。对你们中间那些不认识 Phil 的人,他帮忙建造了非常受欢迎的 SubText博客引擎,而且拥有一个非常精彩的博客。 标签: ASP.NET, Visual Studio, .NET, Tips and Tricks...[阅读全文]

posted @ | Feedback (12) | Filed Under [ ASP.NET .NET Visual Studio Tips and Tricks ]

摘要:【原文地址】 Common Gotcha: Don't forget to when adding providers 【原文发表日期】 Monday, November 20, 2006 11:22 PM 最近,我帮了几个人,他们在如何在web.config文件里添加新的成员(Membership),角色(Role)和用户信息(Profile)提供器(provider)上遇上了问题。如果你会在你的web.config文件里添加提供器声明的话,请继续读下去,了解一下如何避免一个常见的问题。 症状: 你要配置ASP.NET 2.0来在远程SQL数据库里存储你的成员/角色管理/用户信息数据。为达成这个目的,你首先使用aspnet_regsql.exe工具在数据库里生成了合适的数据定义。你决定不在你的web.config文件里覆盖"LocalSqlServer"这个连接字符串,而是象下面这样,在你的web.config文件里注册一个新的提供器 (注:下面这个注册有个bug,所以别拷贝/粘贴):       <membership>            <providers>                <add name="AspNetSqlMembershipProvider"                    type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"                    connectionStringName="MyDatabase"                    enablePasswordRetrieval="false"                    enablePasswordReset="true"                    requiresQuestionAndAnswer="true"                    requiresUniqueEmail="false"                    passwordFormat="Hashed"                    maxInvalidPasswordAttempts="5"                    minRequiredPasswordLength="7"                    minRequiredNonalphanumericCharacters="1"                    passwordAttemptWindow="10"                    passwordStrengthRegularExpression=""                     applicationName="/"                 />            </providers>      </membership> 在注册上面这个提供器时,你很小心地明确设置了applicationName属性,因此避免了另外一个非常常见的问题。 但,当你在一个没有SQL Express的机器上运行你的应用时,你看到了有点奇怪的行为。你也许会得到象这样的出错信息: An error has occurred while establishing a connection to the server.  When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified) (在建立到服务器的连接时发生了错误。 当连接到 SQL Server 2005时,连接失败可能是因为在默认设置下 SQL Server 不允许远程连接这个事实导致的。(提供器:SQL网络接口,错误:26 - 查找指定服务/实例时出错)) 你也许会发现web管理工具在连接到你的数据库时也有问题,或者你用它创建的角色/用户没有在上面配置的数据库里正确地存储下来。 问题的起因: 上面这个问题的根本原因取决于新的提供器是如何在web.config 文件注册的。 web.config 文件里的......[阅读全文]

posted @ | Feedback (2) | Filed Under [ ASP.NET .NET Tips and Tricks Security ]

摘要:【原文地址】 Podcasts and Prototyping 【原文发表日期】 Sunday, November 19, 2006 11:37 PM Ron Jacobs 最近发布了他的 ARCast.net 节目里采访我的播客(podcast),该节目是个面向架构师的免费podcast系列。在这一期的podcast里,我们讨论了几个大家也许会发现比较有趣的主题: .NET,特别是ASP.NET后面的一些历史 原型开发(prototyping)的重要性以及如何不把它搞砸了 培养成功的架构师所需的“软技能(soft skills)”的重要性 原型开发的讨论,我想,对外面的许多项目都有很多的相关性。这是个我真的建议所有的开发人员都应该花更多的时间去做的最佳实践。因为做得好的话,确实允许你实验和很快地尝试很多主意和概念性的东西,可以帮助你在你的项目里在创新方面有显著的提高。 原型开发关键的东西在于,保证你绝对不把原型代码变形转化成生产代码(production code)。别试着对原型代码整理(clean up)或提炼(refine)使之成为生产级别的代码。这类“整理(clean up)”往往走得不够远,其结果是,使得项目的起始基础很差。把“快捷而质量不高(quick and dirty)”的代码导入到代码库里就象是把一个坏苹果扔进一筐好苹果里一样,你很容易会以code rot(代码腐烂)在代码库里蔓延而告终。 从空白的新项目开始总归是最好的,然后把原型的概念,而不是原型的代码引入到项目里来。在前面花额外的时间确保新的生产代码是从100%的生产质量起步的,别试着通过重用原型里的代码来节省几天的时间。你会发现,在一个原型开发练习之后,从头开始编写“真正的”生产代码会比你预期的要快很多,因为那些关键想法在你的脑子里已经是有形有肉了(fleshed out),因此你对实现( implementation)应该如何组织会有一个极其深刻的理解。代码质量的标准也显著地提高了。 我最近在实现一个想法时就遇上了这样的事情,这个想法是在过去几个周末的业余时间里,我一直在用原型开发来实验的很多想法中的一个。我有些非常复杂的调度逻辑我一直在编写,并且随着我试验各种功能和方法时,这个逻辑也一直在变。我知道,一旦对其中一些编程模型方面的想法试验完毕之后,我应该能够将它整理得很干净的,但它一直不干净,直到昨晚,我腾出了几个小时来从头编写新的实现时,我才看到我能在那个迭代开发出来的原型之上得到多么显著的改进。我猜想,大多数人,如果训练有素,并且确定在使用原型方法完成迭代开发/从中学到东西之后有意识地扔掉原型代码的话,都是能看到类似的编码改进或质量的结果的。 想完整收听这个podcast的话 ,请访问Ron的这个podcast连接。 希望本文对你有所帮助, Scott 附注:我刚看到Paul Glavich 在这里贴出了另一个采访我的podcast 。这第二个podcast 节目的内容包括,ASP.NET AJAX (即 Atlas), WPF/e,Windows Workflow/Cardspace,BLINQ 和Script#,以及 Visual Studio 2005 SP1。也一定要去看一下! 标签: ASP.NET, .NET, Talks...[阅读全文]

posted @ <