65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET MVC 中的 Action Result

starIconstarIconstarIconstarIconstarIcon

5.00/5 (13投票s)

2018 年 6 月 22 日

CPOL

10分钟阅读

viewsIcon

31146

在本文中,您将学习 ASP.NET MVC 5 中关于 Action Result 的基本核心概念。希望您会喜欢。欢迎提出您的反馈意见。

引言和背景

本文将告诉您关于 ASP.NET MVC 中 Action Result 的从基础到高级的核心概念。上周,我的一位朋友问了一个问题:“为什么在 action 方法中存在 ContentResult 数据类型,它的目的是什么?” 我将本文献给他。希望他会喜欢。

将要涵盖的主题是

  • 什么是 ActionResult
    • 返回内容的结果
    • 重定向的结果
    • 状态结果

这个问题

根据问题的第一个部分,为什么在 action 方法中存在 ContentResult 数据类型?要理解这一点,您必须了解 ASP.NET MVC 5 中的数据类型,因为 ContentResult 是一种数据类型,其基类型是 ActionResult,因此您必须了解 ActionResult

让我们开始 Action Result 的学习。

操作结果

Action Result 实际上是一种数据类型。当它与 action 方法一起使用时,就称为返回类型。如您所知,action 指的是控制器的方法。所以 Action Result 是 action 执行后的结果。事实上,Action Result 是一种返回类型。这种返回类型有许多其他派生类型。首先,让我们看看 ActionResult 的基类型和派生类型。

namespace System.Web.Mvc
{
    public abstract class ActionResult
    {
        //
        // Summary:
        //     Initializes a new instance of the System.Web.Mvc.ActionResult class.
        protected ActionResult();
    }
}

正如您在 Visual Studio 中看到的,ActionResult 类型来自 System.Web.Mvc assembly。问题是,我们无法使用 Visual Studio 的“转到定义”功能查看此程序集内部的内容。

要查看程序集内部,您可以按照下面提供的步骤下载 ILSpy,或者点击 此处 查看我名为 ILSpy.gif 的 GIF 文件。

步骤如下

  1. 我将为您提供下载 ILSpy 的直接链接。点击 此处
  2. 如果您没有 System.Web.Mvc 程序集,则可以点击 此处 下载。
  3. 下载后,解压 ILSpy 并运行它。
  4. 点击文件(左上角)。
  5. 选择“打开”选项,然后打开您下载的程序集。
  6. 选择后,程序集将在 ILSpy 软件中加载。
  7. 展开程序集,您将看到 ActionResult,也将其展开,您将看到基类型和派生类型。
  8. 下面图片显示了 ActionResult 的类型

现在您可以看到,ActionResult 是一个基数据类型,其派生类型包括 HttpStatusCodeResultJavaScriptResultFileResultContentResultJsonResultEmptyResultRedirectResultRedirectToRouteResultViewResult。并且每个数据类型(基类型或派生类型)都应该有一个辅助方法。

当我们进入 ActionResult 时,发现它是一个 abstract 类。

namespace System.Web.Mvc
{
    public abstract class ActionResult
    {
        //
        // Summary:
        //     Initializes a new instance of the System.Web.Mvc.ActionResult class.
        protected ActionResult();
    }
}

它是一个 abstract 类,因为控制器的方法可以同时返回不同类型的数据。因此,它必须是 abstract 的,以便每个 Http 请求都能得到妥善处理。请看下面的代码

public ActionResult Index()
{
    bool answer = DateTime.Now.Day + 2 == 5;
    if (answer)
    {
        return Content("Correct");
    }
    else
    {
        return View();
    }
}

如您所见,同一个 action 方法“Index”返回两种不同的类型,分别是 ContentView。所以,如果您想返回多种类型,您必须使用基类型 ActionResult

上述概念也回答了“何时选择基类型 ActionResult 或派生类型?”这个问题。

答案是,为特定结果选择派生类型是一种好习惯,但当您希望 action 方法返回多种类型时,您必须使用基类型 ActionResult

现在,重要的概念来了,派生类型有三个类别。让我们看一下。

正如您所见,ActionResult 的数据类型有三个类别

  1. 返回内容的结果
  2. 重定向的结果
  3. 状态结果

让我们逐一理解。

返回内容的结果

顾名思义,这些结果用于将内容返回到浏览器。有 7 种内容返回结果

  1. ViewResult
  2. PartialViewResult
  3. ContentResult
  4. EmptyResult
  5. FileResult
  6. JsonResult
  7. JavaScriptResult

ViewResult

ViewResult 是一个 datatype,负责返回 View。让我们看一个例子。

public class HomeController : Controller
{
    public ViewResult Index()
    {
        return View();
    }
}

Index 视图的代码如下

<h2> This is Index View. </h2>

如您所见上面的代码,index action 方法使用 ViewResult 类型返回 View。之后,MVC 将在 Views 文件夹的 “Home” 文件夹中查找名为 “Index” 的 View。

输出

