【原文地址】 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
【原文地址】 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 Sub
End 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 %> 指令,对页面的内容重构,把所有可缓存的内容都封装在ASP.NET用户控件中,这些用户控件是通过 .ascx 文件来实现的。然后你在这些用户控件的每一个文件的顶部添加 <%@ OutputCache %> 指令,使得它们可以单独缓存。这避免了每次请求都需要访问数据库,确保了用户名字总是正确地输出的,因为用户名字不在缓存的用户控件区域里。这个方法目前在ASP.NET 1.1 里就可行,当然,在ASP.NET 2.0依然行之有效。
但这个方案的缺点是,为使缓存可行,它要求我们重构我们页面的编码和布局。但假如我们在页面上只有几个地方我们想要保持动态,这个重构会非常不方便。好消息是,ASP.NET 2.0 增加了对输出缓存替换块(Output Cache Substitution block )的支持,它提供了一个极其干净的方法来处理这个场景。
使用 <asp:substitution>控件的输出缓存替换块:
输出缓存替换块允许你OutputCache整个页面的输出,同时在HTML输出中留下几个动态区域标记来指明在以后的请求中你需要动态填充内容的地方(譬如,上面例子中的用户名消息)。我有时把这称为“甜圈缓存(donut caching)功能”,因为外部的页面内容都是缓存的,只有页面内容流中间的几个孔(hole)是动态的。这与使用用户控件实现的局部页面缓存正好相反,因为在局部页面缓存的情形下,整个页面是动态的,中间的区域是缓存的。
你通过使用整页输出缓存的方式来实现输出缓存替换,使用与上面 Products.aspx 例子中完全一样的句法。然后,你可以通过在页面上添加 <asp:substitution> 控件来指明页面的哪些区域你需要动态地使用替换块来填充,象这样:
<div class="header">
<h1>Caching Samples</h1>
<div class="loginstatus">
<asp:Substitution ID="Substitution1" runat="server" MethodName="LoginText" />
</div>
</div>
<asp:Substitution> 控件与ASP.NET中的其他控件不同,它与 ASP.NET 的输出缓存注册了一个回调事件,当页面内容在后来的请求中从 ASP.NET输出缓存发出时,该事件会导致你的页面或母板页的一个静态方法的调用。这个静态方法在运行时会传进一个HttpContext 对象,它包含了ASP.NET Request, Response,User, Server,Session, Application等内在对象,然后你就可以使用它们来返回一个字符串,ASP.NET 会在内容发回客户端前自动把这个字符串注入到页面的相关区域里去。
譬如,在输出缓存的products.aspx 页面中,为处理上面这个我们需要动态输出欢迎消息的场景,我们只要简单地添加这个方法到我们的Site.Master后台代码文件中,然后让上面这个 <asp:substitution> 控件来调用:
Partial Class Site
Inherits System.Web.UI.MasterPage
Shared Function LoginText(ByVal Context As HttpContext) As String
Return "Hello " & Context.User.Identity.Name
End Function
End Class
这样,整个页面将被输出缓存,除了我们页面右上方的 <asp:substitution> 控件代表的欢迎消息的内容外。
很明显地,我们可以把这个进一步延伸,假如我们想要包括另外象用户他们的购物篮有多少样东西这样个人化的信息等。非常酷的是,页面上所有其他的内容仍然是保持完全缓存的,我们不用在后继请求里访问数据库来生成其内容,这意味着我们在单独一个服务器上每秒钟就可以处理成千个产品页。实际上,在请求中,不用生成页面上的任何控件,在以后的请求里,除了上面那个静态方法外,也没有编码会执行,这使得一切都快速无比。
使用Response.WriteSubstitution 方法的输出缓存替换块:
除了使用 <asp:substitution> 控件在页面上指定可替换的内容块外,你也可以使用 Response.WriteSubstitution 方法。这个方法接受一个HttpResponseSubstitutionCallback 方法的delegate对象为参数,你可以在你的应用的任何类里实现这个方法 (而不限于你后台类里的静态方法)。
<asp:substitution> 控件在内部使用这个方法来接连页面的后台类里的delegate方法。同样地,你也可以在你自己的控件或页面使用这个方法,以取得最大的控制和灵活性。
结论:
我还没有找到一个无法从ASP.NET缓存功能上受益的ASP.NET应用。因为ASP.NET支持整页输出缓存,局部页面输出缓存,以及现在的甜圈(donut)层次的缓存,这允许你根据任何参数或你需要的自定义逻辑来变换缓存内容,而现在又允许你在数据库改变时自动使得缓存内容失效并重新生成缓存内容,你不应该发现你自己再会建造一个用不上任何缓存的应用了。
我绝对建议你花点时间熟悉一下ASP.NET所有的缓存功能。想找到我完成的有关缓存的另外的例子的话,请下载我最近在ASP.NET Connections大会上做的技巧/诀窍讲座。下载内包括讲义和演示代码,说明如何使用整页缓存,局部页面缓存,替换块缓存(substitution block caching),以及SQL缓存失效(SQL Cache Invalidation)。
想阅读我写的其他ASP.NET技巧/诀窍博客帖子的话,请浏览我的ASP.NET技巧,诀窍和资源网页。
希望本文对你有所帮助,
Scott
【原文地址】 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博客引擎,而且拥有一个非常精彩的博客。
【原文地址】 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 文件里的 <providers> 节是以一个集合的方式实现的,所以有可能同时注册多个提供器。这是很有用的,当你要用一个成员储存来认证一些用户,而用另外一个成员储存来认证另外的用户时。
在默认情形下,ASP.NET 2.0在你的机器上的根web.config文件里注册了一批默认的 SQL Express提供器,在你第一次访问时,将在你的应用的/app_data 文件夹中生成一个SQL Express数据库,来存储/管理成员/角色/用户信息数据。因为这是在机器范围的层次上注册的,在默认情形下,所有的提供器集合都继承了这注册信息。除非你明确地设置 <clear/> 或者覆盖(override)了继承的值,你的应用会使用这默认注册的成员/角色/用户信息提供器。
因为上面这个web.config文件只是简单地添加了一个新的提供器,没有清除或替代默认的提供器注册信息,上面的应用现在配置了2个Membership提供器。当你在编码中调用Membership.CreateUser()时,ASP.NET会试着在这2个成员数据库里创建这个用户,如果你在你的系统上没有安装SQL Express的话,针对该数据库的用户创建就会失败,导致上述的错误或奇怪行为。
如何解决这个问题:
除非你想注册多个成员,角色或用户信息数据库(这样的情形应该是很少的),你应该在web.config文件里你的 <add/> 语句之前无例外地添加明确的 <clear/> 指令:
<membership>
<providers>
<clear/>
<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>
这将会确保你的应用不会继承任何默认的提供器注册设置。
注意,你必须对你注册的每个提供器声明都这么做。所以,如果你要添加 <roles> 和 <profile> 提供器,确认你在它们的提供器节也添加了 <clear/> 指令。
希望本文对你有所帮助,
Scott
附注:点击这里浏览一下以前的SP.NET Tips/Tricks, Gotchas, and Recipes文章。
【原文地址】 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。也一定要去看一下!
【原文地址】 IronPython for ASP.NET CTP
【原文发表日期】 Thursday, November 16, 2006 10:40 PM
几个月前,我曾经写过发布 IronPython v1.0 的事。IronPython是Python动态语言在.NET平台上的实现。它支持一个可交互的控制台,该控制台支持完全的动态编译,并且可以让Python程序员轻松地访问所有的.NET库,同时还保持对Python语言完全的兼容性。
IronPython 提供了.NET 编程语言可以如何利用我们在去年发行的.NET 2.0版本的CLR中新加入的动态语言特性的一个极好的例子。譬如,象“轻量级编码生成”这样的CLR特性,现在可以让动态语言很快地在内存里编译和JIT源码 (给予你非常快速的运行速度而不必生成一个.dll 文件)。CLR 2.0 还有把这些JIT过的代码垃圾回收的能力。这意味著,你可以在运行时很快地动态调整类型,而且不用泄漏生成的编码。
上个星期,我们发布了一个非常酷的CTP,提供了ASP.NET和Visual Web Developer Express(当然是免费的)中IronPython的集成支持。安装完毕后,你就可以在创建新的项目和页面时,使用Python作为你的语言选择,轻松地利用动态语言脚本的支持:
IronPython for ASP.NET CTP安装完毕之后, Visual Studio/Visual Web Developer 将为使用Python的ASP.NET项目提供行内(inline)代码和后台代码(code-behind)网页的支持,提供句法高亮显示,WYSIWYG 设计器,以及完整的调试支持。你也可以用它来创建居于App_Script 文件夹下的独立的python模块文件,将它们用于整个网站。
探究Python用法的最轻松的方式是,选择文件->新网站菜单项,然后创建一个 Python版的Personal Starter Kit样例网站(注意下面截图中扩展名为.py的后台代码文件):
上面的Personal Starter Kit Python 样例提供了一个酷的方式来开始学习Python,同时也利用了Python 提供的一些动态语言功能,以及 IronPython 开发组添加的与ASP.NET的良好集成特性。
例如,Photos.aspx网页提供了允许管理人员上传新的照片到相册的支持。这是通过一个使用了模板化插入模式UI的 FormView 控件来实现的,象这样:
<asp:FormView ID="FormView1" DefaultMode="insert" OnItemInserting="FormView1_ItemInserting" runat="server">
<InsertItemTemplate>
Enter Photo: <asp:FileUpload ID="PhotoFile" … />
Enter Caption: <asp:TextBox ID="PhotoCaption" … />
....
</InsertItemTemplate>
</asp:FormView>
在一个强类型语言里,你通常需要使用FormView1的FindControl()方法进入到它的模板里来获取FileUpload 或TextBox控件的引用,然后将该引用强制转换到返回对象的类型,才可以使用这些对象。但在象Python这样的动态语言中,你可以在你的Photos.aspx.py后台代码文件里写下面这样的编码:
import PhotoManager
def FormView1_ItemInserting(sender, e):
caption = FormView1.PhotoCaption.Text
bytes = FormView1.PhotoFile.FileBytes
if len(bytes) == 0:
e.Cancel = True
else:
PhotoManager.AddPhoto(Request.AlbumID, caption, bytes)
注意到没有,你只要写FormView1.PhotoCaption就可以访问模板里的子控件,然后直接引用它的子属性就可以了。这个技术也可以用在象 DataList,Repeater和Wizard这样模板化的控件上。真妙!
如何进一步了解 IronPython
查看一下 IronPython for ASP.NET 主页以进一步了解 IronPython for ASP.NET CTP。你也可以在这里阅读一下David Ebbo 写的精彩白皮书,该文描述了为更好地支持动态语言和编译而对ASP.NET分析器做的变动。
最后,想进一步了解 IronPython本身的话,我建议你观看一下这个9月份时Jod Udell采访Jim Hugunin的精彩录像广播(内有演示)。 Jim 现场编写了一些很酷的演示,包括使用IronPython创建一个与Speech API集成的WPF计算器应用。然后他也演示了如何把影响性能的关键代码从Python重构到象C#这样强类型的语言,以及两者是如何无缝地协作的。你现在可以把这些同样的技术使用在IronPython 和ASP.NET上。
希望本文对你有所帮助,
Scott
【原文地址】 Gotcha: Lost HTML Intellisense within ASP.NET AJAX Controls
【原文发表日期】 Thursday, November 16, 2006 7:55 AM
症状:
你在使用ASP.NET AJAX Beta1 或 Beta2,创建了基于 .master 母版页文件的一个.aspx 页面,你添加了 <asp:scriptmanger>, <asp:updatepanel>, <asp:updateprogress> 或 <asp:timer> 控件到内容页面,发现在这些控件或内嵌在它们中的任何控件里,标识符号的Intellisense功能不工作了:
在上面的截图里,注意到ScriptManager, UpdatePanel and ContentTemplate标识符的下面有红色的波浪形弯线。当你在文档里键入这些元素时,你也得不到标识符的自动完成。但你仍可以编译,运行也没问题,WYSIWYG 设计器照旧工作,但你失去了源码编辑器里的Intellisense功能。
该问题的一些背景知识:
ASP.NET 2.0添加了在web.config文件里注册控件的支持,无论是编译过的还是.ascx 用户控件,去掉了总是要在页面的上方添加 <%@ Register %> 指令的要求。想了解这方面的细节,或看一个实际例子,请查看我最近在 ASP.NET Connections 大会上做的技巧和诀窍讲座的内容。
这个特性的一个很酷的方面是,它现在也允许你把多个程序集映射到同个标识符前缀上。我们在ASP.NET AJAX 中使用了这个功能,以使上面这些控件使用 <asp:> 标识前缀,虽然它们居于包含了ASP.NET其他部分的 system.web.dll 外的另外的程序集之中。
不幸的是,我们在发布ASP.NET AJAX Beta1时,发现了VS标识符Intellisense引擎的一个缺陷,其问题在于,当你把多个程序集映射到同个 <asp:> 标识前缀时,而且在基于母版页的.aspx内容页面的 <asp:content> 里使用这些控件时,你会失去Intellisense功能。
如何解决这个问题
这个intellisense的问题将在VS 2005 SP1里解决。
与此同时,有2个替代方案,你可以马上修正这个问题:
1) 编辑.aspx内容网页时,在Visual Studio IDE中,把相关.master母版页文件保持在打开状态。发现其实只有在.master文件关闭时,Intellisense引擎才会出问题。只要该文件在同一个IDE里一直是打开的,它定位程序集毫无问题,会给予你完整的Intellisense功能:
上面的截图跟前面一个截图是同一个例子,唯一的区别是,我在后面同时打开了Site.Master 文件。那个文件打开时,我就得到ASP.NET AJAX控件元素的完整的Intellisense功能,没有Intellisense错误。
或者,如果你不想把 .master 文件保持打开的话,你也可以使用下面这个方法:
2) 进入你的web.config文件,把ASP.NET AJAX 控件的标识前缀改成不是 <asp:> 的别的东西。譬如,取代这个:
<controls>
<add tagPrefix="asp" namespace="Microsoft.Web.UI" assembly="Microsoft.Web.Extensions" />
<add tagPrefix="asp" namespace="Microsoft.Web.UI.Controls" assembly="Microsoft.Web.Extensions" />
</controls>
而把它们改成类似这样:
<controls>
<add tagPrefix="ajax" namespace="Microsoft.Web.UI" assembly="Microsoft.Web.Extensions" />
<add tagPrefix="ajax" namespace="Microsoft.Web.UI.Controls" assembly="Microsoft.Web.Extensions" />
</controls>
然后,你要将你的.aspx 页里的标识前缀更新到使用这个新的标识前缀。
上面2种方法都可以解决问题,还你完整的 intellisense 功能。这个问题应该会在VS 2005 SP1里被彻底解决。
希望本文对你有所帮助,我也为造成的不便表示歉意,
Scott
【原文地址】Nikhil's WebDevHelper Utility and ASP.NET AJAX Support
【原文发表日期】 Monday, November 13, 2006 10:24 PM
如果你还没订阅Nikhil的博客的话,你真的应该马上去访问并且开始订阅。
Nikhil 是 ASP.NET 开发组的架构师,他不停在他的博客上贴出新的酷工具和样例,当然,这些都是免费的。他的众多项目中有个Script# 项目,是个 C# 编译器,生成的输出是JavaScript,而不是IL,它允许你得到类安全,可重构,编译时代码检查。他也写了针对ASP.NET AJAX 的非常酷的支持前进/后退按钮的控件,我曾在9月份的博客里报道过。
今天早些时候,他发布了他的极受欢迎的WebDevHelper工具的更新版。更新版包括在使用 <asp:updatepanel> 控件时可以轻松地监测从 ASP.NET 返回的更新的HTML的支持。他的工具允许你记录和审视浏览器和服务器间的所有HTTP数据传输,使得调试AJAX代码轻松无比。例如,下图中,在页面上启动局部更新时,你可以看到从UpdatePanel中返回的HTML:
Nikhil还添加了新的支持,能审视JSON 网络请求以及逐层查看线上序列化的对象的细节。譬如,下图中,你可以看到通过 ASP.NET AJAX 网络协议层从服务器端返回的EXIF图片对象的属性。 Nikhil的工具能在客户端自动“探嗅”出这些东西来,允许你轻松审视它们:
他对输出跟踪语句也有支持,对使用WebDevHelper工具在JavaScript脚本代码中 dump (诊断转储) 对象也有支持。
你可以在这里进一步了解这个免费工具,在这里阅读Nikhil的关于如何使用这个工具的精彩文档。
希望本文对你有所帮助,
Scott
【原文地址】Office 2007, VS 2005 Tools for Office, and VS 2005 Extensions for SharePoint
【原文发表日期】 Monday, November 13, 2006 10:03 PM
上个星期微软发布了Office 2007。对你们中还没有试过它的人来说,这可能是自 Office 95 以来最大的Office产品发布,真的是个令人敬畏的的升级。其中最大的创新是新颖的Ribbon UI风格的引入,它提供了崭新的和显著改进的用户体验 (不再使用菜单了):
当我第一次听说Office在引进崭新的UI风格时,我起初的反应是,“哇,真够勇敢的”。可不是每一天都会有一个产品组愿意象这样打几十亿美元的赌的...
在过去的几个月内只用Office 2007做日常办公后,我真的要向Office产品组脱帽致敬,──这一步棋绝对是天才的一着。这个产品不光使我的生产力显著提高,而且使得用Office工作又变得好玩了。是如此好玩,以至于在今夏安装这个产品不久,它就引得我撰写了几篇 长长的 教程 帖子。你知道一个产品绝不会差,如果用它起来是如此地好玩,以至于让你在夏天的周末也留在屋里撰写教程帖子!
非常酷的是,这个星期也看到了对这个产品的不少好评开始进来,做评论的这些人真是喜爱这个产品呢。
现在就去MSDN下载中心下载Office 2007
如果你是MSDN订阅者,你现在就可以去MSDN下载中心下载Office 2007。它拥有一个正式的运行许可(production license),意味着,你可以用它来做所有/任何的日常事务。
想进一步了解其中的设计哲学和形成这些崭新体验的思路,我推荐你去阅读 Jensen Harris博客上的精彩帖子。Jensen是微软Office用户体验产品组的主管项目经理(Group Program Manager),他的博客与我们很好地分享了他们在新产品中所做的一切后面的一些设计哲学和背景。
VS 2005 Office工具
为从 .NET 开发人员的角度帮助你利用Office 2007,上个星期我们也发布了“VS 2005 Office工具”的更新版,允许你利用Office 2007里的新功能和UI。内含对新Ribbon扩展模型的支持。
你可以在这里进一步了解有关信息,和下载这个工具。也一定要去查看一下Visual Studio Tools for Office的博客。
VS 2005 之Windows SharePoint Services 3.0 扩展
为帮助你利用Windows SharePoint Services 3.0 和 Microsoft Office SharePoint 2007 (两者都支持与Office 2007的紧密集成),上个星期我们也发布了崭新的免费 VS 2005 Extensions for Windows SharePoint Services 3.0 下载。这个扩展工具提供了 Visual Studio 2005 对 SharePoint 网站的项目和build的支持。其中包括,在Visual Studio内,创建和build SharePoint网站中的Web Part,以及在项目里点击F5即可调试Web Part等支持。你可以 在这里下载这个工具。
Serge van den Oever 最近贴出了几篇如何使用这个工具的非常棒的教程:
我也建议你查看一下我以前的这篇博客帖子,里面指向了几篇非常棒的文章,教你如何使用ASP.NET 2.0内置的ASP.NET Web Part模型来建立丰富的SharePoint方案。Darren Neimke最近也出版了一本专注于ASP.NET 2.0 Web Part开发的很酷的新书:
你可以从这里去Amazon购买。
希望本文对你有所帮助,
Scott
【原文地址】ASP.NET Connections Slides + Demos
【原文发表日期】 Friday, November 10, 2006 11:36 PM
这个星期早些时候,我在于拉斯维加斯举行的ASP.NET Connections 大会上做了演讲。这是个一年2次的精彩大会,秋季的是在拉斯维加斯举行,春季的是在奥兰多举行。上个星期,仅参与ASP.NET Connections大会的就有1500多人之多,而参与所有DevConnections的则有4700多人之多。除了ASP.NET Connections外,同时举行的还有VS,SQL, SharePoint, Mobile 和 Office Connections大会 ,是在同一个地点举行的,参会人员允许参与任何讲座。
在大会开幕之夜,我向参与大会的所有人做了一个综述性的主题演讲。之后,我还做了三个ASP.NET方面的讲座:
ASP.NET AJAX 主题演讲
这个讲座展开(kick off)了会议的第一个整天,对我们的ASP.NET AJAX 1.0计划做了一个综述和几个从头开始的AJAX 演示。你可以 在这里下载相关的讲义和演示代码。
这个演讲的注目处是,来自Burton的Ben Noonan上台来展示他们在Burton的公开网站上实现的一些非常酷的ASP.NET AJAX 用例。Ben向参会人员很好地示范了他们使用ASP.NET AJAX 的一些方式, 还强调了他们看到的一些好的业务结果 ,无论是在一个用户花在他们网站上的平均时间的增加方面,还是因此带来的销售和收入的增加方面。
我们为大会做的趣事之一是定制了一个Burton ASP.NET AJAX 滑雪板(看右边的图片里滑雪板的样子)。Bill Gates 和 Jake Burton 都同意在上面签了名,昨天,我们通过抽奖把它送给了一个幸运的参会人员。
ASP.NET 技巧和诀窍
这个讲座讨论了ASP.NET UI,缓存和部署方面的技巧和诀窍,以及Visual Studio 2005的技巧和诀窍。你可以在这里下载相关的讲义和演示代码。
想进一步了解如何优化Visual Studio的build性能的话,你可以阅读一下我以前写的这篇相关的帖子。你还可以浏览我以前写的归档于“Tips and Tricks”标签下的帖子,从中你能找到很多篇有关ASP.NET 和Visual Studio技巧和诀窍的帖子。
ASP.NET 和 LINQ
这个讲座对将于明年发布的LINQ新技术做了一个概览,还对它将给ASP.NET带来的生产力的显著提高做了一些演示。点击这里下载相关的讲义和演示代码。
你可以阅读一下我以前写的几篇LINQ方面的帖子,来进一步了解LINQ以及如何将它用在ASP.NET里。下面是特别值得一读的几篇帖子:
就象我以前说过的,我认为LINQ是最酷的新.NET技术之一,绝对值得审阅和试验一下。
我预定的演讲日程
实际上,我已经结束了本年度的会议演讲,感觉轻松多了,因为今年我曾在阿姆斯特丹,赫尔辛基,尼斯,都柏林,奥克兰,悉尼,波士顿,奥兰多,达拉斯,和拉斯维加斯(2次)参与了活动。我盼望能在下2个月内呆在阳光明媚的西雅图,真的做我的日常工作。
明年的演讲日程还没有最后定下来。我将主讲的会议有,一月中旬在俄亥俄举行的CodeMash大会,三月在奥兰多举行的春季ASP.NET Connections大会,有可能会去三月在旧金山举行的SDWest大会(这个还没最后定下来),肯定会去四月三十日至五月二日举行的微软MIX07 大会。
五月份之后,我还没有确定的计划,虽然我大概会再去TechEd(美国)演讲,有可能挤出时间去一次欧洲, 明年非常有可能首行印度和日本。
希望早日见到你们,
Scott
附注:大家有时问我他们是否可以在他们自己的讲座里重用我的一些讲义和演示代码。答复是,绝对可以的!请你尽管重用我的博客上或我的讲座里的所有的内容好了,不用寻求许可或者注明出处。我贴出这些内容就是为了让尽可能多的人可以从中学到东西,所以,有你向别人传递这知识正是我之所愿。