RSS 2.0 Feed

Thursday, April 24, 2008

原文地址:Defining ASP.NET MVC Routes and Views in IronRuby

 

过去的一篇文章中我写了一些关于使用DSL代替XML配置文件的想法。我还在monkey patching CLR objects using IronRuby文章研究了一下下它们如何协同工作。

那些文章是为了我能使用IronRuby定义Asp.net mvc的Routes做准备的。在下面的下载文件里包含了一个不完整的IronRuby视图引擎。我还没有完全做好。

IronRubyMvcDemo.zip Download (4.93 MB)

这些工作在最新的asp.net mvc代码里。

使用Ruby来写routes,需要在你的应用中引用IronRubuMvc库和导入IronRubyMvcLibrary.Routing命名空间在你的Global.asax的代码文件里。从那里,你能调用一个扩展方法在RouteCollection里,像这样

public class GlobalApplication : System.Web.HttpApplication
{
  protected void Application_Start()
  {
    RouteTable.Routes.LoadFromRuby();
  }
}

它将在web根目录里寻找一个Routes.rb的文件,并使用文件里的内容装载routes.下面是我的定义:

$routes.map "products/{action}/{id}"
  , {:controller => 'products', :action => 'categories', :id => ''}
$routes.map "{controller}/{action}/{id}", {:id => ''}
$routes.map "{controller}", {:action => 'index'}, {:controller => '[^\.]*'}
$routes.map "default.aspx", {:controller => 'home', :action => 'index'}

就是这些,我尝试使用tab来格式行的内容,这样他们看起来像个数据表格,而不是简单的代码定义。

在上面的下载文件中是一个使用IroRubyViewEngine的web应用例子。你可以看到我是如何应用Monkey Patching来引用视图数据cleaner.在按一个IronRuby内部,你可以访问到视图数据使用一个全局的变量,$model。这是很好的一件事,不管你通过强类型数据还是不用,你总可以引用视图数据使用$model.property_name.

这时候视图数据是一个视图数据字典,你可以使用类型名作为关键字来查找这个字典。

如果你想理解和修改这些代码,注意检查单元测试,它覆盖了我的95%的代码。下一步,IronRuby控制器...

 

posted @ | Feedback (0) |

Sunday, April 20, 2008

[  原文地址:]Dynamic Language DSL vs Xml Configuration

申明:仅代表个人观点,非其他人的,非官方的。我不应该说这些,但是历史告诉我,我应该说。P.S.我并不是一个DSLs和动态语言的专家;)

这个星期,我参加了一个John Lam关于IronRuby的访谈,他亮出了Uncle Ben的名句“能力越大,责任越大”。当然,他指的是动态语言像Ruby的力量。

我被他另外一句话吸引了。他说如果他阅读使用metaprogramming技术写的ruby 代码几小时,他的脑袋会乱成一团。要理解在meta以及meta-meta层次上写的代码来运行时操纵并重写代码,需要花费很大的精力。也许这就是为什么c#将在近期继续是主要语言,而我尽力让我的大脑在更高层次运作。;)

然而,我认为他指的代码类型是用于实行DSL自身的代码。一旦写了一个DSL,位于那个DSL代码在它之上的代码必须是可读的。在它成为主要语言之前,我已经开始使用IronRuby。我能够看到我自己时不时的创建并使用mini-DSLs作为配置的替代品。

AHhh...配置。有时候我觉的这是一个误称。至少在java和.net社区中将配置运用与实践上时是的。从我们将什么东西都塞进xml配置时就有了这种趋势。

所以人们经常要求我们向那些我认为应该与单元测试一起被设置在代码中的配置特性提供XML。我们已经把XML变成一个程序语言,而且是一个蹩脚的。Ayende 谈论一个issue,在一个工具下清除大量的XML配置。这不是一个棘手的问题,但它吐出了一个事实,XML是代码,但这个代码的外在胜于内涵。要理解我说的外表和内涵强看 Ending Legacy Code In Our Lifetime.

用asp.net mvc 项目时,我们使用了代码第一,配置第二的方法。你可以从我们的URL Routing中看到这一点。你在代码中第一路径,而我们也许在将来的版本中提供配置的方法。

用这个方法,你可以为你的路径定义写单位测试,这是一件好事!Routes将URL转变成一个方法的形式,你为什么不想为它写测试呢?

