【MVC】關於Action返回結果類型的事兒(上)

1、 ASP.NET MVC 1.0 Result 幾何?

Action的返回值類型到底有幾個?我們來數數看。javascript

ASP.NET MVC 1.0 目前一共提供瞭如下十幾種Action返回結果類型:html

1. ActionResult(base)java

2. ContentResultjson

3. EmptyResult數組

4. HttpUnauthorizedResult瀏覽器

5. JavaScriptResult安全

6. JsonResult網絡

7. FileResult (base)架構

8. FileContentResultapp

9. FilePathResult

10. FileStreamResult

11. RedirectResult

12. RedirectToRouteResult

13. ViewResultBase (base)

14. ViewResult

15. PartialViewResult

一個列表下來看得人眼花繚亂,由於可用的Result不少,接着再瞧瞧類關係圖以佐辨析:

ttt

 

如圖中可見,ActionResult可謂人丁興旺,目前膝下有兒9子(如圖中紅色所圈的類),ViewResultBase與FileResult又各有子兩三口,這些兒孫們各司所長。那麼各個 Result 都會幹點啥事兒呢?這個問題說來話長,不過根據諸如「虎父無犬子」、「種瓜得瓜,種豆得豆」、「龍生龍,鳳生鳳,老鼠的孩子打地洞」的俗語,孩子們多少從他爹那兒遺傳了點什麼,因此要說明它們的才幹以前,得先嘮叨嘮叨一下 ActionResult這個爹,這個爺,所以這事情仍是得先從ActionResult提及。

 

2、樸實的 ActionResult

全部的 Result 都派生自 ActionResult抽象類,所以 ActionResult 做爲基類提供了最基礎的功能,ActionResult 是一個抽象類,其聲明以下:

public abstract class ActionResult {

public abstract void ExecuteResult(ControllerContext context);

}

看看普通人民、相貌平平的ActionResult,ActionResult 是個樸素老百姓,沒啥特長,就一個 ExecuteResult() 抽象方法,這個ExecuteResult() 抽象方法還啥都不幹,遺傳給兒女孫子們讓它們去發揮,那麼它的責任其實就很明確了,它就是爲遺傳做準備的,繁殖下一代用的,是隻公豬種。由於ActionResult是全部Result的基類,所以你能夠在全部的Action上使用它做爲返回值類型,而無需動腦筋來明確與返回值相同的類型。

 

2、 EmptyResult

EmptyResult 是ActionResult 最沒用的兒子,雖然生兒都想生孫仲謀,但願兒子們都是八斗之才,國家棟梁,惋惜第一胎 EmptyResult 就嚴重破壞了它的夢想,看來也只能痛恨本身種子不夠好。咱來瞧瞧這個沒用的阿斗:

//表示一個啥都不幹的結果,就像 controller action 返回 null

public class EmptyResult : ActionResult {

private static readonly EmptyResult _singleton = new EmptyResult();

internal static EmptyResult Instance {

get {

return _singleton;

            }

        }

public override void ExecuteResult(ControllerContext context) {

        }

    }

EmptyResult 遺傳並實現了ActionResult的ExecuteResult()方法,同時也遺傳了ActionResult的天真樸實的想法,也想「仍是等下一代吧」,它有點老子的「無爲」味道,因此它的ExecuteResult()方法像足了它的老爹,啥也不幹。

 

EmptyResult 類使用了簡單的單例模式,看來這樣不思進取的兒子,整個家族裏頭生一個就夠糟糕了,用廣東人的話說,生它還不如生塊叉燒肉。

在Action中,若要返回一個空的頁面(不經常使用),則可以下:

public ActionResult Index()

{

return new EmptyResult();

}

執行後頁面將缺省返回一個body爲空的HMTL架構:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head>
<meta content="text/html; charset=gb2312" http-equiv=content-type></head>
<body></body></html>
 

3、RedirectResult

EmptyResult的「無爲」給ActionResult 的打擊着實不小,只好將期待落在其餘孩子身上,RedirectResult雖然不是什麼大才,起碼有一技之長,咱們看看它的 ExecuteResult() 方法:

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

            }

