You've been HAACKED中文版

英文原版地址:http://haacked.com

Phil Haack attemts to infuse technology and software development with humor and a pragmatic eye...

随笔 - 39, 评论 - 15, 引用 - 0

导航

关于

Phil Haack先生是著名博客引擎Subtext的主要开发人员,目前在微软总部担任资深程序经理,主要负责MVC架构相关的内容. 博客堂非常高兴成为Phil Haack先生中文版博客的存放站点,将更多关于ASP.NET MVC架构相关的知识与大家分享.为了保证翻译质量,现在面向所有博客堂堂友征集本博客的负责人员以及两名志愿翻译人员.
如果您有意愿请发送邮件至hanxianlong888[#]163.com 或留言
管理员:开心就好韩现龙dotlive

每月存档

最新留言

广告

【第1页/共4页,39条】
首页
前页
1
2009年07月01日

【原文地址】Writing A Page To A String

【原文发表日期】 May 29, 2009

ASP.NET页面通常是将它们内容直接输出到一个请求响应流(response stream)中。这对比较大型的页面来说应该是一个巨大的效率优化,因为这样做就不需要为页面显示而建立很大的缓冲区或者分配很大的字符串。而分配大型字符串的操作经常会在“大型对象堆栈”(Large Object Heap)上获取所需的内存,而这也意味着这些内存块不会被很快地资源回收。

 

 

 

然而,很多情况下你可能确实需要将一个页面的内容输出到一个字符串里以便进行一些后处理工作。关于这点,我N久之前也曾经写过一篇blog介绍了一个方法:就是使用response filter

不过,最近我学到了Page类中的一个我从没有注意到过的方法,这个方法提供了以上问题的一个更轻量级的解决方案。

我所说的就是CreateHtmlTextWriter这个方法,它是一个保护(protected)成员函数的,而且也是一个虚(virtual)函数的。

 

 

 

以下是一个页面code-behind的代码示例,其中利用了这个函数来对页面的输出内容进行过滤,经此处理后的内容才最终显示在浏览器中。

public partial class FilterDemo : System.Web.UI.Page
{
  HtmlTextWriter _oldWriter = null;
  StringWriter _stringWriter = new StringWriter();
 
  protected override HtmlTextWriter CreateHtmlTextWriter(TextWriter tw)
  {
    _oldWriter = base.CreateHtmlTextWriter(tw);
    return base.CreateHtmlTextWriter(_stringWriter);
  }
 
  protected override void Render(HtmlTextWriter writer)
  {
    base.Render(writer);
    string html = _stringWriter.ToString();
    html = html.Replace("REPLACE ME!", "IT WAS REPLACED!");
    _oldWriter.Write(html);
  }
}

在CreateHtmlTextWriter方法中,我们首先是调用基类的该函数来创建一个原来的HtmlTextWriter,然后将它暂时存放在一个成员变量中。

然后我们还是调用基类的函数来创建一个新的HtmlTextWriter,不过这个对象实例会使用我们自己的StringWrtier作为底层的TextWriter。被传入到Render函数中的HtmlTextWriter就是这个新创建的实例。(在Render函数中)我们首先对这个新的HtmlTextWriter实例调用基类的方法,然后将底层StringWriter的输出内容取出,这样就可以对该部分内容进行所需的处理了。我们最后将最终的输出内容写到原先的HtmlTextWriter中去,因为原先的这个HtmlTextWriter是真正负责将结果写到请求响应中去的。

使用这个技巧的时候有很多值得特别注意的地方。首先,如我先前所提到的,对于大型的页面,以上所做的这些事可能会大大地影响你网页的运行效率和可伸缩性。而且,我也没有针对输出缓存、异步页面等等的情况下测试过上面的技巧,所以你很可能会遇到意想不到的实际结果。

注意,如果你是需要从一个页面调用另一个页面,然后在第一个页面中得到后者的输出内容,那么你可以将你自己的TextWriter实例传到Server.Execute函数中并得到结果,所以这种情况下你无需借助上面所介绍的这个技巧。

posted on 2009-07-01 15:54:46 by demonfox  评论(0) 阅读(853)

 
2009年05月21日

【原文地址】ASP.NET MVC For Visual Studio 2010 Beta 1

【原文发表日期】 May 18, 2009

我本打算这个周末写这篇东西的,可是很抱歉那两天的天气实在太棒了,所以我就和我儿子在户外共度了大部分周末时光。

如果你还没听说的话,Visual Studio 2010 Beta 1已经发布了,注册了MSDN的朋友们都可以去下载。而Soma说在周三Beta 1也会向更广泛地向大众开放。

你可以在下载包里找到一份很精彩的介绍ASP 4新功能的白皮书。

你可能会注意到ASP.NET MVC并没有包含在Beta 1中。主要的原因是Beta 1在MVC 1.0发布之前已经内容锁定了(译注:lock down;微软内部指一个产品只修改bug不增加功能的阶段)。而VS10 Beta 2里会包含ASP.NET MVC。

当下,如果你试着在VS 2010 Beta 1中打开一个MVC项目的话,你会看到一些关于不支持该项目类型之类的错误信息。一个简单的解决方法是这个帖子里所介绍的通过移除ASP.NET MVC ProjectTypeGuid的方法。

我们正在努力设法完成一个编外的安装程序来在VS2010 Beta1环境下安装ASP.NET MVC的项目模版和工具,预计会在六月的某个时间通过CodePlex发布。所造成的不便,敬请见谅。我会在第一时间写博客通知大家的。

posted on 2009-05-21 15:17:31 by demonfox  评论(2) 阅读(2382)

 

【原文地址】Donut Hole Caching in ASP.NET MVC

【原文发表日期】 May 12, 2009

译注:原文的题目是Donut Hole Caching in ASP.NET MVC。Donut就是面包圈的意思,Donut Hole就是面包圈中心的那个洞洞。Donut Caching是指:在整个页面中缓存大部分的页面而对一小块要实时更新的内容不进行缓存。而Donut Hole Caching则是指相反的情况,亦即:不缓存大部分的页面而只缓存一小部分特定的内容。既然是仅缓存一部分的内容,我就译成局部缓存了。而Donut Caching似乎在很多地方都译为:“甜圈缓存”,我就沿用了

不久之前,我写了关于ASP.NET MVC中“甜圈缓存”的一些内容,也即,除了一小部分的信息,你需要缓存整个视图的大部分内容的情况。更技术化的用词也许应该是“缓存替换”(cache substitution),因为这里它用到了Response.WriteSubstitution这个方法,不过我觉得“甜圈缓存”确实是蛮形象的描述 -- 因为你需要缓存所有的东西,除了中间那一小部分内容。

不过,如果是反过来的情况应该怎么办呢?也就是说,如果你是想缓存中间那个窟窿,而不是周围那圈面包怎么办?

(我认为我们应该将所有软件工程的概念都用美味的食物来命名,你觉得如何?)

换句话说,假设你是想对视图中的一部分内容采用与其他所有内容不同的缓存策略(比如,不同的缓存有效时限),那该如何做呢?关于如何在ASP.NET MVC中实现这一点至今还没有很明确的介绍。

举例而言,Html.RenderPartial方法会忽略所有视图用户控件上的OutputCache指令。而另一方面,如果你使用MVC Futures包中Html.RenderAction这个方法来显示一个视图中内嵌的一个动作的输出内容时,你就可能会遇到这个问题:就是虽然只有这个动作有一个OutputCacheAttribute的属性,但实际上整个视图都被缓存了。

我今天对这个问题多了一些深入研究,发现当你给一个控件指定一个OutputCache的指令时(或者给一个页面),这个控件的输出缓存不是由它自己来控制的。相反,看起来是ASP.NET页面的编译系统参与了进来,接收了这个这个指令,并相应地做了缓存行为的处理。

用直白的话来说,这意味着下面我将展示的技巧只有在默认的WebFormViewEngine里才能工作,虽然我对于如何使之在所有的视图引擎(view engine)里工作也有些初始的想法。我只是想和ASP.NET产品组里的一些了解ASP.NET深层机制的成员再进一步交流一下以便确认实实在在准确的处理途径。

在使用默认的WebFormViewEngine的情况下,实现局部输出缓存其实还挺简单的。你只需通过直接通过声明(declaratively)往视图里加入一个ViewUserControl,然后将对RenderAction或RenderPartial的调用都放在这个ViewUserControl内部。如果你调用了RenderAction,那你还需要将相应动作的OutputCache属性去掉。

请记住ViewUserControl会继承他们所在的视图的ViewData。所以如果你使用了一个强类型的视图,你也必须在ViewUserControl的泛型类型参数中使用相同的类。

如果上一段东西你读得有点云山雾罩的话,那是时候来看一个实际的示例了。假设你如下的控制器动作:

public ActionResult Index() {
  var jokes = new[] { 
    new Joke {Title = "Two cannibals are eating a clown"},
    new Joke {Title = "One turns to the other and asks"},
    new Joke {Title = "Does this taste funny to you?"}
  };
 
  return View(jokes);
}

假设你是想在视图里显示一系列的笑话标题。通常,你会先创建一个强类型的视图,然后在那个视图内部,我遍历模型(model)中的数据并打印出各个笑话的标题。

现在,我们还是创建一个强类型的视图,但这个视图包含一个ViewUserControl,来代替原来我们写的遍历模型并打印的代码(请注意为了简洁起见,我删去了Inherits属性值里的那些命名空间)

<%@ Page Language="C#" Inherits="ViewPage<IEnumerable<Joke>>" %>
<%@ Register Src="~/Views/Home/Partial.ascx" TagPrefix="mvc" TagName="Partial" 
%>
<mvc:Partial runat="server" />

在这个控件(译注:即Partial.ascx)内部,我们将完成原来要在主视图中完成的工作,并且配置缓存设定。请注意这里我们的ViewUserControl的泛型类型和视图的类型是一致的:IEnumerable<Joke>。这使我们得以将原本在视图中的代码原封不动地移到这个控件中去。我们也同时在此处配置OutputCache指令。

<%@ Control Language="C#" Inherits="ViewUserControl<IEnumerable<Joke>>" %>
<%@ OutputCache Duration="10000" VaryByParam="none" %>
 
<ul>
<% foreach(var joke in Model) { %>
    <li><%= Html.Encode(joke.Title) %></li>
<% } %>
</ul>

现在,这部分的视图将会被缓存,而其余视图中的内容则不会。而在这个ViewUserControl内部,我们可以随意调用RenderPartial或者RenderAction。

请注意如果你想用这个技巧来缓存RenderPartial的输出结果,这不会给你带来太多的效益,除非显示这个局部视图本身(而非其中的数据)的代价很高。

这是因为输出内容的缓存要直到视图显示的阶段才会发生,如果准备该局部视图背后的数据需要很复杂的运算的话,那你实际上并没有节省多少工作,因为给这个局部视图提供数据的动作方法(action method)还是会在每次页面被请求时运行并且重新创建所需的数据。

在这种情况下,你需要手动缓存这个局部视图的数据,从而免去每次都必须重新创建它们的工作。有一个可以考虑的疯狂的想法是(先公开下想法而已)是允许将输出缓存的元数据(metadata)和一部分视图的数据关联起来。这样,你就可以只创建一小部分专属于那个局部视图的数据,然后这个局部视图就会自动在此之上进行输出缓存。

这个思路可以进一步的优化联合起来使用,也就是通过某些方法声明那一小部分专属于局部视图的数据只需在输出缓存过期(expire)后才需要被重新创建,如此我们就不必在每个请求响应中反复创建它们了。

而在使用RenderAction的情况下,你确实可以得到所有输出缓存的好处,因为如果你的ViewUserControl已经被缓存了的话,你所使用的这个内联的动作方法就不会再被调用了。

我这里编写了一个小小的程序来演示这些概念的实现,以免我上文的介绍不够明了。Enjoy!

posted on 2009-05-21 15:16:25 by demonfox  评论(0) 阅读(2218)

 
2009年05月14日

【原文地址】I’m a Web Developer At Heart

【原文发表日期】 May 7, 2009

曾经有一位年轻的程序员写email问我说如何能成为一个成功的开发人员。我一开始是这样回答的:

我不清楚.你为什么不去问一个成功的开发人员呢?

但而后我想,这样的回答其实仅仅是机巧有余,不是么?我这么老虚伪地故作谦逊是和谁在故弄玄虚呢?毕竟,“clever hack”这个概念就是以我来命名的(译注:注意Phil Haack的姓氏),而显然发明这个词汇的人还及不上我1/10的魅力,这点从他创造这个词组的时候故意地漏掉了一个字母a这件事上也更加可见一斑。当然,这个,还只是发生在我发明了Test-Driven Design,因特网,以及大家所呼吸的空气之前的一些小打小闹。

(对那些幽默理解不能的朋友们,请注意,我并没有真正发明Test-Drive Design)

于是我开始仔细考虑这个问题并对自己说:“假设我是一个成功的软件程序员,那我应该会做哪些事来达到那个目标呢?”然后当我开始思索各种学习提高的方法时,有一件事是显而易见的,那就是参与一些开源软件的项目。

如果说我的职业生涯中有一件事年复一年地使我获益良多,那就是我参与了很多开源的项目。参与开源项目使我有机会广泛地接触各类的问题和技术,而这些问题和技术在日常的工作中我通常不会面对。

在我进一步进行探讨前,我必须声明这个帖子不是我用来回答年轻的程序员们的问题的帖子。不,那样的帖子还是等其他的场合吧。而且我也许会起个陈词滥调又莫测高深的名字比如:“给年轻的开发者们的一些意见”。我的意思是,这样的题目是不是听上去真的既无聊又自大?我对着镜子严肃地说:“拜托你还是冷静点吧。”不过镜子里的那个家伙也许最终还是会这么来一篇的,没办法…

只是,这篇不是那样的帖子。相反,这篇与好为人师的话题很不相干,因为我很擅长一件事,那就是跑题。

在聊到关于开源软件的话题时,我很自然地想到了我参与的第一个开源项目 – RSS Bandit (w00t w00t!) RSS Bandit是一个由Dare ObasanjoTorsten Rendelmann开发的一流的RSS聚合软件。我那时候才刚刚开始接触博客之类的概念,然后一下子就被Dare的直爽而又有深度的博客以及他的可爱的孩子,RSS Bandit(他现在有一个真正的孩子了,祝贺你,老兄)吸引住了。

那时候我还没怎么做过Windows客户端的程序开发。我主要是用老版本的ASP以及早期的ASP.NET在开发网络应用。我于是想通过RSS Bandit来磨练下自己并顺便学习一下Winform的开发。Winform这种状态持续化(stateful)的编程模型让我觉得很新鲜(译注:因为那时基于HTTP的网络应用基本都是stateless的,当然后来有了ViewState等等的技术)。这将是很有趣的一个尝试。

很多新人程序员接触一个开源项目时都梦想着自己很立马开发出引人注目令人惊奇的新功能,由此博得群众的欢呼喝彩,总统因此以你来命名一个国定假日,而且你所有的敌人都立刻自惭形秽并把他们的孩子改名跟你姓了。

但一个真正好的贡献者会收起他/她的骄傲感然后扎扎实实地从一些小事,甚至是琐事开始做起。比如很多开源项目都很需要很好的帮助文档,一部分原因也是因为最吸引眼球的是开发那些新的功能于是没人有兴趣来写那些个劳什子的文档了。

我就是这么开始的。我先开始写了一篇文章:getting started with RSS Bandit.  Dare注意到了,于是问我愿不愿意参与完善文档的建设,我欣然同意了。他给了我提交的权限(我想我应该是Dare和Torsten后第三个有提交权限的人),于是我很努力地编写各式的文档。事实上,很多我当年写的内容仍然在那里,比如这个我当年用过的巨自恋的程序截图。; )