ViewResult 类型有趣之处在于,即使 action 方法的名称与 View 的名称不同,您也可以返回一个不同的 View。看一个例子。

public class HomeController : Controller
{
    public ViewResult Index()
    {
        return View(“Second View” );
    }
}

您可以在下图中看到我们在 views 文件夹中有“Second View”页面

Second View”页面的代码如下

<h2>This is Second View but having action name "Index"</h2>

如上所示,现在 MVC 将查找名为“Second View”的视图,而不是查找与 action 名称同名的视图。

输出

因此,您可以使用 ViewResult 类型调用任何其他具有不同 action 名称的视图。

PartialViewResult

这是用于返回部分视图页面而非常规视图页面的类型。看它的例子。

public class HomeController : Controller
{
    public PartialViewResult Index()
    {
        return PartialView("Second View");
    }
}

Second View”的代码如下所示

<h2>This is Second View but having action name "Index"</h2>

输出

您可以看到,输出与上一个示例相同。但不同之处在于,这里我们看不到“© 2018 - My ASP.NET Application”这一行,因为它是来自 Layout 页面的行,由于使用了 PartialViewResult 数据类型,所以这里没有。

您可以看到,PartialViewResult 的输出与 ViewResult 相同。但是 Layout 页面的内容丢失了。这只是一个示例。这并非真实场景的示例。

现在让我们看一个有 Layout 页面的示例。创建一个名为“Student”的新控制器和一个名为“Name”的 action 方法,如下所示

public class StudentController : Controller
{
    public PartialViewResult Name()
    {
        return View("_SecondView");
    }
}

无需为“Name”创建 View。因为这里,Name action 方法正在调用一个不同的 View 页面。请看下面的文件夹结构

创建部分视图页面的正确方法是,它应该在常规视图中使用,其名称以 _ 开头,并且应该位于 Shared 文件夹中。

现在当您执行它时,您将看到相同的输出,但具有 Layout 页面的内容。请看下面的图片

所以,您可以在这里使用 PartialViewResult datatype

ContentResult

ContentRresult 是一种 datatype,负责返回内容。但有趣的是,您可以很好地控制返回的内容。我的意思是,您必须在 ContentResult 类型的“Content”辅助方法中添加内容。在这里,您可以传递 HTML 内容、JavaScript 内容或其他任何内容。让我们通过示例来理解。

Home 控制器的代码如下

public class HomeController : Controller
{
    public ContentResult Index()
    {
        return Content("<h3>Zain Ul Hassan </h3>");
    }
}

输出

您也可以在 Content 辅助方法中提供 MIME(多用途互联网邮件扩展)类型,以便 MVC 在识别内容后采取适当的操作。代码如下所示

public class HomeController : Controller
{
    public ContentResult Index()
    {
        return Content("<h3>Zain Ul Hassan</h3>", "text/html");
    }
}

输出与上面相同

您也可以提供 JavaScript 内容,它将由 ContentResult 类型返回。让我们看一个例子。

public class HomeController : Controller
{
    public ContentResult Index()
    {
        return Content(
        "<script> alert('Hi! I am Zain Ul Hassan') </script>"
            );
    }
}

输出将如以下所示显示一个警报

所以,您可以以上述方式使用 ContentResult datatype

EmptyResult

此类型实际上用于返回空内容。但问题是,这种 EmptyResult 类型没有辅助方法。所以我们可以通过创建它的对象来使用它,如下所示

public class HomeController : Controller
{
    public EmptyResult Index()
    {
        return new EmptyResult();
    }
}

但是如果您想使用 ActionResult,那么 MVC 将自动识别它是 EmptyResult 类型。代码如下

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return null;
    }
}

所以,这就是 EmptyResult 类型的使用。

FileResult

FileResult 是一种用于将文件返回到浏览器的类型。此类型的辅助方法是 File,并且有许多重载。因此,如果我们使用以下重载并仅指定文件的 URL 和 MIME(多用途互联网邮件扩展)类型,那么我们应该在浏览器中看到文件的内容。让我们看一个例子。

我们使用的重载是

protected internal FilePathResult File(string fileName, string contentType);

使用 FileResult 类型的 action 方法的代码如下

public class HomeController : Controller
{
    public FileResult Index()
    {
        return File("~/Files/text.txt", "text/plain");
    }
}

该文件包含在项目中,并且 URL 如上所示。输出如下

现在,如果您想以字节数组的形式返回文件,那么您需要使用以下代码

public class HomeController : Controller
{
    public FileResult Index()
    {
        byte[] fileBytes = System.IO.File.ReadAllBytes(Server.MapPath("~/Files/text.txt"));
        return File(fileBytes, "text/plain");
    }
}

输出与上面相同

现在,如果您不想在浏览器中显示文件,而是希望提示下载您的文件,那么您需要使用文件辅助方法的以下重载

protected internal virtual FilePathResult File
(string fileName, string contentType, string fileDownloadName);

使用 FileResult 的 action 代码如下