string destinationUrl = UrlHelper.Content(Url, context.HttpContext);

            context.HttpContext.Response.Redirect(destinationUrl, false /* endResponse */);

        }

 

RedirectResult用於執行轉移。事實上 RedirectResult 最終調用了 Response.Redirect() 進行轉移,因此您可使用RedirectResult跳轉到任意的包括當前項目或網絡上的Url,例如:http://www.cnblogs.com,對於當前項目的路徑,由於使用了UrlHelper.Content() 方法獲取目標路徑,因此RedirectResult傳遞的Url同時支持當前項目目錄標識符 ~ (即應用程序目錄)。

 

4、RedirectToRouteResult

RedirectToRouteResult對於RedirectResult而言,其做用有所侷限,僅能轉移到路由(路由匹配的結果最終是一條相對當前項目的Url,例如: /Home/Index ),總的來講與RedirectResult的最終做用是同樣的,都是執行轉移。RedirectResult較爲直接地轉移到任意指定的Url,而RedirectToRouteResult則轉移到指定的路由(路由匹配所得結果最終也是一個的Url):

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

            }

string destinationUrl = UrlHelper.GenerateUrl(RouteName, null /* actionName */, null /* controllerName */, RouteValues, Routes, context.RequestContext, false /* includeImplicitMvcValues */);

if (String.IsNullOrEmpty(destinationUrl)) {

throw new InvalidOperationException(MvcResources.ActionRedirectResult_NoRouteMatched);

            }

            context.HttpContext.Response.Redirect(destinationUrl, false /* endResponse */);

        }

RedirectToRouteResult先經過調用UrlHelper.GenerateUrl()來得到路由匹配所得的最終Url,接着的執行轉移過程與RedirectResult相同。

路由配置的過程在Global.asax文件中進行,在以MVC模板方式建立的MVC項目中都帶有此文件,可在文件中的MvcApplication類的 RegisterRoutes()方法中進行配置路由,該方法缺省的內容以下:

public static void RegisterRoutes( RouteCollection routes )

        {

            routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" );

            routes.MapRoute(

"Default",                                              // Route name

"{controller}/{action}/{id}",                           // URL with parameters

new { controller = "Home", action = "Index", id = "" } // Parameter defaults

            );

        }

RedirectToRouteResult 可跳轉至任何一條匹配的路由規則。是以利用路由轉移能夠跳轉到其餘控制器的 Action。

 

5、ContentResult

ContentResult用於將字符串直接向客戶端輸出。ContentResult的ExecuteResult方法其實是調用了 Response.Write( string… ),輸入並沒有特別之處,可是在 ASP 時代,這個Response.Write() 倒是能夠縱橫頁面。從輸出一個簡單的字符串到整個頁面,Response.Write()都能勝任,因此ContentResult顯得特別強大:

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

            }

HttpResponseBase response = context.HttpContext.Response;

if (!String.IsNullOrEmpty(ContentType)) {

                response.ContentType = ContentType;

            }

if (ContentEncoding != null) {

                response.ContentEncoding = ContentEncoding;

            }

if (Content != null) {

                response.Write(Content);

            }

        }

若沒有提供任何輸出的內容,ContentResult呈現的結果與EmptyResult 是同樣的,都是輸出最基本的<body>標記內容爲空的HTML,若內容不爲空,則直接輸出這些內容(再也不輸出其餘任何 HTML 代碼),例如:

public ActionResult Index()

{

return Content( "a" );

}

其頁面的HTML代碼也將只有一個字符 a,要補全全部基本標記須要在字符串中編寫,例如:

public ActionResult Index()

        {

return Content( "<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN"">" +

"<html>" +

"<head><meta content=""text/html; charset=gb2312"" http-equiv=content-type></head>" +

"<body>" +

"abc" +

"</body>" +

"</html>"

                        );

        }

固然不建議使用此方法來輸出頁面標記,ContentResult 用在Ajax中頗爲合適,由於只要內容不爲空,輸出的字符串與傳送到客戶端的內容一致,沒有額外的附加內容。

