测试环境:netcore3.1
前置条件
首先,我们需要一个测试用的标准结果集
PersonJsonResult
public class PersonJsonResult<T>
{
//错误状态标识
public static string STATUS_ERROR = "0";
//正确状态标识
public static string STATUS_SUCCESS = "1";
private string status;//状态
private string message;//消息
private T data;//数据
public string Status { get => status; set => status = value; }
public string Message { get => message; set => message = value; }
public T Data { get => data; set => data = value; }
//无参构造器
public PersonJsonResult()
{
}
//两参构造器
public PersonJsonResult(string status, string message)
{
this.status = status;
this.message = message;
}
//全参构造器
public PersonJsonResult(string status, string message, T data)
{
this.status = status;
this.message = message;
this.data = data;
}
}
方法一:使用JsonResult
该操作用于定义一个方法级返回
HomeController
[Route("Home")]
public class HomeController : Controller
{
[Route("")]
[Route("Index")]
[HttpGet]
public JsonResult Index()
{
PersonJsonResult<String> result = new PersonJsonResult<String>(PersonJsonResult<String>.STATUS_SUCCESS,"message","data");
return Json(result);
}
}
访问接口出现如下结果即证明成功:
原理:
在JsonResult源码中,可以看到开发人员的注释,在该类的摘要中指明了其作用,同时我们可以知晓JsonResult继承自ActionResult,JSON数据的返回被当做一种特殊的返回行为来看待
// 摘要:
// 将给定对象格式化为JSON的操作结果。
public class JsonResult : ActionResult, IActionResult, IStatusCodeActionResult
{
........
}
且因为JsonResult是一个返回类型,我们不能闷头直接把PersonJsonResult当做结果返回,因此需要格式化一下,而这里充当格式化行为执行人的就是JSON方法,在源码中我们可以看到,该方法是抽象类Controller中的一个内置,[NonAction]注明其为纯粹操作方法。
public abstract class Controller : ControllerBase, IActionFilter, IFilterMetadata, IAsyncActionFilter, IDisposable
{
//
// 摘要:
// 创建一个Microsoft.AspNetCore.Mvc.JsonResult对象,将指定的数据对象序列化为JSON。
//
//
// 参数:
// data:
// 待序列化的对象
//
// 返回结果:
// 创建 Microsoft.AspNetCore.Mvc.JsonResult对象
// 将指定的数据序列化成JSON做为响应。
[NonAction]
public virtual JsonResult Json(object data);
}
方法二:使用[ApiController]
ApiController,人称小“@RestController”,本着好的设计就该互相抄的原则,此注解的出现也是理所当然的事情,该注解用于定义一个类级别的Api
ApiController
[ApiController]
[Route("Api")]
public class ApiController : Controller
{
//该注解将全部方法都定义为了Json返回
//因此可以直接把我们的PersonJsonResult直接充当返回类型
[Route("get")]
public PersonJsonResult<String> getPersonJsonResult() {
return new PersonJsonResult<String>(PersonJsonResult<String>.STATUS_SUCCESS, "message");
}
}
访问接口测试:
原理:
我们来到ApiController的源码,观察其摘要,我们便了解到该注解的官方定义,就是用来册封API,改善开发人员体验的。
//
// 摘要:
// 声明一个类和其所有的派生类都用于服务HTTP API响应。
// 配置基于此属性装饰的控制器旨在改善开发人员构建API的体验。
// 在程序集中修饰时,程序集中的所有控制器都将被视为具有API行为的控制器。
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ApiControllerAttribute : ControllerAttribute, IFilterMetadata, IApiBehaviorMetadata
{
public ApiControllerAttribute();
}
接着我们又看到ApiControllerAttribute继承自ControllerAttribute,进入ControllerAttribute源码,我们知道ApiControllerAttribute其实是ControllerAttribute的一种,继承自ControllerAttribute从而让他拥有了Controller的属性,另外该摘要还特别声明了将NonControllerAttribute所注释的对象进行排外。
//
// 摘要:
// 系统默认的控制器发现机制会将应用此属性的类型和任何派生类型视为控制器
// 除非 Microsoft.AspNetCore.Mvc.NonControllerAttribute 被应用
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ControllerAttribute : Attribute
{
public ControllerAttribute();
}
于是又顺理成章的点击去看Attribute,我们便知道这东西已经是一个基类了,用于标识自定义属性,说明我们已经深入到地基了。
//
// 摘要:
// 表示自定义属性的基类。
[AttributeUsageAttribute(AttributeTargets.All, Inherited = true, AllowMultiple = false)]
public abstract class Attribute
{
}
然后我们回过头去,已知ApiControllerAttribute除去继承了ControllerAttribute之外,还实现了另外两个接口:IFilterMetadata 和 IApiBehaviorMetadata。
public class ApiControllerAttribute : ControllerAttribute, IFilterMetadata, IApiBehaviorMetadata
{
public ApiControllerAttribute();
}
先进入第一个接口:IFilterMetadata ,观察其摘要,我们意识到该接口用于处理mvc请求管道中的流,算是一个小过滤器,那这一样一来我们就能清楚被ApiController定义的控制器如何不跟普通控制器一起混淆了,因为它被过滤器拦截了,然后才去进行了一些封装Json之类的操作。
//
// 摘要:
// MVC请求管道中处理的过滤器的标记接口。
public interface IFilterMetadata
{
}
接着是第二个接口:IApiBehaviorMetadata,即IApiBehaviorMetadata是IFilterMetadata的一种,从其实现了IFilterMetadata接口这一点上就可以看出,并且该接口还回过头去强调了一番使用ApiControllerAttribute可以更好的构筑API,而这个接口,比起前面笼统的过滤器(Filter)接口,它更强调一种行为(Behavior),什么Behavior?ApiBehavior!如何实现这个行为?ApiControllerAttribute属性!如此,二者一前一后打配合,从而将我们的控制器设定为了一个纯API返回的类。
//
// 摘要:
// 一个Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata,用于指明一个类和其所有派生类都用于服务HTTP API响应。
// 使用此属性装饰的控制器(尤指Microsoft.AspNetCore.Mvc.ApiControllerAttribute)
// 配置该属性旨在改善开发人员构建API的体验。
public interface IApiBehaviorMetadata : IFilterMetadata
{
}