ASP.NET Core: 二十. Action的多种数据返回格式处理机制(四)

简介: 上一章讲了系统如何将客户端提交的请求数据格式化处理成我们想要的格式并绑定到对应的参数,本章讲一下它的“逆过程”,如何将请求结果按照客户端想要的格式返回去。

在OnResultExecuting中可以通过设置context.Cancel = true;取消后面的工作的执行。

    public void OnResultExecuting(ResultExecutingContext context)
    {
        //用于验证的代码略
        context.Cancel = true;
        Debug.WriteLine("HomeController=======>OnResultExecuting");
    }

再看输出结果就至于的输出了

HomeController=======>OnResultExecuting

同时返回结果也不再是JSON值了,返回结果以及Content-Type全部为空。所以这样设置后,IActionResult以及OnResultExecuted都不再被执行。


在这里除了可以做一些IActionResult执行之前的验证,还可以对HttpContext.Response做一些简单的操作,例如添加个Header值:

public void OnResultExecuting(ResultExecutingContext context)
{
    context.HttpContext.Response.Headers.Add("version", "1.2");
    Debug.WriteLine("HomeController=======>OnResultExecuting");
}

除了正常返回JSON结果外,Header中会出现新添加的version

Content-Type: application/json; charset=utf-8
version: 1.2

再看一下OnResultExecuted方法,它是在IActionResult执行之后执行。因为在这个方法执行的时候,请求结果已经发送给请求的客户端了,所以在这里可以做一些日志类的操作。举个例子,假如在这个方法中产生了异常:

  public void OnResultExecuted(ResultExecutedContext context)
  {
      throw new Exception("exception");
      Debug.WriteLine("HomeController=======>OnResultExecuted");
  }

请求结果依然会返回正常的JSON,但从输出结果中看到是不一样的

HomeController=======>OnResultExecuting
……
System.Exception: exception

发生异常,后面的Debug输出没有 执行。但却将正确的结果返回给了客户端。

Result Filter介绍完了,看一下核心的IActionResult的执行。

4. IActionResult的执行

在ResourceInvoker的case State.ResultInside阶段会调用IActionResult的执行方法InvokeResultAsync。该方法中参数IActionResult result会被调用ExecuteResultAsync方法执行。

protected virtual async Task InvokeResultAsync(IActionResult result)
{
    var actionContext = _actionContext;
    _diagnosticSource.BeforeActionResult(actionContext, result);
    _logger.BeforeExecutingActionResult(result);
    try
    {
        await result.ExecuteResultAsync(actionContext);
    }
    finally
    {
        _diagnosticSource.AfterActionResult(actionContext, result);
        _logger.AfterExecutingActionResult(result);
    }
}

由图 2可知,虽然所有类型的Action的结果都被转换成了IActionResult,但它们本质上还是有区别的。所以这个IActionResult类型的参数result实际上可能是JsonResult、ViewResult、EmptyResult等具体类型。下面依然以第一节JSON的例子为例来看,它返回了一个JsonResult。在这里就会调用JsonResult的ExecuteResultAsync方法,JsonResult的代码如下:

public class JsonResult : ActionResult, IStatusCodeActionResult
{
   //部分代码略
    public override Task ExecuteResultAsync(ActionContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }
        var services = context.HttpContext.RequestServices;
        var executor = services.GetRequiredService<JsonResultExecutor>();
        return executor.ExecuteAsync(context, this);
    }
}

在它的ExecuteResultAsync方法中会获取依赖注入中设置的JsonResultExecutor,由JsonResultExecutor来调用ExecuteAsync方法执行后面的工作。JsonResultExecutor的代码如下:


public class JsonResultExecutor
{
//部分代码略
    public virtual async Task ExecuteAsync(ActionContext context, JsonResult result)
    {
        //验证代码略
        var response = context.HttpContext.Response;
  ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
            result.ContentType,
            response.ContentType,
            DefaultContentType,
            out var resolvedContentType,
            out var resolvedContentTypeEncoding);
        response.ContentType = resolvedContentType;
        if (result.StatusCode != null)
        {
            response.StatusCode = result.StatusCode.Value;
        }
        var serializerSettings = result.SerializerSettings ?? Options.SerializerSettings;
        Logger.JsonResultExecuting(result.Value);
        using (var writer = WriterFactory.CreateWriter(response.Body, resolvedContentTypeEncoding))
        {
            using (var jsonWriter = new JsonTextWriter(writer))
            {
                jsonWriter.ArrayPool = _charPool;
                jsonWriter.CloseOutput = false;
                jsonWriter.AutoCompleteOnClose = false;
                var jsonSerializer = JsonSerializer.Create(serializerSettings);
                jsonSerializer.Serialize(jsonWriter, result.Value);
            }
            // Perf: call FlushAsync to call WriteAsync on the stream with any content left in the TextWriter's
            // buffers. This is better than just letting dispose handle it (which would result in a synchronous write).
            await writer.FlushAsync();
        }
    }
}

JsonResultExecutor的ExecuteAsync方法的作用就是将JsonResult中的值转换成JSON串并写入context.HttpContext.Response. Body中。至此JsonResult执行完毕。


ViewResult会有对应的ViewExecutor来执行,会通过相应的规则生成一个 Html页面。


而EmptyResult的ExecuteResult方法为空,所以不会返回任何内容。

    public class EmptyResult : ActionResult
    {
        /// <inheritdoc />
        public override void ExecuteResult(ActionContext context)
        {
        }
    }

5. 下集预告

对于以上几种类型返回结果的格式是固定的,JsonResult就会返回JSON格式,ViewResult就会返回Html格式。


但是从第一节的例子可知,string类型会返回string类型的字符串,而Book这样的实体类型却会返回JSON。


由图 2可知这两种类型在执行完毕后,都被封装成了ObjectResult,那么ObjectResult在执行的时候又是如何被转换成string和JSON两种格式的呢?


下一章继续这个话题。


目录
相关文章
|
15天前
|
数据可视化 网络协议 C#
C#/.NET/.NET Core优秀项目和框架2024年3月简报
公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。
|
1月前
mvc.net分页查询案例——DLL数据访问层(HouseDLL.cs)
mvc.net分页查询案例——DLL数据访问层(HouseDLL.cs)
8 0
|
3月前
|
开发框架 前端开发 JavaScript
盘点72个ASP.NET Core源码Net爱好者不容错过
盘点72个ASP.NET Core源码Net爱好者不容错过
71 0
|
3月前
|
开发框架 .NET
ASP.NET Core NET7 增加session的方法
ASP.NET Core NET7 增加session的方法
37 0
|
1月前
|
SQL 数据库
使用ADO.NET查询和操作数据
使用ADO.NET查询和操作数据
9 0
|
1月前
|
开发框架 人工智能 .NET
C#/.NET/.NET Core拾遗补漏合集(持续更新)
C#/.NET/.NET Core拾遗补漏合集(持续更新)
|
1月前
|
开发框架 中间件 .NET
C# .NET面试系列七:ASP.NET Core
## 第一部分:ASP.NET Core #### 1. 如何在 controller 中注入 service? 在.NET中,在ASP.NET Core应用程序中的Controller中注入服务通常使用<u>依赖注入(Dependency Injection)</u>来实现。以下是一些步骤,说明如何在Controller中注入服务: 1、创建服务 首先,确保你已经在应用程序中注册了服务。这通常在Startup.cs文件的ConfigureServices方法中完成。例如: ```c# services.AddScoped<IMyService, MyService>(); //
61 0
|
2月前
|
开发框架 前端开发 .NET
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
为了便于大家查找,特将之前开发的.Net Core相关的五大案例整理成文,共计440页,32w字,免费提供给大家,文章底部有PDF下载链接。
33 1
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
|
2月前
|
算法 BI API
C#/.NET/.NET Core优秀项目和框架2024年1月简报
C#/.NET/.NET Core优秀项目和框架2024年1月简报
|
2月前
|
SQL 开发框架 .NET
ASP.NET WEB+EntityFramework数据持久化——考核练习库——1、用户管理系统(考点:查询列表、增加、删除)
ASP.NET WEB+EntityFramework数据持久化——考核练习库——1、用户管理系统(考点:查询列表、增加、删除)
67 0