public class HomeController : Controller
{
    public FileResult Index()
    {
        return File(Url.Content("~/Files/text.txt"), "text/plain", "testFile.txt");
    }
}

输出

因此,这就是 FileResult 在不同场景下的使用。

JsonResult

这是 ActionResult 的派生类型,用于表示 JSON 数据。要查看如何将任何数据 JSON 化,您可以查看下面的代码

public JsonResult Index()
{
    return Json(new { Name = "Zain Ul Hassan", ID = 1 });
}

其输出如下

执行上述代码后,您将收到此错误。现在让我们理解一下问题所在。

如您所知,JSON 包含您编码的宝贵数据,因此 MVC 会严格阻止通过 GET 请求共享信息。事实上,MVC 正在试图阻止您进行 JSON 劫持。

因此,如果您想通过 GET 请求共享信息,那么您必须使用以下代码

public JsonResult Index()
{
    return Json(new { Name = "Zain Ul Hassan", ID = 1 }, JsonRequestBehavior.AllowGet);
}

输出将变为

因此,JsonRequestBehavior.AllowGet 允许 MVC 通过 GET 请求共享信息。但是,当您确定您的 JSON 数据不包含敏感数据时,您应该使用上述功能。

JavaScriptResult

此派生类型用于从控制器返回 JavaScript 代码。当它执行时,我们会看到我们在控制器 action 方法中提到的 JavaScript 代码。有关详细信息,请看一个例子

public JavaScriptResult Index()
{
    return JavaScript("alert('Zain Ul hassan')");
}

名为 IndexView 具有以下代码

<script type="text/javascript" src="@Url.Action("Index")"></script>

输出如下

重定向的结果

此类型的 ActionResult 用于重定向目的,您将在此处看到示例。有 2 种重定向结果

  • RedirectResult
  • 重定向到 Action 结果

重定向结果

如果您使用此类型,它将重定向到您指定的 URL。示例如下

public RedirectResult Index()
{
    return Redirect("https://www.c-sharpcorner.com/members/zain-ul-hassan2");
}

在输出中,将打开指定的 URL,如下所示

RedirectionResult 更适合重定向到实时 URL,也就是说,将其用于重定向到当前应用程序的本地页面不是最佳实践。为此,请使用下面解释的 RedirectionToRouteResult

重定向到路由结果

它负责重定向到应用程序内的操作。它有很多辅助方法,实际上是重载的。我们使用 RedirectToRoute,它会将我们重定向到指定控制器内的操作。让我们看一个例子。

public RedirectToRouteResult Index()
{
    return RedirectToRoute(new { controller = "Student", action = "Name" });
}

我们在 Student 控制器中有 Name action 方法,Name 视图的代码如下

<h2>Redirection Successfull</h2>

所以输出如下

现在,如果您在同一个控制器中,并且不想指定控制器名称,那么更好的选择是 RedirectToAction 辅助方法。请看下面的代码

public class HomeController : Controller
{
    public RedirectToRouteResult Index()
    {
        return RedirectToAction("SecondIndex");
    }
    public ActionResult SecondIndex()
    {
        return View();
    }
}

SecondIndex 的视图代码如下

<h3>This is the SecondIndex of the same controller named as "Home"</h3>

输出如下

正如您所见,辅助方法 RedirectToAction 用于调用当前控制器内的操作,如果 MVC 找不到它,将发生 404 错误。RedirectToAction 有许多重载,您可以指定控制器、操作、路由值等。因此,您必须根据您的场景使用。

状态结果

它的职责是向浏览器发送状态代码。此集合有三种类型,如下所述

  1. HttpStatusCodeResult
  2. HttpUnauthorizedResult
  3. HttpNotFoundResult

HttpStatusCodeResult

此类型用于向浏览器发送 HTTP 状态代码。看它的例子。

public HttpStatusCodeResult Index()
{
    return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
}

输出如下

您可以使用 HttpStatusCodeResult 类型的重载版本显示您自己的消息。

public HttpStatusCodeResult Index()
{
    return new HttpStatusCodeResult(HttpStatusCode.Unauthorized, "Sorry! You don't have access.");
}

输出

这里,HttpStatusCode 来自 System.Net 命名空间。并包含所有 HTTP 状态代码。

如果您不想使用 System.Net 命名空间,那么 HttpStatusCodeResult 有一个重载,其输出与上面相同。请看下面的代码

public HttpStatusCodeResult Index()
{
    return new HttpUnauthorizedResult("Sorry! You don't have access.");
}

输出与上面相同,但代码看起来更具可读性。

HttpNotFoundResult

这也是 HttpStatusCodeResult 的一个重载,但它有一个辅助方法,我们不必创建一个匿名对象。代码如下

public HttpNotFoundResult Index()
{
    return HttpNotFound("Sorry! You don't have access.");
}

输出

摘要

这些是理解 Action Results 的基本核心内容。如果您有任何疑问,请随时在下面的评论中与我联系。另外,请提供反馈,无论是积极的还是消极的——这将帮助我改进我的文章并提高我分享知识的热情。

© . All rights reserved.