事實上從ContentResult咱們能夠看到一個ActionResult其實並沒有特別,從前面幾個Result 來看,其實不過是Response.Redirect或Response.Write,此外還能夠利用二進制流Response.OutputStream.Write向客戶端上載文件……據此咱們因此拓展編寫更多針對實際意義的Result。例如 XmlResult(文件)、RssResult(跟XmlResult實際上是同樣的)等等。

 

6、JsonResult

JsonResult首先將指定的對象序列化爲Json字符串,而後將字符串寫入到HTTP輸出流。撇開對象序列化爲Json字符串這一過程,實際上與ContentResult實際上是同樣的,由於JsonResult與ContentResult都是調用Response.Write()向HTTP輸出流寫入一些內容。因此對此再也不贅述:

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

            }

HttpResponseBase response = context.HttpContext.Response;

if (!String.IsNullOrEmpty(ContentType)) {

                response.ContentType = ContentType;

            }

else {

                response.ContentType = "application/json";

            }

if (ContentEncoding != null) {

                response.ContentEncoding = ContentEncoding;

            }

if (Data != null) {

// The JavaScriptSerializer type was marked as obsolete prior to .NET Framework 3.5 SP1

#pragma warning disable 0618

JavaScriptSerializer serializer = new JavaScriptSerializer();

                response.Write(serializer.Serialize(Data));

#pragma warning restore 0618

            }

        }

有個地方想嘮叨兩句,在代碼中的:

response.ContentType = "application/json";

若要直接向頁面輸出的話須要更改成文本類型,例如 text/html,不然你要以文件形式下載JsonResult的結果內容。不過這對於將Json用於Ajax而言不會有什麼影響。

 

7、JavaScriptResult

道與 JsonResult、ContentResult相同。因此也不贅述,徒費脣舌:

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

            }

HttpResponseBase response = context.HttpContext.Response;

            response.ContentType = "application/x-javascript";

if (Script != null) {

                response.Write(Script);

            }

        }

8、HttpUnauthorizedResult

HttpUnauthorizeResult 設置客戶端錯誤代號爲 401,即未經受權瀏覽狀態,若設置了Form驗證而且客戶端沒有任何身份票據,那麼將轉跳到指定的頁面(例如登錄頁):

public override void ExecuteResult(ControllerContext context) {

if (context == null) {

throw new ArgumentNullException("context");

            }

// 401 is the HTTP status code for unauthorized access - setting this

// will cause the active authentication module to execute its default

// unauthorized handler

            context.HttpContext.Response.StatusCode = 401;

        }

能夠學習HttpUnauthorizeResult來編寫更多同類的返回結果,例如設置 Response.StatusCode = 404,這個是常見的「頁面未找到」錯誤,403 禁止訪問等等。

 

9、FileResult

FileResult是一個抽象類,主要屬性包括聲明內容類型信息ContentType 及文件名稱FileDownloadName,客戶端下載工具中將顯示此名稱(若是有指定,ContentType可指定任意非空字符串),若是不指定文件名,ContentType須要正確指定,不然沒法識別待下載的文件類型。

FileResult 用做其餘向客戶端上載文件的類的基類。

 

10、FilePathResult

FilePathResult 繼承自 FileResult,使用 FilePathResult 類向客戶端上載文件只須要給出文件的路徑便可。FilePathResult 將調用 Response.TransmitFile() 傳輸該文件:

protected override void WriteFile(HttpResponseBase response) {

            response.TransmitFile(FileName);

        }

 

11、FileContentResult

FileContentResult繼承自 FileResult。

FileContentResult 將指定的字節內容寫入二進制流(客戶端將以文件形式下載),對比 FilePathResult 所不一樣的是 FilePathResult是給出文件路徑,而後將整份文件上載給客戶,而 FileContentResult 則能夠傳輸某一個字節數組,例如:

public ActionResult Index()

{

return File( System.Text.Encoding.UTF8.GetBytes( "你好嗎" ), "unknown", "t.txt" );

}

FileContentResult 使用 Response.OutputStream.Write 輸出內容:

protected override void WriteFile(HttpResponseBase response) {

            response.OutputStream.Write(FileContents, 0, FileContents.Length);

}

 

12、FileStreamResult