慢慢地,我得到了越来越多的信任,并被允许做一些bug的修正和一些小的功能块。我负责的第一个主要的功能是实现可配置的键盘快捷键,还挺不错。

小小逸事一则。我和这两位在RSS Bandit上合作了多年,但却从没有亲自面会过Dare一直到刚刚在Las Vegas举行的今年度的Mix大会上。真的!而我早先在德国于Torsten见过面。

(译注:我和Phil不同,两年前加入微软的时候,我就和Dare有过几面之缘,也和他的group合作过不短的时间。不过我一直都没有意识到他就是我用过的第一个聚合阅读器的作者,直到看到Phil的这篇文章,呵呵)

我那时真的很喜欢RSS Bandit方面的工作,那几乎成了我的一个爱好,占去了我不多的业余时间里的剩余空闲。我想你可以说RSS Bandit的工作使我免受了洛杉矶街头流氓团伙的不良影响,当然我也没试过去加入那些团伙,而估计他们也不会要我。不过渐渐地,我意识到了一些事。尽管起初的那种学习了解状态持续化编程模型的兴奋感犹在眼前……

我意识到我并不喜欢这种模型。

事实上,我发现这个模式很陌生也很难掌握。我总是遇到一些奇怪的使我脑筋打结的怪问题,比如用户单击了一个按钮后,此按钮仍然保留了它之前的状态。那时我就会想,“为什么我需要手动清除按钮的状态呢?为什么在用户进行一个动作之后这个状态不自行消失呢?”我开始意识到我的问题在于我的思维一直还是遁寻着网络应用程序员的模式,而不是客户端应用程序员的模式。