我写这个文章的原因是,最近我一直在用IronRuby,想写一些在自己的时间里做的一些有趣的事情。这个帖子告诉了大家我为什么要研究IronRuby,除了它很有趣,以及贯穿Hack的研究精神。

posted @ | Feedback (0) |

[  原文地址:]ASP.NET MVC Preview of a Preview

更新:只是为了证明这是一个预览版的预览版,我们在预建VSI的下载时出现了一个签名问题。你如果试着从源代码开始构建,将会碰上问题。为此我们致以歉意,即是它是一个比较粗糙的预览版,我们确实想把它做好,这样你们就可以用这些代码了。所以你遇到了那个问题,请务必重新下载VSI.

大家都知道,微软对命名非RTM(Release to Manufacturing)版本更为拿手。我们有例如CTP,Preview,Alpha,Beta,RC(Release Candidate)等等的术语。另一方面,微软至少已经尽力向RTM发展,而不是一直将产品保持在Beta测试期中。

用asp.net mvc,我们需要添加另外一个版本的类型。现在我一直把它叫做CodePlex Source Release,意味着单纯的分享在进程中的源代码。有一天,ScottGu在我的办公室里把他叫做“预览版的预览版(Preview of a Preview)”,这个名字把我吸引住了。这确实是一个即将来临的预览版的预览版。;)

说起ScottGu,他在他的博客里填了一篇这一版本的具体描述,我推荐大家看一下,因为他细致的描述了大部分的修改。

对这个最近发行的代码,我尤其高兴的一点 我们发行了单元测试。正如Scott提到的,我们使用MoQ作为我们测试的模拟框架。请注意这不是一个官方确定的特定的模拟框架。起初我们想把测试放到Rhino Mocks(我曾经写了很多关于他们的文章)中。MoQ正好有一个与我们内部使用的模拟框架相似的程序模式,所以我们转向了MoQ。

之后,我会再写一些关于这个版本的文章。但是现在,我将留给一个 更新 Northwind的demo,它是以这个版本为基础的。

posted @ | Feedback (0) |

Monday, April 14, 2008

这篇就不翻译了,原文献上

If ever someone was undeserving of having others spend their valuable time translating his blog, it would be me. But hey, some people from the http://blog.joycode.com/ site went ahead and did it anyway. I must admit that I’m very flattered that anyone would put the effort in.

Before this, I learned that Subtext powers MySpace China's blogs, and now my blog is translated to Chinese. As David Hasselhoff says, “I’m big in China”. (To my Chinese audience, that is a joke. I am quite small.)

posted @ | Feedback (1) |

原文地址:Upcoming Changes In Routing

纠正了一些我们刚发现的小错误。预览代码是不是很有趣?

我们已经做了一些修改让routing更加有力和有用,但就像Ben叔叔说的,能力越大责任越大(?好像是周星星说的吧?^_^)。我首先会列出修改的内容,然后讨论一下修改的含义。

  • Routes不再视点符号“.”为分隔符。当前,routes视.和/号为特殊符号。他们是分隔符号。在这次修改后只把/号作为分隔符号了。
  • Routes在一个部分中可以有多个(不相邻)url 参数。当前,URL 参数在一个route中在分隔符间必须填满空间,比如:{param1}/{param2}.{param3}。在修改之后,一个URL部分可以有一个以上的参数,只要它们是有符号分开的,比如:{param1}.{ext}/{param3}-{param4}

通过带"."号的参数值

