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}"); }