就与一个客户端程序开发者转向网络程序开发时感觉相似(比如网络程序中,因为状态不是持续化(stateless)的,所以你必须在响应每个请求后都重设所有控件的状态),一个此前专注于网络程序的开发者会发现客户端程序的开发是一件很费脑筋的事,因为所有的系统状态都像那个酒吧里最漂亮的小妞身边的那个跟屁虫一样 ---- 他就是赖在那里不从你眼前消失。

于是我才意识到,从骨子里来说,我其实是一个网络应用程序员并且我情愿Make web, not war译注:这个我实在不想翻译,译了也没意思,呵呵,太搞了,你自己看video吧)。所以大概就是在那个时候,我开始了Subtext项目,因为我内心里还是更希望做一个网络的应用。最终,我不再使用RSS Bandit,而是转向了在线的聚合阅读工具,就是Google Reader(有点讽刺,呵呵),而其中最主要的原因,就是在线的阅读工具使我可以随时随地看到我订阅的内容,并且一直保持最近更新的状态,而我也不需要在每一台新的电脑上进行同步或者安装一个程序。

所以说我虽然更喜欢(或者说也许是更习惯于)网络应用的状态非持续化的编程模式,我同时也为网络应用本身的状态持续化的特性所吸引,也即,我所拥有的数据的状态不是绑定在任何一台特定的终端上的而是存储在一个无所不在的网络平台上,而我又可以随时随地地使用这个平台(当然,网络应用也有它自身的问题和课题,比如网络服务当机的问题)

