上一节列出了多种不同的Action,它们的处理在这里就不一一讲解了。通过下图 17‑2看一下它们的处理结果:
图 2
这里有void类型没有讲到,它本身没有返回结果,但它会被赋予一个结果EmptyResult,它也是ActionResult的子类。
图 2被两行虚线分隔为三行,第一行基本都介绍过了,第二行是第一行对应的异步方法,上一节介绍常见的返回类的时候说过,这些异步方法的返回结果和对应的同步方法是一样的。不过通过图 2可知,处理它们的XXXResultExecutor方法是不一样的。
第三行的ActionResult<T> 类型是在ASP.NET Core 2.1 引入的,它支持IActionResult的子类也支持类似string和Book这样的特定类型。
public sealed class ActionResult<TValue> : IConvertToActionResult { public ActionResult(TValue value) { if (typeof(IActionResult).IsAssignableFrom(typeof(TValue))) { var error = Resources.FormatInvalidTypeTForActionResultOfT(typeof(TValue), "ActionResult<T>"); throw new ArgumentException(error); } Value = value; } public ActionResult(ActionResult result) { if (typeof(IActionResult).IsAssignableFrom(typeof(TValue))) { var error = Resources.FormatInvalidTypeTForActionResultOfT(typeof(TValue), "ActionResult<T>"); throw new ArgumentException(error); } Result = result ?? throw new ArgumentNullException(nameof(result)); } /// <summary> /// Gets the <see cref="ActionResult"/>. /// </summary> public ActionResult Result { get; } /// <summary> /// Gets the value. /// </summary> public TValue Value { get; } public static implicit operator ActionResult<TValue>(TValue value) { return new ActionResult<TValue>(value); } public static implicit operator ActionResult<TValue>(ActionResult result) { return new ActionResult<TValue>(result); } IActionResult IConvertToActionResult.Convert() { return Result ?? new ObjectResult(Value) { DeclaredType = typeof(TValue), }; } }
TValue不支持IActionResult及其子类。它的值若是IActionResult子类,会被赋值给Result属性,否则会赋值给Value属性。它实现了IConvertToActionResult接口,想到刚讲解string类型被处理的时候用到的Convert方法。当返回结果实现了IConvertToActionResult这个接口的时候,就会调用它的Convert方法进行转换。它的Convert方法就是先判断它的值是否是IActionResult的子类,如果是则返回该值,否则将该值转换为ObjectResult后返回。
所以图 2中ActionResult<T> 类型返回的结果被加上引号的意思就是结果类型可能是直接返回的IActionResult的子类,也有可能是string和Book这样的特定类型被封装后的ObjectResult类型。
3. Result Filter的执行
结果被统一处理为IActionResult后,进入图 1所示的第三部分。这部分的主要内容有两个,分别是Result Filters的执行和IActionResult的执行。Result Filter也有OnResultExecuting和OnResultExecuted两个方法,分别在IActionResult执行的前后执行。
自定义一个MyResultFilterAttribute,代码如下:
public class MyResultFilterAttribute : Attribute, IResultFilter { public void OnResultExecuted(ResultExecutedContext context) { Debug.WriteLine("HomeController=======>OnResultExecuted"); } public void OnResultExecuting(ResultExecutingContext context) { Debug.WriteLine("HomeController=======>OnResultExecuting"); } }
将它注册到第一节JSON的例子中:
1. [MyResultFilter] public JsonResult GetJson() { return new JsonResult(new Book() { Code = "1001", Name = "ASP" }); }
可以看到这样的输出结果:
1.HomeController=======>OnResultExecuting ……Executing JsonResult…… HomeController=======>OnResultExecuted