ASP.NET MVC和Rails具有相似的使用领域,围绕相同的体系结构构建,这两个框架都是相对较新的开放源代码。
因此,作为一名Rails程序员,我想知道ASP.NET MVC可以做什么而Ruby on Rails不能做什么,反之亦然?
ASP.NET MVC和Rails具有相似的使用领域,围绕相同的体系结构构建,这两个框架都是相对较新的开放源代码。
因此,作为一名Rails程序员,我想知道ASP.NET MVC可以做什么而Ruby on Rails不能做什么,反之亦然?
Answers:
我已经使用Rails和ASP.NET MVC开发了实际的应用程序,但是这个答案带来了一个重要的警告:我是使用第二版Rails进行学习和开发的,所以我完全有可能过时了Rails知识。
话虽这么说,我不认为一个可以完成任何事情,而另一个则无法完成。考虑到Web应用程序的任何要求,您应该能够使用Rails或ASP.NET MVC构建该应用程序(可能同样有效)。
据我所知,ASP.NET MVC中有几件整洁的东西,主要是由于C#/。NET的方面。例如:当我有一个包含提交表单的页面时,我将有一个动作来检查它是否正在处理GET或POST来决定要做什么:
def edit
@item = Item.find(params[:id])
if request.post?
@item.update_attributes(params[:item])
redirect_to :action => 'edit', :id => @item.id
end
end
这是一个简单的例子,但是这种if request.post?
模式在Rails中是非常普遍的。对于非平凡的情况,Action代码可能会变得又大又杂乱,而且经常希望我可以将其整洁地重构为单独的方法。在ASP.NET MVC中,我可以这样做:
public ActionResult Edit() {
// Render my page that has the Edit form
...
}
[HttpPost]
public ActionResult Edit(Foothing foo) {
// Save my Foothing data
...
}
我认为能够完全区分GET和POST请求的处理很整洁。你的旅费可能会改变。
ASP.NET MVC所做的另一件事非常酷(我再次认为)也与处理表单POST有关。在Rails中,我必须查询params
所有表单变量的哈希值。假设我有一个表单,其字段为“ status”,“ gonkulated”,“ invert”和“ disposition”:
def edit
@item = Item.find(params[:id])
if params[:status] == "new"
...
else
...
end
if params[:gonkulated] == "true"
...
else
...
end
if params[:invert] == "true"
...
else
...
end
# Rest ommited for brevity
end
但是ASP.NET MVC巧妙地允许我将所有表单值作为我的Action方法的参数:
[HttpPost]
public ActionResult Edit(int id, string status, bool gonkulated, bool invert, int disposition) {
...
}
这是我真正喜欢ASP.NET MVC或Rails的两件事。对于任何有理智或有能力的开发人员选择一个框架而不是另一个框架,它们是没有足够的理由的。
public ActionResult Edit(Foothing foothing)
,即ModelBinder的功能更加整洁。
与Rails相比,ASP.NET MVC的一个优势是,如果您需要在现有数据库上构建新的应用程序。Rails的ActiveRecord对于如何构造表(表必须具有一个且只有一个整数列作为主键,称为“ id”等)非常有意见,因此,如果您现有的表不符合ActiveRecord首选项,则很难制作ActiveRecord工作。但是使用ActiveRecord和Rails用新的数据库开发新的应用程序很快!
ASP.NET MVC没有默认的ORM。您可以选择适合自己需求的数据访问策略。像nhibernate这样的ORM可以支持旧数据库。您可以使用guid主键等。
Rails ActiveRecord的替代方法是DataMapper,但我没有尝试过。
两者兼而有之,IMO的回答是,如果您的应用程序需要做的不仅仅是从数据库读取/写入,则ASP.NET MVC比Rails更灵活。以我的经验,Rails在您向应用程序介绍任何形式的复杂性或逻辑(除了非常琐碎的CRUD逻辑之外)的那一刻,都会迅速崩溃。ASP.NET MVC不会遇到此限制,因为它对您的操作更加“开放”。
在典型的“ Web 2.0” CRUD应用程序中,所有其他条件都是相同的,没有其他可以做的,但是对于需要工作流,不同数据源或与另一个应用程序进行交互的更复杂的应用程序,则那不是典型的CRUD,ASP.NET可以做更多的事情,而且不像Rails那样严格。
我从未与Ruby on Rails一起工作过,所以我没有完全资格回答这个问题,但是我非常喜欢ASP.NET MVC的一件事是类型安全。这是有道理的。亚当·克罗斯兰(Adam Crossland)和rmac在他们的评论中简要地谈到了它,但是我想指出的是,使用如下所示的控制器方法,每个参数都将被强类型化。这使Edit方法中的代码更加整洁,因为您不必担心将字符串表示形式转换为正确类型的变量。
[HttpPost]
public ActionResult Edit(int id, string status, bool gonkulated, bool invert, int disposition) {
...
}
此类型安全性显示的另一位置是“视图”和“部分视图”,在其中可以将部分视图的视图与Plain Old C#对象关联,该对象将用作该视图或部分视图的模型。这使工作变得更加轻松,尤其是在您要构建包含其他视图的视图层次结构的地方。
如果Infinity.ViewModels.Site
是包含名为的类的名称空间ContactViewModel
,则对于Razor视图,您可以通过在视图顶部放置如下一行来实现:
@model Infinity.ViewModels.Site.ContactViewModel
对于ASPX视图,可以通过以下方式声明视图:
<%@ Page Language="C#" ="~/Views/Shared/Site.master" ="System.Web.Mvc.ViewPage<Infinity.ViewModels.Site.ContactViewModel>" %>
您可以在Controller动作方法中将模型对象的实际实例与视图相关联,然后通过视图的Model
属性访问视图中的模型对象的实例。
对我而言,这种坚强的型真的很酷。创建ASP.NET MVC的团队花费了很多心血来使3个Model,View和Controller区域中的每个区域都得到强类型。
我不确定Ruby-on-Rails是否有此功能,但我希望如此。
它们非常相似,并且大多数都可以“做相同的事情”,只是其中一些事情比一件事情容易而难。
我在原始发行版附近使用了ASP.NET MVC,它肯定是Rails克隆减去activerecord。因此,Rails几乎可以肯定具有更大的功能集和更大的插件/宝石生态系统。
以我有限的经验,ASP.NET MVC的主要优点是它是一种编译语言。这样,您就可以在编译时检测到一些编程错误,而Ruby在单元测试期间必须依靠检测这些错误。
同样,它被编译的事实使得拥有高级重构工具成为可能,例如,在一处更改属性的名称,并更改对该属性的所有引用。至少在许多Rails开发人员使用的TextMate中无法做到这一点。
另一方面,Ruby on Rails的主要优点是它是一种解释型语言;)Ruby的本质(如何修改内存中的任何对象或对类进行猴子修补)可以带来一些非常优雅的解决方案;请查看《Eloquent Ruby》一书中的一些示例。而且很多Rails框架本身就是基于这种能力的。
随时可以替换任何对象上任何方法的能力也极大地帮助了我编写单元测试。在.NET中,依赖注入和IOC容器实际上是创建可测试代码的要求。在Ruby中这不是必需的。
编辑:
考虑一下之后,Rails的杀手feature可能是数据库迁移。ASP.NET MVC框架本身不提供任何数据库支持。.NET框架确实具有一些数据访问组件/ ORM,例如Entity Framework和Linq to Sql。但是它没有用于设计数据库结构的任何工具。
如果您购买了VS中较昂贵的版本之一,则可以获得Data Dude,它可以设计数据库架构,并提供一些用于将该架构部署到数据库的工具。但是据我所知,对从早期版本的应用程序迁移进行处理的支持非常有限。
有人声称,由于缺乏对数据库迁移的支持,ASP.NET MVC并不是真正的MVC框架,而仅仅是VC框架。
再次编辑:
自从我上次编辑以来,对Visual Studio工具链/ EF的更改已引入了基于代码的迁移。(如果您要沿着那条路走,也可以查看FluentMigrator)
我对Microsoft的MVC 3和Entity Framework的主要问题是它们惊人的糟糕设计原则。
我遇到的第一个问题是将另一个类用作属性并尝试为可能的值创建下拉列表时。
为了说明我的观点,假设您有两个类似的模型类:
public class Color
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Thing
{
public int ID { get; set; }
public string Name { get; set; }
public virtual Color Color { get; set; }
}
创建Color属性对于实际的ORM而言已足够,但对于EF而言已足够。您必须在Thing类中为Color属性添加一个冗余ID,如下所示:
public class Thing
{
public int ID { get; set; }
public string Name { get; set; }
public int ColorID { get; set; }
public virtual Color Color { get; set; }
}
如果不为外部对象引用添加冗余ID字段,则无法使用链接类中的所有可能选项轻松创建下拉列表。
这确实是一个糟糕的设计,因为它将一个类的内部工作原理与另一个类紧密地结合在一起。对ColorID一无所知,Color类应该处理自己的相等性检查,而不会暴露其甚至具有ID。
这是最佳实践101的东西,但显然Microsoft完全不了解计算机科学和面向对象编程的基本原理。[/ rant]
int?