与此同时,我也会不时地抽空关心一下RSS Bandit的最新进展。它确实也有很多Google Reader所没有的很酷的功能,比如它可以从聚合器客户端直接通过Comment API来发表评论,还有它可以订阅需要身份验证的聚合。而且我觉得Dare正在努力把RSS Bandit引向一个全新的更有竞争力的方向

所有我说的这些其实只是想说明,如果你想成为一个更好的程序员,那就找一个你感兴趣的开源项目,然后参与进去(比如这个,:) ,因为也许它就会引导你发现自己的本质是何种类型的开发者。就如我所最终了然的,我从内心深处是一个网络应用的程序员。

posted on 2009-05-14 16:47:00 by demonfox  评论(0) 阅读(2783)

 
2009年05月08日

【原文地址】Put Your Pages and Views on Lockdown

【原文发表日期】 May 5, 2009

我相信你一定了解,我们程序开发人员是一群老顽固的人而且我们就喜欢周遭的东西和我们理想中的情况保持一致。不然你怎么解释那经年不停众说纷纭的关于大括号应该放在哪个位置的讨论?

所以我们应该也不会惊讶于开发人员对那些aspx文件里面(以及后台)的内容的锱铢必较,无论是对那些Web Forms的网页还是对ASP.NET MVC里的视图。

