Web API为JSON和XML提供媒体类型格式化程序。框架默认将这些格式化程序插入管道中。客户端能够在HTTP请求的Accept标头中请求JSON或XML.html
格式化数据这个东西,其实没有什么最好的数据,要看各类场景,最适合才是最好的,不是说json就比xml好,容易解析什么的等。git
废话很少说了,概念的东西你们一百度一大堆。开始咱们的正文吧,固然首先咱们仍是要建立一个WebAPI项目,不会建立请返回第一章:如何建立简单的WebAPI项目github
首先咱们最熟悉的就是特定类型了,好比stting或自定义对象类型等。就例如模版控制器的就是返回一个字符串数组类型:web
[HttpGet] public ActionResult<IEnumerable<string>> Get() { return new string[] { "value1", "value2" }; }
这种的示例没有已知条件,直接返回特定类型便可了 ,可是有些操做咱们须要考虑已知的条件,这时候会返回多个返回结果。根据不一样的条件返回对应结果,下面咱们来看一下IActionResult 类型。json
在多种状况条件返回多个不一样结果时, 要支持此类操做,必须使用 IActionResult 或 ActionResult<T>。ActionResult类型表示多种的HTTP状态码。属于此类别的一些常见返回类型包括:api
BadRequestResult (400)数组
NotFoundResult (404) mvc
OkObjectResult (200)app
在返回多个类型的时候咱们如何返回不一样的类型哪,咱们能够借助【ProducesResponseType】特性来帮助咱们实现返回自定义多个类型。下面咱们写个简单的get方法的同步和异步的示例:框架
同步示例:
返回两个状况当id为5我给你正确返回,不是5我就找不到。固然实际状况确定不是这个样子,可是就是打一个找资源的例子,找到就返回,找不到就返回404,。
[HttpGet("{id}")] [ProducesResponseType(200, Type = typeof(Person))] [ProducesResponseType(404)] public IActionResult Get(int id) { if (id == 5) { return Ok(new Person { Id = "001", name = "姓名1", age = 18, Birthday = DateTime.Now, introduce = "介绍001" }); } else { return NotFound(); } }
下面是异步的方法:
[HttpGet("{id}")] [ProducesResponseType(200, Type = typeof(Person))] [ProducesResponseType(400)] public async Task<IActionResult> Get(int id) { if (id == 5) { await Task.Run(()=>System.Threading.Thread.Sleep(1000)); return Ok(new Person { Id = "001", name = "姓名1", age = 18, Birthday = DateTime.Now, introduce = "介绍001" }); } else { return BadRequest(); } }
CreatedAtAction方法:建立一个CreatedAtActionResult对象,该对象生成Status201Created响应;具体想要了解的能够查看官方文档:CreatedAtAction方法介绍
下面咱们看一下请求结果:
id不是5的时候返回找不到:
id为5的时候正常返回我们的对象:
这个类型是从ASP.NET Core 2.1引入的,全部使用前请看下版本哦。它支持返回从 ActionResult 派生的类型或返回特定类型。 ActionResult<T>
经过 IActionResult 类型可提供如下优点:
Type
属性T
和 ActionResult
均转换为 ActionResult<T>
。 将 T
转换为 ObjectResult,也就是将 return new ObjectResult(T);
简化为 return T,什么个意思哪,说白了就是在定义的时候指定了类型直接return就能够了。
NotFound():没有找到,为响应建立的NotFoundResult。
PhysicalFile(string【文件的路径】,string【内容类型】):返回由physicalPath
(Status200OK)指定的文件。
我就写部分经常使用的其余的有兴趣能够去官网了解一下:返回状态相应
咱们都知道WebAPI由于MVC的内置因此默认支持了json,xml和文本格式。那么咱们想使用其余格式怎么办哪,微软老是不会让咱们失望,咱们能够自定义啊。
首先建立自定义格式化程序大体步骤:
CanReadType
/CanWriteType
方法ReadRequestBodyAsync
/WriteResponseBodyAsync
方法从那些类中派生官方给的解释是;
对于文本媒体类型(例如,vCard),从 TextInputFormatter 或 TextOutputFormatter 基类派生。
对于二进制类型,从 InputFormatter 或 OutputFormatter 基类派生。
例如官方示例:
public class VcardOutputFormatter : TextOutputFormatter
在构造函数中,经过添加到 SupportedMediaTypes
和 SupportedEncodings
集合来指定有效的媒体类型和编码。
public VcardOutputFormatter() { SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/vcard")); SupportedEncodings.Add(Encoding.UTF8); SupportedEncodings.Add(Encoding.Unicode); }
经过重写 CanReadType
或 CanWriteType
方法,指定可反序列化为或从其序列化的类型。 例如,可能只能从 Contact
类型建立 vCard 文本,反之亦然。
protected override bool CanWriteType(Type type) { if (typeof(Contact).IsAssignableFrom(type) || typeof(IEnumerable<Contact>).IsAssignableFrom(type)) { return base.CanWriteType(type); } return false; }
CanWriteResult方法不必定必须重写,可是有时候确实必须的,必须重写官方给的解释是;
简单的意思是若是你返回的类型是父类的话,可是实际返回值可能存在子类型的返回且子类型为多个。可是你仅仅但愿处理其中一个子类型的返回。这个时候可使用CanWriteResult提供的上下文来检查对象类型。
实际的反序列化或序列化工做在 ReadRequestBodyAsync
或 WriteResponseBodyAsync
中执行。 如下示例中突出显示的行展现了如何从依赖关系注入容器中获取服务(不能从构造函数参数中获取它们)
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) { IServiceProvider serviceProvider = context.HttpContext.RequestServices; var logger = serviceProvider.GetService(typeof(ILogger<VcardOutputFormatter>)) as ILogger; var response = context.HttpContext.Response; var buffer = new StringBuilder(); if (context.Object is IEnumerable<Contact>) { foreach (Contact contact in context.Object as IEnumerable<Contact>) { FormatVcard(buffer, contact, logger); } } else { var contact = context.Object as Contact; FormatVcard(buffer, contact, logger); } return response.WriteAsync(buffer.ToString()); }
private static void FormatVcard(StringBuilder buffer, Contact contact, ILogger logger) { buffer.AppendLine("BEGIN:VCARD"); buffer.AppendLine("VERSION:2.1"); buffer.AppendFormat($"N:{contact.LastName};{contact.FirstName}\r\n"); buffer.AppendFormat($"FN:{contact.FirstName} {contact.LastName}\r\n"); buffer.AppendFormat($"UID:{contact.ID}\r\n"); buffer.AppendLine("END:VCARD"); logger.LogInformation($"Writing {contact.FirstName} {contact.LastName}"); }