ASP.NET MVC 中的 Action Result





5.00/5 (13投票s)
在本文中,您将学习 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 文件。
步骤如下
- 我将为您提供下载 ILSpy 的直接链接。点击 此处。
- 如果您没有 System.Web.Mvc程序集,则可以点击 此处 下载。
- 下载后,解压 ILSpy 并运行它。
- 点击文件(左上角)。
- 选择“打开”选项,然后打开您下载的程序集。
- 选择后,程序集将在 ILSpy 软件中加载。
- 展开程序集,您将看到 ActionResult,也将其展开,您将看到基类型和派生类型。
- 下面图片显示了 ActionResult的类型

现在您可以看到,ActionResult 是一个基数据类型,其派生类型包括 HttpStatusCodeResult、JavaScriptResult、FileResult、ContentResult、JsonResult、EmptyResult、RedirectResult、RedirectToRouteResult、ViewResult。并且每个数据类型(基类型或派生类型)都应该有一个辅助方法。
当我们进入 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”返回两种不同的类型,分别是 Content 和 View。所以,如果您想返回多种类型,您必须使用基类型 ActionResult。
上述概念也回答了“何时选择基类型 ActionResult 或派生类型?”这个问题。
答案是,为特定结果选择派生类型是一种好习惯,但当您希望 action 方法返回多种类型时,您必须使用基类型 ActionResult。
现在,重要的概念来了,派生类型有三个类别。让我们看一下。

正如您所见,ActionResult 的数据类型有三个类别
- 返回内容的结果
- 重定向的结果
- 状态结果
让我们逐一理解。
返回内容的结果
顾名思义,这些结果用于将内容返回到浏览器。有 7 种内容返回结果
- ViewResult
- PartialViewResult
- ContentResult
- EmptyResult
- FileResult
- JsonResult
- 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')");
}
名为 Index 的 View 具有以下代码
<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 有许多重载,您可以指定控制器、操作、路由值等。因此,您必须根据您的场景使用。
状态结果
它的职责是向浏览器发送状态代码。此集合有三种类型,如下所述
- HttpStatusCodeResult
- HttpUnauthorizedResult
- 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 的基本核心内容。如果您有任何疑问,请随时在下面的评论中与我联系。另外,请提供反馈,无论是积极的还是消极的——这将帮助我改进我的文章并提高我分享知识的热情。