举例说,有些程序员坚持一个网页里不应该包含服务器端的脚本程序段落,而另一些则认为MVC的视图中不应该含有任何Web Form的控件。那如果你可以事先规定你的视图将拒绝任何带有控件实例的代码段,那不是很棒么?

幸运的是,ASP.NET里提供了大量的不为大众所知的可扩展组件来帮助你实现这样的功能,比如PageParseFilter这个类。MSDN是这样描述它的:

Provides an abstract base class for a page parser filter that is used by the ASP.NET parser to determine whether an item is allowed in the page at parse time.

也就是说,通过实现这个类,你可以在页面分析器分析.aspx文件的时候有机会插入你自定义的处理逻辑。

比如,下面是一个很简单的滤子类,它屏蔽了所有带有runat=”server”属性的脚本代码段:

using System;
using System.Web.UI;
 
public class MyPageParserFilter : PageParserFilter {
  public override bool ProcessCodeConstruct(CodeConstructType codeType
    , string code) {
    if (codeType == CodeConstructType.ScriptTag) {
      throw new InvalidOperationException("Say NO to server script blocks!");
    }
    return base.ProcessCodeConstruct(codeType, code);
  }
 
  public override bool AllowCode {
    get {
      return true;
    }
  }
 
  public override bool AllowControl(Type controlType, ControlBuilder builder)   {
    return true;
  }
 
  public override bool AllowBaseType(Type baseType) {
    return true;
  }
 
  public override bool AllowServerSideInclude(string includeVirtualPath) {
    return true;
  }
 
  public override bool AllowVirtualReference(string referenceVirtualPath
    , VirtualReferenceType referenceType) {
    return true;
  }
 
  public override int NumberOfControlsAllowed {
    get {
      return -1;
    }
  }
 
  public override int NumberOfDirectDependenciesAllowed {
    get {
      return -1;
    }
  }
}

请注意我们必须重置一些我们并不感兴趣的属性的默认值,比如NumberOfControlsAllowed,否则这些属性值返回将是默认的值“1”,这当然不是我们想要的。

如果想应用这个滤子,你只需在web.config文件的<pages />标签里加上如下声明即可:

<pages 
  pageParserFilterType="Namespace.MyPageParserFilter, AssemblyName">

要想在ASP.NET MVC的视图上应用分析滤子则更麻烦一些,因为MVC的视图都已经有一个分析滤子应用其上了:ViewTypeParserFilter。我以前提到,在使用泛型的模式(model)类的时候,我们可以免去在视图中用到code-behind的烦恼 (还记得我上文提到的那些开发者么?他们就是不喜欢在视图类中用到code-behind。),而提供如此灵活性的背后是很多如黑巫术般的诡异工作,这个滤子类就是这些工作的一部分。

假定我们希望防止开发者使用在ASP.NET MVC框架中毫无意义的那些服务器端控件。理想化的情况是,我们就继承一下ViewTypeParserFilter类,然后加入我们想定义的逻辑,这样原来的ViewTypeParserFilter的那些功能我们也保留了。

但问题是这个滤子类是internal的,我们无法继承。幸运的是,我们可以找到这个类的ASP.NET MVC源代码,重命名一下它的类型和命名空间,然后就按我们的需要来修改好了。完成了以后,我们还可以和其他人分享这些改动。这就是ASP.NET MVC开源协议的好处之一。

警告:ViewTypeParserFilter的存在是ASP.NET MVC这个框架实现中的一个内部细节。未来我们最理想的目标应该是不必通过这个滤子类,我们也可以提供优美的泛型语法。所以我下面马上要介绍的东西也许在未来就作废了,所以你自己得承担起未来维护的责任。It’s definitely running with scissors (译注:这就是翻译所不能的地方了,“Running with Scissors”是一部美国的电影,多译为“夹缝求生”。也是ALT.NET的徽标上的也有一个“带着剪刀奔跑”的图形暗喻,意指程序员所应具备的灵活性和处理不确定性的能力。我还是不强行翻译好了,做个注解就是。)

