zoukankan      html  css  js  c++  java
  • 【MVC】关于Action返回结果类型的事儿(上)

    一、 ASP.NET MVC 1.0 Result 几何?

    Action的返回值类型到底有几个?咱们来数数看。

    ASP.NET MVC 1.0 目前一共提供了以下十几种Action返回结果类型:

    1. ActionResult(base)

    2. ContentResult

    3. EmptyResult

    4. HttpUnauthorizedResult

    5. JavaScriptResult

    6. JsonResult

    7. FileResult (base)

    8. FileContentResult

    9. FilePathResult

    10. FileStreamResult

    11. RedirectResult

    12. RedirectToRouteResult

    13. ViewResultBase (base)

    14. ViewResult

    15. PartialViewResult

    一个列表下来看得人眼花缭乱,因为可用的Result很多,接着再瞧瞧类关系图以佐辨析:

    ttt

    如图中可见,ActionResult可谓人丁兴旺,目前膝下有儿9子(如图中红色所圈的类),ViewResultBase与FileResult又各有子两三口,这些儿孙们各司所长。那么各个 Result 都会干点啥事儿呢?这个问题说来话长,不过根据诸如“虎父无犬子”、“种瓜得瓜,种豆得豆”、“龙生龙,凤生凤,老鼠的孩子打地洞”的俗语,孩子们多少从他爹那儿遗传了点什么,所以要说明它们的才干之前,得先唠叨唠叨一下 ActionResult这个爹,这个爷,因此这事情还是得先从ActionResult说起。

    二、朴实的 ActionResult

    所有的 Result 都派生自 ActionResult抽象类,因此 ActionResult 作为基类提供了最基础的功能,ActionResult 是一个抽象类,其声明如下:

    public abstract class ActionResult {

    public abstract void ExecuteResult(ControllerContext context);

    }

    看看普通人民、相貌平平的ActionResult,ActionResult 是个朴素老百姓,没啥特长,就一个 ExecuteResult() 抽象方法,这个ExecuteResult() 抽象方法还啥都不干,遗传给儿女孙子们让它们去发挥,那么它的责任其实就很明确了,它就是为遗传作准备的,繁殖下一代用的,是只公猪种。因为ActionResult是所有Result的基类,因此你可以在所有的Action上使用它作为返回值类型,而无需动脑筋来明确与返回值相同的类型。

    二、 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>
     

    三、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同时支持当前项目目录标识符 ~ (即应用程序目录)。

    四、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。

    五、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其实是一样的)等等。

    六、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而言不会有什么影响。

    七、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);

                }

            }

    八、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 禁止访问等等。

    九、FileResult

    FileResult是一个抽象类,主要属性包括声明内容类型信息ContentType 及文件名称FileDownloadName,客户端下载工具中将显示此名称(如果有指定,ContentType可指定任意非空字符串),如果不指定文件名,ContentType需要正确指定,否则无法识别待下载的文件类型。

    FileResult 用作其他向客户端上载文件的类的基类。

    十、FilePathResult

    FilePathResult 继承自 FileResult,使用 FilePathResult 类向客户端上载文件只需要给出文件的路径即可。FilePathResult 将调用 Response.TransmitFile() 传输该文件:

    protected override void WriteFile(HttpResponseBase response) {

                response.TransmitFile(FileName);

            }

    十一、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);

    }

    十二、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流数据发送到客户端浏览器上。
  • 相关阅读:
    达到XML简单的动态配置
    初步swift语言学习笔记9(OC与Swift杂)
    【COCOS2DX-对28游戏开发】 Cocos2d-x-3c 道路设计 CocosBase CocosNet CocosWidget
    无法识别的属性“targetFramework”。请注意属性名称区分大小写。
    IIS6.0服务器搭建网站无法访问解决方法
    IIS7授权错误:“无法验证对路径的访问”的解决方法
    如何在IIS6,7中部署ASP.NET网站
    IIS的安装与配置
    VS2010如何生成release文件
    发布网站
  • 原文地址:https://www.cnblogs.com/Alex80/p/11055933.html
Copyright © 2011-2022 走看看