FileStreamResult 繼承自 FileResult。

FileStreamResult 向指定文件流讀取數據,其餘的內容與FileContentResult道同。請參考FileContentResult。

 

代碼 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 1 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

using System.IO;

namespace MVC.Controllers
{
/// <summary>
/// Controller 類必須以字符串 "Controller" 作類名稱的結尾,字符串 Controller 以前的字符串爲 Controller 的名稱,類中的方法名爲 Action 的名稱
/// </summary>
public class ControllerDemoController : Controller
{
// [NonAction] - 當前方法僅爲普通方法,不解析爲 Action
// [AcceptVerbs(HttpVerbs.Post)] - 聲明 Action 所對應的 http 方法

/// <summary>
/// Action 能夠沒有返回值
/// </summary>
public void Void()
{
Response.Write(string.Format("<span style='color: red'>{0}</span>", "void"));
}

/// <summary>
/// 若是 Action 要有返回值的話,其類型必須是 ActionResult
/// EmptyResult - 空結果
/// </summary>
public ActionResult EmptyResult()
{
Response.Write(string.Format("<span style='color: red'>{0}</span>", "EmptyResult"));
return new EmptyResult();
}

/// <summary>
/// Controller.Redirect() - 轉向一個指定的 url 地址
/// 返回類型爲 RedirectResult
/// </summary>
public ActionResult RedirectResult()
{
return base.Redirect("~/ControllerDemo/ContentResult");
}

/// <summary>
/// Controller.RedirectToAction() - 轉向到指定的 Action
/// 返回類型爲 RedirectToRouteResult
/// </summary>
public ActionResult RedirectToRouteResult()
{
return base.RedirectToAction("ContentResult");
}

/// <summary>
/// Controller.Json() - 將指定的對象以 JSON 格式輸出出來
/// 返回類型爲 JsonResult
/// </summary>
public ActionResult JsonResult(string name)
{
System.Threading.Thread.Sleep(1000);

var jsonObj = new { Name = name, Age = new Random().Next(20, 31) };
return base.Json(jsonObj);
}

/// <summary>
/// Controller.JavaScript() - 輸出一段指定的 JavaScript 腳本
/// 返回類型爲 JavaScriptResult
/// </summary>
public ActionResult JavaScriptResult()
{
return base.JavaScript("alert('JavaScriptResult')");
}

/// <summary>
/// Controller.Content() - 輸出一段指定的內容
/// 返回類型爲 ContentResult
/// </summary>
public ActionResult ContentResult()
{
string contentString = string.Format("<span style='color: red'>{0}</span>", "ContentResult");
return base.Content(contentString);
}

/// <summary>
/// Controller.File() - 輸出一個文件(字節數組)
/// 返回類型爲 FileContentResult
/// </summary>
public ActionResult FileContentResult()
{
FileStream fs = new FileStream(Request.PhysicalApplicationPath + "Content/loading.gif", FileMode.Open);
int length = (int)fs.Length;
byte[] buffer = new byte[length];
fs.Read(buffer, 0, length);
fs.Close();

return base.File(buffer, "image/gif");
}

// <summary>
/// Controller.File() - 輸出一個文件(文件地址)
/// 返回類型爲 FileContentResult
/// </summary>
public ActionResult FilePathResult()
{
var path = Request.PhysicalApplicationPath + "Content/loading.gif";
return base.File(path, "image/gif");
}

// <summary>
/// Controller.File() - 輸出一個文件(文件流)
/// 返回類型爲 FileContentResult
/// </summary>
public ActionResult FileStreamResult()
{
FileStream fs = new FileStream(Request.PhysicalApplicationPath + "Content/loading.gif", FileMode.Open);

return base.File(fs, @"image/gif");
}

/// <summary>
/// HttpUnauthorizedResult - 響應給客戶端錯誤代碼 401(未經受權瀏覽狀態),若是程序啓用了 Forms 驗證,而且客戶端沒有任何身份票據,則會跳轉到指定的登陸頁
/// </summary>
public ActionResult HttpUnauthorizedResult()
{
return new HttpUnauthorizedResult();
}

/// <summary>
/// Controller.PartialView() - 尋找 View ,即 .ascx 文件
/// 返回類型爲 PartialViewResult
/// </summary>
public ActionResult PartialViewResult()
{
return base.PartialView();
}

/// <summary>
/// Controller.View() - 尋找 View ,即 .aspx 文件
/// 返回類型爲 ViewResult
/// </summary>
public ActionResult ViewResult()
{
// 若是沒有指定 View 名稱,則尋找與 Action 名稱相同的 View
return base.View();
}

/// <summary>
/// 用於演示處理 JSON 的
/// </summary>
public ActionResult JsonDemo()
{
return View();
}

/// <summary>
/// 用於演示上傳文件的
/// </summary>
public ActionResult UploadDemo()
{
return View();
}

/// <summary>
/// 用於演示 Get 方式調用 Action
/// id 是根據路由過來的;param1和param2是根據參數過來的
/// </summary>
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetDemo(int id, string param1, string param2)
{
ViewData["ID"] = id;
ViewData["Param1"] = param1;
ViewData["Param2"] = param2;

return View();
}

/// <summary>
/// 用於演示 Post 方式調用 Action
/// </summary>
/// <remarks>
/// 能夠爲參數添加聲明,如:[Bind(Include = "xxx")] - 只綁定指定的屬性(參數),多個用逗號隔開
/// [Bind(Exclude = "xxx")] - 不綁定指定的屬性(參數),多個用逗號隔開
/// [Bind] 聲明一樣能夠做用於 class 上
/// </remarks>
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult PostDemo(FormCollection fc)
{
ViewData["Param1"] = fc["param1"];
ViewData["Param2"] = fc["param2"];

// 也能夠用 Request.Form 方式獲取 post 過來的參數

// Request.Form 內的參數也會映射到同名參數。例如,也可用以下方式獲取參數
// public ActionResult PostDemo(string param1, string param2)

return View("GetDemo");
}

/// <summary>
/// 處理上傳文件的 Action
/// </summary>
/// <param name="file1">與傳過來的 file 類型的 input 的 name 相對應</param>
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UploadFile(HttpPostedFileBase file1)
{
// Request.Files - 獲取須要上傳的文件。固然,其也會自動映射到同名參數
// HttpPostedFileBase hpfb = Request.Files[0] as HttpPostedFileBase;

string targetPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "Upload", Path.GetFileName(file1.FileName));
file1.SaveAs(targetPath);

return View("UploadDemo");
}
}
}

 

 