在我的演示程序中,我将下列文件拷贝到了自己的项目中:

  • ViewTypeParserFilter
  • ViewTypeControlBuilder
  • ViewPageControlBuilder
  • ViewUserControlControlBuilder

然后我定义了一个新的分析器滤子,它继承自ViewTypeParserFilter并重载了AllowControl这个方法,如下:

public override bool AllowControl(Type controlType, ControlBuilder builder) {
  return (controlType == typeof(HtmlHead) 
    || controlType == typeof(HtmlTitle)
    || controlType == typeof(ContentPlaceHolder)
    || controlType == typeof(Content)
    || controlType == typeof(HtmlLink));
}

除了那些典型的视图中必须要用到的几个控件外,这个新的滤子会阻止开发者加入任何其他的控件。当然,也很容易想到接下来我们可以提供一些简单的方法来允许开发者配置这个可用控件列表。

实现完这个新的滤子类后,我们可以修改Views文件夹下的Web.config文件来指定新的分析器滤子。

上文介绍的是允许开发者往网页分析流程中插入自定义逻辑的一个强大的方法,所以请大家谨慎使用。如你所愿的,我这里有一个很简单演示程序可供参考。

posted on 2009-05-08 17:09:27 by demonfox  评论(0) 阅读(2781)

 
2009年05月03日

译注:本篇为09年3月的补全

【原文地址】I’m Speaking At Mix 2009

【原文发表日期】 Mar 1, 2009

终于把注册登记的事情搞定了,我正式准备出席今年的Mix 09喽! Woohoo! 而且我不仅仅是参加本次大会,我还将第一次在Mix上做主题演讲,所以如果各位朋友也准备参加的话,届时请一定过来寒暄几句。

我以前也提过,Mix是我最喜爱的微软举办的大会之一。Jeff Atwood概括得好:

“参加过'06和'07年的MIX后,它就成为了我最锺意的微软技术会议…

我喜欢Mix是因为…

- Mix的规模相对较小而有亲和力,一般出席的人数在2,000人左右

- 无缝地整合了软件工程和设计方面的内容

- 汇集了很多非微软的人士,甚至那些传统上对微软有敌意的人,所以你可以听到各方面的意见

我参加了Mix创建以来的每一届大会:

- Mix 06 第一届Mix大会,Atwood, Galloway, 和我的处女行

- Mix 07 我遇到了Miguel,见证了Moonlight的横空出世,然后决定加入微软

- Mix 08 第一次有了关于ASP.NET MVC的专题演讲,由Scott Hanselman主讲

- Mix 09 让我们拭目以待

今年的Mix上我将主讲以下两个专题:

MIX09-T50F ASP.NET MVC: America’s Next Top Model View Controller Framework(译注:这里其实是一个双关幽默,取义于美国的一个蛮收欢迎的电视真人秀:America’s Next Top Model,当然两个Model的意义不同,后者是模特的意思)

介绍如何创建一个简单的ASP.NET MVC的应用程序,并以此演示该框架的一些关键特性。同时,你可以了解到如果利用一些新的很酷的工具来提高开发效率。

MIX09-T44F Microsoft ASP.NET Model View Controller (MVC): Ninjia on Fire Black Belt Tips

介绍一些实用的技巧和窍门,使你能最充分地利用ASP.NET MVC框架

第一个讲座是概括性的介绍,第二个则允许我更深入地进行一些讨论。

我最近一直努力地在准备一些实例演示,所以希望到时候能给大家看一些十分有趣的东西。无论如何,如果你打算参加本次大会,那请给我留个言,过来聊几句,互相问个好。

同时,如果你对某些内容特别感兴趣,也可以事先告诉我。这将会是一次很令人期待的盛会。

posted on 2009-05-03 18:31:55 by demonfox  评论(0) 阅读(2833)

 
2009年05月01日

说明:我决定从今天起优先翻译Phil最新的帖子以配合他的进度,而滞后的09年3月1日到4月22日间的帖子会尽快按时间由旧到新的次序补齐。

 

【原文地址】ASP.NET MVC NerdDinner Walkthrough

【原文发表日期】 Apr 29, 2009

等待终于有了结果,我和Scott Hanselman, Rob Conery, Scott Guthrie一起合作的这本书终于在Amazon.com上架了

为了纪念本书的顺利发行,两位Scott同学协力将该书的第一章从免费的PDF电子书的格式转换成了一系列的HTML文章

这是很精彩的一整个系列的文章,其中详细介绍了NerdDinner网站的构建。从中你可以了解到大部分ASP.NET MVC的日常使用中所会接触到的方方面面,从而对这个框架的各个组成部分如何协同工作会有一个很好的初始理解。

这本书的其余部分是提供给那些希望对这个框架的细节进行进一步钻研的朋友们的。在书中,我们尝试着在各处插入一些ASP.NET MVC产品组的工作花絮和记录,这些小豆腐块的风格很接近于《框架设计指南》(Framework Design Guidelines)这本书里的那些注记。如果你想找几个不购买这本书的理由,那可以参考一下Rob的帖子

