为什么大多数MVC示例控制器代码返回ActionResult?

5

我想知道为什么在大多数MVC示例代码中,几乎每个控制器方法都返回ActionResult,即使很明显该代码只能返回一种类型的结果。我知道有某些情况下这样做是有必要的,比如根据逻辑可能返回RedirectResult或ViewResult等,但大多数方法并非如此。

这不就相当于在方法上设置返回类型为“object”吗?为什么不直接指定JsonResult、FileResult或ViewResult作为返回类型呢?难道我没有看到的好处就是把每个控制器方法的返回类型设置为ActionResult吗?

典型案例:

public ActionResult Index()
{
    return View();
}

为什么这似乎是常态而不是这样:
public ViewResult Index()
{
    return View();
}

编辑:目前为止,除了一个回复外,所有回复都表明ActionResult只是更通用的。我知道这一点。 :) 但是,为什么在控制器方法上接受这种做法,而不是在任何其他地方呢?您不会在普通方法中返回类型的最高级基类,而通常会尝试返回最具体的类型。是什么让控制器方法如此不同,以至于博客作者和“示例代码编写者”(是的,我创造了这个术语)会只返回ActionResult?


6个回答

6

以下是从SO上接受的答案,我认为很有道理:

ASP.NET MVC控制器方法必须返回ActionResult吗?

您完全可以使用特定的返回类型,尽管网络上的大多数示例似乎都返回了ActionResult。我只会在操作方法的不同路径返回不同的子类型时才返回ActionResult类。

Steven Sanderson在他的书《Pro ASP.NET MVC Framework》中也建议返回特定类型。请看下面的引用:

"此操作方法明确声明返回ViewResult实例。如果方法返回类型为ActionResult(所有操作结果的基类),则它将正常工作。事实上,一些ASP.NET MVC程序员将所有操作方法声明为返回非特定的ActionResult,即使他们确定它总是返回一个特定的子类。但是,在面向对象编程中,已经确立了一个原则,即方法应该返回它们可以的最具体的类型(以及接受它们可以的最通用的参数类型)。遵循这个原则可以最大程度地方便和灵活代码调用您的方法,例如您的单元测试。"

另请参阅:

http://www.bengtbe.com/blog/post/2009/07/01/Use-specific-return-types-in-your-ASPNET-MVC-action-methods.aspx


我也同意这个答案,并且会接受它,但我仍然很好奇,在一个开发人员习惯尽可能明确声明返回类型的环境中,为什么MVC程序员在某些情况下似乎突然抛弃了这个概念。这并不是很有道理。 - Scott
2
@Scott Schluer:因为控制器操作的真正“消费代码”通常是浏览器或JavaScript,所以类型安全的好处在这种情况下不太明显。如果您可以像GWT的RPC框架一样在类型安全的语言中使用此代码,我认为人们会更加注意设置特定的返回类型。 - StriplingWarrior
2
我发现对于它们全部使用ActionResult非常方便。我同意减少类型安全性的担忧在这种特定情况下更加可行。我认为这是一种主要基于方便和可读性的实践。当我看到ActionReult时,我立即知道方法的目的。如果我需要在该操作上抛出一个重定向,我不需要修改返回类型来实现。 - Derrick
1
@Derrick 关于重定向的问题。@jim Derrick所说的是,如果您需要重定向而不是显示页面,则需要更改返回类型。 - bzlm
bzlm - 在这方面已经被接受了。然而,在那种情况下,返回类型可能会在该更改之后变得“提高”。 - jim tollan

1

我猜测返回ActionResult而不是更具体的结果,只是因为没有必要使代码更具体。

使用更通用的类型可以使事情更加灵活。

请记住,更改返回类型可能不是Web应用程序项目中的问题,但这也会导致您在测试项目中更改所有单元测试。


在我看来,如果你改变了你的返回值,你必须要相应地修改你的单元测试。当这种情况发生时,我宁愿让编译器告诉我“这些单元测试将不再起作用”。在大多数情况下,你的单元测试只需要将结果转换为其实际类型,以便测试例如返回的ViewResult上的Model是否具有你期望的值。 - StriplingWarrior
@StriplingWarrior - 就我个人而言,我宁愿先构建我的项目,然后发现我的单元测试失败,也不愿因为单元测试中的错误代码而延误项目的构建。 - Justin Niessner
我想这是一个观点问题。就我个人而言,我认为在编译时捕获更多的问题可以节省时间,这也是使用类型安全、编译语言的最大原因之一。 - StriplingWarrior

0

这可能是因为ActionResult是视图可以处理的最高对象。

ActionResult

ViewResult

System.Object
  System.Web.Mvc.ActionResult
    System.Web.Mvc.ViewResultBase
      System.Web.Mvc.ViewResult

对我来说,每个XXXResult都专门用于特定的用途。 如果您不需要特定的...


0

只有在控制器内部逻辑不确定返回类型时,应使用通用返回类型。否则-使用特定的(这被认为是更好的编程)。

我不知道为什么人们在示例中使用ActionResult,但我已经看到了许多我可能不同意的东西-取其精华,去其糟粕....

在您知道这是唯一返回对象而不是ActionResults时,应使用ViewResult。


0

我认为真正的原因是MVC模板中自动生成的代码会让你从ActionResult开始,人们只是按照这个模式进行。由于许多人不对其控制器操作进行单元测试,他们无法以类型安全的方式使用结果,这就成为了一个痛点。


那听起来很疯狂。看看http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx。即使是Scott Guthrie也这样做,我相信他不是那种只因为理解不足就跟随“出厂设置”的开发人员。:)一个简单的控制器方法,仅返回视图,但返回类型是ActionResult... - Scott

0

ScottGu 之所以这样做,可能是为了举例子更容易。演示的主题通常决定了您看到的代码质量;如果只是为了举例子,他们通常会随便写点东西来说明一下(在发布之前,在自己的端上编写/测试示例变得更加容易,并且在发布时保持不变;我也这样做过)。至于最佳实践;关于 HTML 和 JS(基本上)“不太关心”类型,不要让 JavaScript 的问题(如类型弱点)泄漏/感染您自己磨练出来的良好编码风格。尽可能使用特定类型。此外,如果您的 JS 代码使用类型最佳实践编写,则该代码也可能期望 JSON 结果(如果是这样),并且是代码可以测试的内容,因此如果它正在尝试在可以使用类型的地方执行正确的操作,则不希望在那里限制 JS 代码的功能。确实,在某些情况下,不良影响比其他情况更/少明显(例如返回到不太安全的语言),但是始终保持一致是更好的编程习惯。通常,这种做法会导致某种类型转换/强制转换,以返回您想要使用的更具体对象的功能(很可能在基本对象中不可用-如果始终可用,则您的类型太具体/应该是基础)。强制转换本质上是丑陋/邪恶的;在运行时派生类型总会让您陷入麻烦(为什么这种做法已被反对/静态/强类型/安全性的好处已被吹捧了几十年)。让您代码的使用者/维护者也能通过元信息(悬停在方法上等)来判断函数实际正在做/返回。事实上,这对于单元测试更好,因为这是可以测试的条件(正如 Steven Sanderson 的书摘所示)。我还发现有人使用不想保留构建作为弱类型的原因?真的吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接