在ASP.NET Core MVC中,咱們有時候須要在Controller的Action中直接輸出數據到Response.Body這個Stream流中,例如若是咱們要輸出一個很大的文件到客戶端瀏覽器讓用戶下載,那麼在Controller的Action中用Response.Body這個Stream流,來逐步發送文件數據到客戶端瀏覽器是最好的辦法。

 

可是我今天在ASP.NET Core MVC的Controller的Action中使用Response.Body輸出數據到客戶端瀏覽器的時候遇到了個問題,咱們來看看下面這個Controller:

複製代碼
using Microsoft.AspNetCore.Mvc;
using System.IO;

namespace AspNetCoreActionFilter.Controllers
{
    public class HomeController : Controller
    {
        /// <summary>
        /// 顯示一個網頁供測試
        /// </summary>
        public IActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 調用此Action,採用Response.Body的Stream流發送字符串數據到客戶端瀏覽器
        /// </summary>
        /// <returns>返回一個IActionResult對象</returns>
        public IActionResult WriteResponseWithReturn()
        {
            Response.ContentType = "text/html";

            using (StreamWriter sw = new StreamWriter(Response.Body))
            {
                sw.Write("Write a string to response in WriteResponseWithReturn!");
            }

            return null;
        }
    }
}
複製代碼

能夠看到這個HomeController很是簡單就兩個Action:

  • Index這個Action用於顯示一個簡單的網頁作測試
  • WriteResponseWithReturn這個Action採用Response.Body的Stream流發送字符串數據到客戶端瀏覽器,其返回類型爲IActionResult,可是咱們實際上返回的是一個null

 