唯一的坏消息是尽管我们竭力地威逼利诱哀求恳请,我们最终无法说服出版社的编辑们发行一本印有着我们白金拉长大额头玉照封面的本书特别纪念版。我完全相信我们可以为这本特别纪念版多要点价从而好好地发笔财。不过现在我也就只能把这特别版的封面贴这里,你们自己看好了。点击图片可以放大。

posted on 2009-05-01 15:50:38 by demonfox  评论(0) 阅读(2875)

 

【原文地址】ALT.NET Seattle Day Three

【原文发表日期】 Mar 01, 2009

第三天也就是ALT.NET西雅图大会的最后一天对我来说是挺短的。我可怜的及其有耐性的太太这天觉得身体不适所以我只能在午饭时分匆匆告辞。不过离开之前,我有机会参加了John LamJimmy Schementi主持的一个精彩的讨论,是关于“在.NET程序中加入脚本支持”的内容。你可以在Kyte.tv上收看本场讨论的视频

John和Jimmy介绍了如何利用IronRuby来给终端用户提供应用程序脚本编写的功能。这方面典型的例子自然是许多3-D游戏,比如Half-Life,一般都是用C++来编写核心的3-D引擎的。然而,他们通常会提供一种脚本语言比如LUA之类的来编辑游戏中各种物体的行为等等,这么做主要的原因是这方面的内容(物体的行为,场景动画的设置等等)的可变性很强,所以你需要一种比较轻量级的语言来提供灵活性。

同样的道理也适用于这样的情况:你使用C#编写了某个企业级应用程序的主要逻辑,但同时,你也希望通过IronRuby这样的语言来动态配置后台的规则引擎。

赶到讨论现场时我已经迟到了。我问了John和Jimmy是否准备了什么示例演示。可惜他们并没有所准备,所以我给大家快速地演示了一个提供了IronRuby脚本编辑支持的ASP.NET MVC程序,我觉得同样的思路应该对不少C#开发者也有启发意义。这其实只是我在大量的空余时间里所做的一个小东西,我希望能在MVP峰会和Mix中给大家现场演示一下。现在我还不想在我的博客上讨论它,因为我还有一些东西想进一步完善。

在这场讨论之前,Aaron Jensen给我看了他用Spark View EngineASP.NET MVC做的一些很酷的东西。讨论结束后,Eric Hexter又向我介绍了他的公司用T4模版和ASP.NET MVC做的一些精彩的内容。这些真的给了我很多的灵感,我对在下一版的ASP.NET MVC中如何支持这些新的尝试有了很多主意。

本次大会上最酷的一件事之一就是我们利用了Kyte.tv.  事实上,在本周前我还从来没听说过这个新鲜玩意儿,不过好像到场的每个人都在用Kyte.tv录制现场的讨论会。早早回家后,我趁我太太和孩子小憩的时候又重新上网收看了Scott Hanselman录制的几个小组讨论。很酷吧?

posted on 2009-05-01 15:50:09 by demonfox  评论(0) 阅读(2549)

 

【原文地址】ALT.NET Seattle Day Two

【原文发表日期】 Mar 01, 2009

ALT.NET第二天的议程顺利结束了,可累坏我了(DemonFox: 这里的原文很有趣:I’m already pooped (for you non-English speakers, that means tired, not something else that might come to mind)  呵呵,因为在英语俚语里,poop的一个释义就是“便便”,: D)。

首先再次鸣谢,Brad Wilson,以下的照片都是由我们这位记者提供的。如果想进一步了解一下会中的小组讨论到底有多么精彩纷呈,Brad的相册上有更多的现场照片。

我参加的第一个小组讨论的话题是关于如何在.NET社区里鼓励开源项目的发展(见上图),参与讨论的各位自然是天南地北无所不提。很多人认为整个业界现在越来越多滴转向开源模式的软件开发,因此那些懂得将开源模式引为己用的业者将会比其他人更有竞争力。

讨论中所提及的一个有趣的话题是关于如何开展更多的开源项目方面的知识普及。比如,了解各类开源协议对很多人而言是一件挺麻烦的事。如果能有一些简单的工具,比如协议互相间的兼容性列表或一个协议选择器(也就是知识共享协议生成器这样的工具)应该会挺有用的。

其实我个人以前也尽我所知地给读者介绍过我对软件授权协议的一些粗浅的了解

当天晚些时候的关于测试驱动开发(Test-Driven-Development)的小组讨论中,有人提到了另一个有趣的现象,就是很多开发理念或方法,如果得不到微软的认可或支持的话,通常就很难有足够的影响力以至于就好像根本不存在一样。

我参加的下一个小组讨论是关于“基于Mac, Linux, 和iPhone的.NET/Mono框架”,主持人是总是很风趣的Miguel De Icaza和Joseph Hill. 我可以确定基本上所有人都参加了这个小组讨论,因为显然大家都想在iPhone用C#写个模拟放屁声的的软件然后靠这个每天赚个$10,000来块钱

