ASP.NET MVC与RAILS3的比较

进入后Web年代之后,MVC框架进入了快速演化的时代,Struts等垂垂老矣的老一代MVC框架因为开发效率低下而逐渐被抛弃,新一代的MVC则高举敏捷的大旗,逐渐占领市场,其中的代表有Rails (ruby), .NET MVC (.NET), Django (Python),Symfony (PHP)等等,这些框架的思想都大同小异,这里列举出Rails3和.NET MVC的一些的区别,以方便Web开发者从Rails迁移到.NET MVC,或者反之,从.NET MVC迁移到Rails.

[b]生成项目[/b]
Rails和.NET MVC都能够产生项目的基本骨架,只是生成的方式略有不同,Rails采用的是命令行的方式:
[code]
rails tapir
[/code]
而Microsoft则秉承其强大的IDE,提供了项目向导。

最终得到的目录结构,仅在测试和配置项上略有不同。
[table]
|Rails| ASP.NET MVC|
|/app/models |/Models |
|/app/controllers |/Controllers|
|/app/views|/Views|
|/public/javascript|/Scripts|
|/public|/Content|
|/db|/App_Data|
|/test|单独的VS项目|
|/config |/Global.asax, /Properties, Web.config|
[/table]

值得一提的是rails的一个亮点:rails可以预先配置三个不同的环境:开发、测试、最终产品,可以通过RAILS_ENV这个环境变量来做简单切换,.NET MVC并未提供这样的配置环境,你可以通过手工配置来完成。

[b]模型Model[/b]
Rails默认采用ActiveRecord作为模型,当然切换到其他的框架也很简单,可选项有 Neo4J, MongoDB,和DataMapper。在Rails中,还是采用命令行来创建模型,Rails会生成一些骨架代码,包括:模型、迁移任务和测试。你可以用-o来选择其他模型、-t来选择其他测试框架:
[code]
$ rails g model customer name:string email:string
invoke active_record
create db/migrate/20100419094010_create_customers.rb
create app/models/customer.rb
invoke test_unit
create test/unit/customer_test.rb
create test/fixtures/customers.yml
[/code]

Rails默认采用Sqlite3作为后台数据库,而且Rails会很贴心的为开发、测试、生产三个环境分别产生一个数据库拷贝。

在Rails中,所有的数据库的操作都通过脚本和迁移来完成,Rails中的迁移应该是最有价值的一个东西,当不同的开发者同时在修改一个数据库,或者您在升级现有的生产环境下的数据库,迁移就显示出它的强大威力:
[code]
class CreateCustomers < ActiveRecord::Migration

# Called when migrating up to this version
def self.up
create_table :customers do |t|
t.string :name
t.string :email
t.timestamps
end
end

# Called when migrating down from this version
def self.down
drop_table :customers
end
end
[/code]

我们可以通过rake db:migrate命令迁移到不同的数据库版本上去。

和Rails不同的是,.NET MVC并为绑定一个模型框架,你要从既有的框架中选择一个适合你的,这个名单里可以用Nhibernate,Linq to SQL, Entity Framework,Castle ActiveRecord或者Ruby的ActiveRecord,不过.NET MVC没有迁移的概念,这有点遗憾。

大部分情况下Linq To SQL就很适合项目开发。

[b]查询语言[/b]
Rails3使用AREL(Active Record Relations),LINQ-to-SQL则使用LINQ。 二者都是相当优美的语言
[code]
# A simple query with AREL
User.where(users[:name].eq('Anders')).order('users.id DESC').limit(20)
[/code]

[code]
// The same with C#
// Lambda Syntax
db.Users.where(u => u.Name == "Anders").orderBy(u => u.Id).Take(20)

// LINQ Syntax
(from u in db.Users
where u.Name == "Anders"
orderby u.Id descending
select u).Take(20);
[/code]

现在除了在.NET中采用Ruby的ActiveRecord(借助ironruby),目前还没有其他框架提供类似Ruby的findbyXXX的功能,不过C# 4.0的method_missing使得这类框架应该会很快出现(比如Nhibernate 3.0)