結果我在瀏覽器(IE瀏覽器)上輸入Url地址"Home/WriteResponseWithReturn"返回的結果以下:

能夠看到頁面報錯了,可是返回的Http狀態碼是200,表示Http響應又是成功的。。。總之來講HomeController的WriteResponseWithReturn這個Action執行出問題了,咱們輸出到Response.Body的Stream流中的文字,沒能正確發送到客戶端瀏覽器。

 

接着我修改了下HomeController的WriteResponseWithReturn這個Action,讓其返回一個EmptyResult對象,以下所示:

複製代碼
using Microsoft.AspNetCore.Mvc;
using System.IO;

namespace AspNetCoreActionFilter.Controllers
{
    public class HomeController : Controller
    {
        /// <summary>
        /// 顯示一個網頁供測試
        /// </summary>
        public IActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 調用此Action,採用Response.Body的Stream流發送字符串數據到客戶端瀏覽器
        /// </summary>
        /// <returns>返回一個IActionResult對象</returns>
        public IActionResult WriteResponseWithReturn()
        {
            Response.ContentType = "text/html";

            using (StreamWriter sw = new StreamWriter(Response.Body))
            {
                sw.Write("Write a string to response in WriteResponseWithReturn!");
            }

            return new EmptyResult();
        }
    }
}
複製代碼

再嘗試在瀏覽器上輸入Url地址"Home/WriteResponseWithReturn",此次返回的結果以下:

此次瀏覽器成功將咱們輸出到Response.Body的Stream流中的文字顯示出來了,並且返回的Http狀態碼也是200

 

接着我在HomeController中又定義了一個Action叫WriteResponseWithoutReturn,仍是輸出一段字符串數據到Response.Body的Stream流中,發送給客戶端瀏覽器,可是WriteResponseWithoutReturn這個Action方法沒有返回類型,返回類型爲void,以下所示:

複製代碼
using Microsoft.AspNetCore.Mvc;
using System.IO;

namespace AspNetCoreActionFilter.Controllers
{
    public class HomeController : Controller
    {
        /// <summary>
        /// 顯示一個網頁供測試
        /// </summary>
        public IActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 調用此Action,採用Response.Body的Stream流發送字符串數據到客戶端瀏覽器
        /// </summary>
        /// <returns>返回一個IActionResult對象</returns>
        public IActionResult WriteResponseWithReturn()
        {
            Response.ContentType = "text/html";

            using (StreamWriter sw = new StreamWriter(Response.Body))
            {
                sw.Write("Write a string to response in WriteResponseWithReturn!");
            }

            return new EmptyResult();
        }

        /// <summary>
        /// 調用此Action,採用Response.Body的Stream流發送字符串數據到客戶端瀏覽器
        /// </summary>
        public void WriteResponseWithoutReturn()
        {
            Response.ContentType = "text/html";

            using (StreamWriter sw = new StreamWriter(Response.Body))
            {
                sw.Write("Write a string to response in WriteResponseWithoutReturn!");
            }
        }
    }
}
複製代碼

而後我在客戶端瀏覽器上輸入Url地址"Home/WriteResponseWithoutReturn"來訪問咱們新加的這個Action方法,此次返回的結果以下:

能夠看到若是Action返回的類型是void,那麼輸出到Response.Body的Stream流中的數據也能夠成功發送到客戶端瀏覽器。

 

小結:

因此當咱們在ASP.NET Core MVC中Controller的Action中,要用Response.Body的Stream流輸出數據到客戶端時,有兩種辦法能夠確保數據能夠成功發送到客戶端:

  • 若是基於某種緣由必需要將Action方法的返回類型定義爲非void類型(例如咱們本例中的WriteResponseWithReturn方法返回的就是IActionResult類型),切記不要返回null,要返回一個EmptyResult對象才能保證Response.Body的Stream流數據能成功發送到客戶端瀏覽器上。
  • 還有個辦法就是將Action方法的返回類型定義爲void(例如咱們本例中的WriteResponseWithoutReturn方法),這樣也能夠安全地將Response.Body的Stream流數據發送到客戶端瀏覽器上。
相關文章
相關標籤/搜索