这次修改,点号成了另外一个意思。它不再是“特殊”的了。比如,你建了一个网站,能提供其他网站的信息。你可能想支持像下面这样连接:

  • http://site-info.example.com/site/www.haacked.com/rss
  • http://site-info.example.com/site/www.haacked.com/stats

    第一条URL将显示关于www.haacked.com Rss种子信息,而第二条URL将显示网站的统计信息。为了这些,你可能需要定义下面的route。

    routes.Add(new Route("site/{domain}/{action}" 
      , new MvcRouteHandler()) 
    { 
      Defaults=new RouteValueDictionary(new {controller="site"})  
    });
    这个routes有下面的controller和action方法。
    public class SiteController : Controller
    {
      public void Rss(string domain)
      {
        RssData rss = GetRssData(domain);
        RenderView("Rss", rss);
      }
    
      public void Stats(string domain)
      {
        SiteStatistics stats = GetSiteStatistics(domain);
        RenderView("Stats", stats);
      }
    }
    这里的基本思路是我们的域(这里例子里的www.haacked.com)将得到action方法的域参数。这里的问题是,它不能运行在以前的routing系统中 ,因为老的routing认为点号是分隔符。你需要这样site/{sub}.{domain}.{toplevel}/{action}定义routes的urls,但这不能工作有两个子域或者没有子域的情况下。

    我们不再视点号为特殊符号,以上的情况就能成为可能了。

    多个URL部分

    怎么样添加多个URL部分?它仍旧允许使用和做扩展的URLs的routing。比如,假如 你想route一个请求给action方法:

    public void List(string category, string format)

    旧的和新的routing,你都可以匹配这个请求为下面的URL...

    /products/list/beverages.xml

    使用下面的route

    {controller}/{action}/{category}.{format}

    去执行那个action方法。但是,假如 你不想使用文件扩展名,而仍旧想指定format使用一个专门的路径。使用新的Routing,你可以使用任何的字符作为分隔符,比如,可能你想使用“-”符号作为分隔符。你可以匹配下面的URL

    /products/list/beverages-xml

    使用下面的route

    {controller}/{action}/{category}-{format}

    这样仍旧可以执行action方法。

    注意 我们现在允许任何字符成为分隔符。因此,如果你真的想,虽然不知道你为什么要那么做,你可以使用BLAH去分隔fromat你可以匹配下面的route

    /products/list/beveragesBLAHxml

    使用route

    {controller}/{action}/{category}BLAH{format}

    它仍旧会route到相同的方法上。

    Consequences

    这使的routing更加强大,但也会有些后果,你必须知道的。

    比如:使用默认的在asp.net mvc预览第二版项目模板定义的routes,一个请求“/Default.aspx”将会失败,因为它不能发现controller使用名字“Default.aspx”。Huh?“/Default.aspx”现在必须匹配route {controller}/{action}/{id},因为我们不能视点号为特殊字符了。

    不仅如此,对/images/jpegs/foo.jpg?请求会是怎样?routing是不是会试着路由到controller="images",action="jpegs",id="foo.jpg"?

    我们做出决定,在默认情况下,routing不允许文件在本地磁盘上。现在routing在试图route前将会检查文件是否在磁盘上(通过虚拟路径提供者)。

    如果文件在磁盘上,我们将弹出和不会route,并让web server作为正常请求处理。如果文件不存在,我们会试图运行routing.这样可以确保我们不能循环的请求磁盘上的静态资源。当然,这些默认的设置是可以改变的,通过设置RouteTable.Routes.RouteExistingFiles=true.

    为什么现在写blog为这些?

    Dynamic Data工作组赢了让MVC组修改了routing。:) 他们发布了一个最新的Dynamic Data预览版包含了最新的routing dll.

    查看ScottGu’s post on the subject.我真的感觉Dynamic Data是asp.net工作组中最被低估的新技术。当你深入研究,这真是非常cool."scaffolding"只是冰山一角。

    安装Dynamic Data预览版需要将routing assembly安装进GAC。如果你安装了这个,它可能破坏已经存在MVC预览第二版的站点,因为assembly装载器在assembly版本相同的情况下会优先装载GAC里的版本。而新routing assembly和mvc预览第二版里的版本号是相同的。

    Dynamic Data预览版里的readme已经写了如何更新你的mvc 预览第二版的项目,使它在新的routing里能正常工作。你会注意到readme里推荐将在根目录里default.aspx文件重定位到 /Home.技术上,在根目录里的Default.aspx文件没有必要根据routing的变化做改变。不幸的是,Cassini不能正常的工作,当你为“/“做请求而不在默认的文档。他不能运行任何asp.net modules.因此我们将文件仍旧保存在根目录,但你可能将能移除它当你部署在IIS 7.0中时。因此,我要重申这一点上,在项目根目录里的Default.aspx要确保Cassini工作正确的,在将来不需要IIS7,但现在是需要的。

    我们将有一个新的mvc源代码版本在CodePlex发布,在未来的两三个星期里,它将支持新的routing 引擎。

    www.haacked.com Rss种子信息,而第二条URL将显示网站的统计信息。为了这些,你可能需要定义下面的route。
  • posted @ | Feedback (0) |

    Sunday, April 13, 2008

    原文地址:My First IronRuby Unit Test Spec For ASP.NET MVC

    使用一门DLR语言像IronRuby来建立一个ASP.NET MVC程序是一件很Nice的事情,然而使用DLR语言可不是很自由。

    在我们设计中有一些地方是专门针对静态语言的(像属性(Attribute)为基础的过滤器),它在动态语言中就不能工作了。

    最理想的我们可以最大限度的减少这种情况的使用,如果我们不能减少,我们就必须确保框架的可扩展性,允许扩展系统如我们可以提供一个DLR友好的功能。

    我们怎么识别和减少这类情况呢?设计审查帮助,好像离的很远。因此,在和一些DLR团队成员协作下,我一直在探索用于测试IronBuby的最小规格框架,今晚我写了第一篇测试说明。了解一下它(注意:在require申明的一些行里增加了换行为了适应我的blog文章的宽度)

    require File.dirname(__FILE__) + '/../../spec_helper'
    require 'System.Web.Abstractions
    , Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    require 'System.Web.Routing
    , Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
    require 'System.Web.Mvc
    , Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

    describe "Route#<<" do

      it "can create RouteCollection which is empty" do
        rc = System::Web::Routing::RouteCollection.new
        rc.count.should == 0
      end
     
      it "can add route to RouteCollection" do
        rc = System::Web::Routing::RouteCollection.new
        r = System::Web::Routing::Route.new "", nil
        rc.add "route-name", r
       
        rc.count.should == 1
      end

    end

    下面是结果:

    Administrator CWindowsSystem32cmd.exe

    Yay!两个测试通过了。

    Yeah,这两个测试是非常非常的简单,但,hey,这只是我的第一步。我需要熟悉最小规格的框架。不仅如此,我已经很久没有写Ruby代码了。幸运的是,我有一份The Ruby Way的拷贝,这应该有帮助的。

    我可能有更加优先的工作要做,但是有时候需要找一些乐趣给自己。另外,我是在我自己的时间做这些事的。:)

    posted @ | Feedback (0) |

    原文地址:Unit Test Project Structure Poll

    当我建立应用程序时,我个人喜欢将单元测试放入一个单独的类库中而不是放在正在测试的应用程序中。That’s just how I roll

    我假设每个人的单元测试结构都是这样的,但我已与一些使用TDD很久的人交谈过,他们把他们代码放在同一个项目中。

    因此我想进行一次简单的投票,来看看大家使用什么结构的单元测试。我一直参与一些不同的内部讨论来看微软在设计上,工具上,代码上是怎样可以更好的支持单元测试。

    请注意这不是一个孰是孰非的问题。我不认为一个方法要比另一个方法更加正确。我只是想确定我们对实际操作有一个正确的观点。

    所以请务必回答这次调查,并鼓励其他人也这样做。我讨厌内部团队基于错误的假设进行选择。谢谢!

    译者:投票请到作者原文中去投! 

    posted @ | Feedback (0) |

    [原文地址]Interview With Brad Wilson On Microsoft And Open Source

    How Software is Built这篇帖子 中,我与Brad Wilson有了一次会谈,他是微软的OfficeLabs团块的开发员,但也许大家更熟悉他在xUnit.net,CodePlex,ObjectBuilder上的工作。

    brad 我最喜欢这个帖子的一点是Brad提供了他对微软内外部对开源不同观点的自己的想法以及他个人经验在开源项目中的贡献。也许一些人很难相信,但在微软内部确实有一些程序员是喜欢并致力于一些开源项目的。

    Brad(与Jim Newkirk) 在我的书中得到大加赞赏的另一个原因是xUnit.net 最近更新了他们的安装程序 包括了与asp.net mvc 预览第二版测试项目的整合

    posted @ | Feedback (0) |

    Wednesday, April 09, 2008

    原文地址:Subtext Awakens From Its Slumber

        Subtext已经沉寂了一段时间了。我认为开源项目们只会偶尔的沉寂一下时,Subtext却是很长时间一点动静都没有.

        主要原因是一些核心程序员几乎同一时间忙于更换工作(或是搬家)。像我,到微软工作和到西雅图花了我大量的时间和精力。

        安定下来之后,我卸载了老版本的TortoiseSVN客户端程序,安装了一个最新的版本,在TortoiseSVN目录中看到,在我离开的时间里,一些新人的加入让我感到很激动。

        那不完全是真的,但是要抓住事实的中心。

        总之,既然我差不多已经在美丽的Bellevue安定下来了,WA,上个星期决定花点时间在Subtext上。现在我又开始忙的不可开交了,但很高兴已经修复了一些关键的问题。

        We decided to scale back the 2.0 release a bit. We were a bit too ambitious with the feature set and supporting two branches became way to time consuming. So we replaced the trunk with the 1.9 branch and all new development is in the trunk where it should be.

        下个版本将仍然针对asp.net 2.0,之后,我们将针对asp.net3.5进行开发。现在我不去介绍2.0的特性。大量的工作在修复bug上,完善一些小的缺陷以及改进一些基础结构。我觉的Subtext最好的部分之一是build process and continuous integration server.

        既然我们要给下一个2.0版本加标签,我们将加入的一些新的热门的特征。它应该会是一个很好的版本。抱歉 沉寂了那么久,但是Subtext还是一直在前进。

    posted @ | Feedback (1) |

    Monday, March 24, 2008

    原文地址:Comparing Moq to Rhino Mocks

    原文发表时间:Mar 23, 2008

          长期以来我是Rhino Mocks的大粉丝,乐此不疲的写关于它的文章。当Moq出现时,我一直对它无动于衷,因为我原以为lambda表达式是华而不实的。我认为如果它只是使用lambads的话,我对此不感兴趣。

        幸运的是 在我的twitter圈子里有一些人一直对Moq大加赞赏。我是一个乐于承认错误的人,所以我决定找出Moq究竟好在哪里。结果发现,使用lambdas并不是Moq最优的部分。它有清晰干净的API设计以及弱的录制/回放模式.

        为了更好的说明我的意思,这里有一个简单的例子,分别用Rhino Mocks和Moq写的两个单元测试方法。使用mock框架的测试,只用一个方法来建出一个接口。

    [Test]
    
    public void RhinoMocksDemoTest()
    
    {
    
    MockRepository mocks = new MockRepository();
    
    var mock = mocks.DynamicMock<ISomethingUseful>();
    
    SetupResult.For(mock.CalculateSomething(0)).IgnoreArguments().Return(1);
    
    mocks.ReplayAll();
    
    var myClass = new MyClass(mock);
    
    Assert.AreEqual(2, myClass.MethodUnderTest(123));
    
    }
    
    [Test]
    
    public void MoqDemoTest()
    
    {
    
    var mock = new Mock<ISomethingUseful>();
    
    mock.Expect(u => u.CalculateSomething(123)).Returns(1);
    
    var myClass = new MyClass(mock.Object);
    
    Assert.AreEqual(2, myClass.MethodUnderTest(123));
    
    }
    

        注意使用Moq的测试只需要四行代码,而使用Rhino Mocks的测试需要六行。代码的行数当然不是衡量API的标准,但在这个例子中确实是这样。Rhino Mocks中多于的代码是由于需要实例化MockRepository类并调用它的RepalyAll方法。

        我喜欢Moq的另外一个方面是expectations都是基于Mock自身的。即使在我喜欢上它之后,当要使用Rhino Mocks建立results/expecations时,我仍然很困惑。首先你必须使用正确的静态方法,不管是 SetupResult 还是 Expect。第二,我经常搞不清SetupResult.On和SetupResult.For.我感觉MoQ更加直观和清晰。

        我要习惯于Moq的另外一个小的方面是 我一直努力将Mock本身而不是Mock.Object传到需要它的method/ctor上。当你使用Rhino Mocks创建mock的时候,你取回的是实际的类型而不是wrapper.然而,我看到了在Moq方法中使用wrapper的好处,现在非常喜欢用它。

        对Moq的唯一的抱怨 是它的名字。谈论Moq的你必须说“Moq with a Q”.比起MoQ,我更喜欢MonQ.不管如何,如果那是我唯一的抱怨,那我是一个快乐的人!你可以从google Code Page 下载MoQ,了解更多。

    Nice work Kzu!

    附录

    万一你想重建测试例子,以下是我MyClass和接口IsomethingUseful的代码。

    public interface ISomethingUseful 
    {
    int CalculateSomething(int x);
    }
    public class MyClass
    {
    public MyClass(ISomethingUseful useful)
    {
    this.useful = useful;
    }
    ISomethingUseful useful;
    public int MethodUnderTest(int x)
    {
    //Yah, it's dumb.
    return 1 + useful.CalculateSomething(x);
    }
    }
    

    posted @ | Feedback (0) |