[b]控制器[/b]
在.NET MVC中,你在Controller目录上点添加,就有很贴心的向导引导你为项目添加控制器,甚至还可以增加基本的CRUD的功能。
[code]
public class CustomersController : Controller {
// GET: /Customers/
public ActionResult Index() {
return View();
}

// GET: /Customers/Details/5
public ActionResult Details(int id) {
return View();
}

// GET: /Customers/Create
public ActionResult Create() {
return View();
}

// POST: /Customers/Create
[HttpPost]
public ActionResult Create(FormCollection collection) {
try {
// TODO: Add insert logic here
return RedirectToAction("Index");
} catch {
return View();
}
}
}
[/code]

和Rails的脚手架代码一样,这些最基本的代码99%会被废弃,但是提供了“让程序跑起来看看”的基础。

Rails还是通过命令行来为项目增加控制器,你还可以在命令行里制定为控制器生成哪些Action。

[b]过滤器[/b]
Rails很容易为某个Action添加个过滤器
[code]
class ItemsController < ApplicationController
before_filter :require_user_admin, :only => [ :destroy, :update ]
before_filter :require_user, :only => [ :new, :create]
end
[/code]
.NET也不含糊,只要重载OnActionExecuting就可以实现同样的功能:
[code]
override void OnActionExecuting(ActionExecutingContext filterContext)
{
var action = filterContext.ActionDescriptor.ActionName;
if (new List<string>{"Delete", "Edit"}.Contains(action)) {
RequireUserAdmin();
}
if ("Create".Equals(action)) {
RequireUserAdmin();
}
}
[/code]
或者通过.NET的attribute更漂亮的完成
[code]
[RequireUserAdmin("Delete", "Edit")]
[RequireUser("Create")]
public class CustomersController : Controller
[/code]

[b]路由[/b]
在Rails中,可以修改routes.rb来修改路由,默认的Rails的路由被配置成RESTful:
[code]
Tapir::Application.routes.draw do |map|
resources :animals

get "customer/index"
get "customer/create"

match "/:year(/:month(/:day))" => "info#about",
:constraints => { :year => /\d{4}/,
:month => /\d{2}/,
:day => /\d{2}/ }
match "/secret" => "info#about",
:constraints => { :user_agent => /Firefox/ }
end
[/code]
通过rake routes你可以快速查看路由的结果。

ASP.NET MVC的路由稍微复杂一些,不过同样强大:
[code]
// Global.asax.cs
public class MvcApplication : System.Web.HttpApplication {
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

// Constrained route
routes.MapRoute( "Product", "Product/{productId}",
new {controller="Product", action="Details"},
new {productId = @"\d+" } ); // Constraint

// Route with custom constraint, defined below
routes.MapRoute( "Admin", "Admin/{action}",
new {controller="Admin"},
new {isLocal=new LocalhostConstraint()} );
}
...
}

public class LocalhostConstraint : IRouteConstraint {
public bool Match ( HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values,
RouteDirection routeDirection )
{
return httpContext.Request.IsLocal;
}
}
[/code]

[b]View[/b]
二者在View上的表现十分接近,添加控制器的时候,会自动创建相应的视图,规则也类似:视图所在的文件夹以控制器的名字命名,视图的文件名则以控制器的action命令,二者也都提供了从某个模型创建脚手架视图的能力。

[b]Partials[/b]
Rails和Asp.NET MVC都提供了在文件中包含部分HTML文件能力,ASP.NET MVC的文件采用ASP,而Rails默认是ERB或HAML.
[code]
<!-- Rails -->
<%= render 'form' %>
[/code]

[code]
<!-- ASP.NET MVC -->
<% Html.RenderPartial("Form", Model);%>
[/code]

.NET MVC 2中更做出了一些改进,提倡用2个替代的方法来产生代码:
[code]
<%= DisplayFor("Address", m => m.Address ) %>

<%= EditorFor("Address", m => m.Address ) %>
[/code]


[b]尾声[/b]
这篇文章对Rails和.NET MVC作了一个快速的浏览,目的是让有相应编程经验的程序员能快速了解另一个框架。无论Rails还是.NET MVC,都只是一个工具,一个好的程序员应该能随心摆弄他的工具,而不是被工具所摆布。


参考:
http://blog.jayway.com/2010/04/23/asp-net-mvc-vs-rails3/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值