当日晚些时候,Karen Liu (她是托管语言和集成开发环境项目组的Program Manager),Euan Garden(他是Visual Studio测试组的Program Manager),还有我(见上图)一起主持了关于测试驱动开发与微软的小组讨论,其间我们介绍了在微软程序员部门,为了改进编写单元测试的效率和习惯,我们所作的一系列工作,比如ASP.NET MVCWPF的Model-View-ViewModel,Visual Studio的一些改进,Silverlight, 等等。

这些努力的重点都在于如何使我们的工具和开发框架更好地服务于所有编写自动化测试的程序员。不过使用测试驱动开发模式的程序员通常都有很高的要求和期待,所以在尽力满足这些要求和期待的过程中,我们觉得所有的开发人员都从中获益了。

我展示了一些幻灯片,介绍了我们交流和合作的用户群,以及在下一波产品中将会出现的各种最新的改进。

Karen Liu在现场演示了Visual Studio 2010中我们是如何为测试优先的开发者提供更好的工作流程的支持。Euan Garden则主持了关于Visual Studio单元测试框架的讨论。

我们一起展望了Visual Studio中单元测试支持的前景。有不少人都提到他们希望看到Visual Studio能集成xUnit.NET这样的工具,就如ASP.NET MVC中集成了jQuery一样;个中原因,正如我上文所提到的,在他们的工作环境里,如果这些工具不被Visual Studio所支持,那它们就好像不存在一样。就我所听见的情况,这似乎是一个共同的呼声,就是当大家想在自己的工作范围内推广一个开发工具而微软又没有替代品的话,如果没有微软的开发环境提供集成支持,那周遭的人接受起来就会相对困难很多。

有一位与会者事后向我提起说他从没有用过jQuery(也不经常使用JavaScript),直到ASP.NET MVC集成了这个库。而现在,他很满意在ASP.NET MVC中使用jQuery的感觉。

对我来说,这是一个很好的例证,就是如果我们能在产品中聪明地应用各类开源资源,那将会使我们的客户更加满意。

posted on 2009-05-01 15:49:53 by demonfox  评论(0) 阅读(2243)

 

【原文地址】ALT.NET Seattle Day One

【原文发表日期】 Feb 27, 2009

ALT.NET西雅图大会的第一天顺利结束了,我现在很期待明天的各项小组讨论。

作为一个以Open Spaces的理念来组织的会议,于会的参加者,我们,首要的任务便是制定大会接下来的日程安排。上面这张照片里(Brad Wilson摄影),你看到的是Scott Hanselman正在提议一个讨论的话题,这也是我最喜欢的会议照片之一(DemonFox: 是因为Scott的眼神巨呆滞??^_^)。整个过程用了大约两个小时,然后我们一大群书呆子一起去Red Robin吃了晚饭。

 

这次是我第二次参与ALT.NET Open Spaces的会议,我个人很喜欢这种形式的会议里提倡的若干原则:

- 来者是客,来参加的都是应该来参加的。

- 会上所发生的任何事就是唯一可能发生的事

- 无论何时开始都是最适当的时间

- 当会议结束时,就是它该结束的时候

从某些角度来说,这让我想起了BurningMan的十大准则,特别是以下两条:

最大限度的包容 (Radical Inclusion)

任何人都可以成为BurningMan(译注:BurningMan是美国的一个户外团体生存活动,所以若是直译为“燃烧的人”就没有意思了)的一份子。我们欢迎并尊敬陌生人。参与我们的社团没有任何先决条件。

参与 (Participation)

我们的社团专注于一种最大限度的参与精神。我们相信改造性的变化,无论对个人也好对社会也好,只有通过个人深入地参与其中才可能发生。切实的行动,才能改变自我。我们邀请每个人都来工作,每个人都来游戏。我们通过行动打开心扉而使这个世界变得真实(DemonFox: 好煽情的说,呵呵)。

这次的会议我们也没有严格意义上地区分听众演讲者。每个人都可以是听众同时也是演讲者,因为通常,每个人都会多少有些有趣的东西可以和别人分享,并互相教授和学习。

我很喜欢这次的会议的另一个原因是我能因此有机会见到很多熟悉的面孔以及与世界各地那些我素未谋面的合作者们相会。比如,Steve Harman,还有,我终于有机会和Simone Chiaretta本人见面,也就是Subtext背后的第三个火枪手(DemonFox:如果熟悉大仲马先生的《三个火枪手》的朋友应该能懂这个比喻,: ))。 从意大利远道赶来已经30多个小时没合眼了的Simone显然已经耗尽了能量,连睁着眼拍张照的力气都没了。

我期待着明天更精彩的内容。

posted on 2009-05-01 15:49:40 by demonfox  评论(0) 阅读(2318)

 
【第1页/共4页,39条】
首页
前页
1

Powered by: Joycode.MVC引擎 0.5.1.0