在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流數據發送到客戶端瀏覽器上。