58

作为 ASP.NET MVC 的新手,我一直想知道 Controller 方法的签名。在我见过的所有示例中,它们似乎总是返回 ActionResult,即使它们实际上返回了 ViewResult 实例或类似实例。

这是一个常见的例子:

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

public ViewResult Index()在这种情况下,将方法声明为并获得更强的类型支持不是更有意义吗?

实验表明这是可行的,所以它似乎是可能的。

我确实意识到可能存在需要多态性的情况(例如,如果您只想在某些情况下重定向,但在其他情况下显示视图),但如果该方法总是返回一个视图,我会找到一个 ViewResult 更多可取的。

就未来的兼容性而言,ActionResult 显然提供了更健壮的签名,但如果一个人控制了整个代码库,那么如果将来需要的话,总是可以将方法的签名更改为更通用的返回类型。

是否还有其他我不知道的注意事项,或者我应该继续使用特定的返回类型声明我的控制器方法?

4

6 回答 6

60

您绝对可以使用特定的返回类型,即使网络上的大多数示例似乎都返回ActionResult。唯一一次我会返回ActionResult类是当 action 方法的不同路径返回不同的子类型时。

Steven Sanderson 还建议在他的书Pro ASP.NET MVC Framework中返回特定类型。看看下面的报价:

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

于 2009-06-20T13:33:59.313 回答
13

始终返回您可以返回的最准确的类型。因此,当操作始终显示视图时,您应该返回 ViewResult。我只会在某些情况下(无效的发布数据)或 RedirectToRouteResult 在其他情况下返回 ViewResult 时使用 ActionResult 。

使用一些高级动作过滤器/执行场景,您甚至可以返回与 ActionResult 无关的完全不同的东西。

于 2009-06-20T13:18:21.733 回答
8

[部分答案]:您并不总是返回 ActionResult,不。以下是您可以返回的其他一些结果的列表:

  • 查看结果
  • 部分查看结果
  • 重定向结果
  • 重定向到路由结果
  • 内容结果
  • json结果
  • JavaScript结果
  • 文件结果
  • 空结果

有关更多信息,请参阅文档

也许这会有所帮助。祝你好运!

于 2009-06-20T13:13:06.580 回答
7

是的,您可以定义您的操作,例如:public ViewResult Index(). 但有时您的操作可能会返回不同的结果(如果不将结果声明为基类,这是不可能的ActionResult)。例如:

public ActionResult Show()
{
    ...

    if(Request.IsAjaxRequest())
    {
        return PartialView(...);
    }

    return View(...);
}

或者:

public ActionResult Show()
{
    ...

    try
    {
        ...
    }
    catch(Exception)
    {
        return RedirectToAction(...);
    }

    return View(...);
}
于 2009-06-20T13:40:42.327 回答
3

ActionResult 是各种返回类型的基类。因此,您的操作必须返回一个 ActionResult或从它派生的类才能工作。常见的有ViewResult,JsonResult等。

于 2009-06-20T14:12:45.650 回答
2

是的,我有 Sanderson 的书,我喜欢关于具体的部分,因为当我查看其他控制器动作示例时,这让我很烦恼。我的哲学甚至 b4 学习 MVC 是,因为函数(返回值的方法)应该被视为好像你在声明一个变量/在上下文中可以替换相同类型的变量/引用,所以要具体说明类型,因为你如果声明一个 var (将其视为希望避免在应用程序中将所有变量定义为“对象”类型 - 更健壮,但您会失去一些设计时检查和类型安全性)。也有助于正确返回类型的控制器单元测试。

有关相关参考,请查看 Listkov 的替换原则(“SOLID”中的“L”)。

于 2012-03-14T21:18:51.997 回答