1.簡單介紹json
ASP.NET Core Web API 是 ASP.NET Core MVC 的一個功能。ASP.NET Core MVC 包含了對 Web API 的支持。能夠構建多種客戶端的 HTTP 服務。ASP.NET Core Web API可用於在 .NET Core 上構建 RESTful 應用程序。api
框架包含對 HTTP 內容協商的支持,內置支持以 JSON 或 XML 格式化的數據。編寫自定義格式化程序已添加對自有格式的支持。瀏覽器
使用連接生成對超媒體的支持。啓用對跨資源共享(CORS)的支持,以便 Web API 能夠在多個 Web應用程序之間共享。app
例如,新建一個 API 項目,默認包含一個 ValuesController:框架
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { // GET api/values [HttpGet] public ActionResult<IEnumerable<string>> Get() { return new string[] { "value1", "value2" }; } // GET api/values/5 [HttpGet("{id}")] public ActionResult<string> Get(int id) { return "value"; } // POST api/values [HttpPost] public void Post([FromBody] string value) { } // PUT api/values/5 [HttpPut("{id}")] public void Put(int id, [FromBody] string value) { } // DELETE api/values/5 [HttpDelete("{id}")] public void Delete(int id) { } }
默認包含了 GET,POST,PUT,DELETE 這幾個 HTTP 請求操做。這裏直接使用特性路由,在控制器上註明 [Route("api/[controller]")]。調試並打開瀏覽器輸入 https://localhost:5000/api/values ,會返回數據。ide
2.自定義格式化(Format)spa
ASP.NET Core MVC內建支持對相應數據的格式,用來修正格式或生成客戶端指定的格式。調試
1.特定格式的操做結果code
某些操做結果的類型是特定的格式,好比 JsonResult 或 ContentResult 。操做能夠老是返回格式爲特定格式的具體結果。好比返回 JsonResult 時將返回 JSON 格式化數據,而無論客戶端要求的是什麼格式。orm
操做並不要求返回任何特定的類型, MVC 支持任何對象做爲返回值。若是操做返回的是 IActionResult 的某個實現,而且控制器繼承自 Controller ,那麼可使用更多輔助方法。若是不是,則將使用合適的 IOutputFormatter 實現序列化對象。
若要從繼承 Controller 基類的控制器返回特定格式的數據,可使用內置的輔助方法 Json 來返回 JSON 格式, 使用 Content 來返回 純文本。操做方法的返回類型必須是指定的結果類型(如 JsonResult)或 IActionResult。
[HttpGet] public JsonResult Get() { return Json(new User()); }
以上代碼 Content-Type 將返回 application/json。
要想返回純文本格式的數據,則使用 ContentResult 以及 Content 輔助方法:
[HttpGet] public ContentResult Get() { return Content("result"); }
以上代碼 Content-Type 將返回 test/plan 。 也可使用一個字符串相應類型來實現這個行爲:
[HttpGet] public string Get() { return "result"; }
對於具備多個返回類型或選項的複雜操做,請選擇 IActionResult 做爲返回類型。
2.配置格式化程序
若是應用程序想支持默認 JSON 以外的格式,能夠在 project.json 文件中添加這些額外的依賴項,並配置 MVC 來支持。輸入和輸出的格式是能夠隔離的。輸入格式經過使用模型綁定,輸出格式經過格式化響應。
3.添加對 XML 格式的支持
要添加對 XML 格式的支持,須要先安裝 Microsoft.AspNetCore.Mvc.Formatters.Xml 包,而後在 ConfigureServices 中配置 XmlSerializerFormatters :
services.AddMvc()
.AddXmlSerializerFormatters()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
或者能夠只添加輸出格式:
services.AddMvc(options => { options.OutputFormatters.Add(new XmlSerializerOutputFormatter()); }) //.AddXmlSerializerFormatters() .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
這兩種方法都將使用 System.Xml.Serialization.XmlSerializer 序列化結果。還能夠經過添加其餘相關格式來使用 System.Runtime.Serialization.DataContractSerializer :
services.AddMvc(options => { options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter()); }) //.AddXmlSerializerFormatters() .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
4.強制特定格式化
如果想爲某個操做限制響應格式,則可使用 [Produces] 過濾器。[Produces] 過濾器能夠爲這個控制器或 Action 指定響應格式:
[HttpGet("{id}", Name = "Get")] [Produces("application/json")] public string Get(int id) { return "value"; }
對於一些特殊狀況,可能不想使用內建的格式化實現。默認狀況下,返回類型爲 string 時將格式化爲 text/plain 。這種行爲能夠經過移除 TextOutputFormatter 來改變:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.OutputFormatters.RemoveType<TextOutputFormatter>(); options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>(); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
上面移除了 TextOutputFormatter 和 HttpNoContentOutputFormatter,當返回類型爲 string 時,將返回 406 Not Acceptable。若是存在 XML 格式化程序,則將格式化響應結果。
移除了 HttpNoContentOutputFormatter ,當返回某個返回類型爲模型對象的操做返回 null 時,將返回 204 No Content 響應。JSON 格式將簡單地返回主體信息爲 null 的響應,而 XML 格式將返回一個空的帶有 xsi:nil="true" 屬性的 XML 元素。
5.響應格式 URL 映射
客戶端能夠在 URL 中請求特定的格式,好比在請求字符串或路徑中,或者經過使用特定格式的文件擴展名(好比 .xml 或 .json),須要在 API 所使用的路由中指定:
[FormatFilter] public class UserController : Controller { // GET: api/User [HttpGet] [Route("[controller]/[action]/{id}.{format?}")] public IActionResult GetById(int id) { return Content("xxx"); } }
這個路由配置將容許使用可選的文件擴展名來指定格式。[FormatFilter] 特性將在 RouteData 中檢查該格式的值是否存在,並建立響應時將響應數據映射到相應的格式:
Route Formatter
/User/GetById/5 :默認輸出格式
/User/GetById/5.json :JSON格式(若是配置過)
/User/GetById/5.xml; :XML格式(若是配置過)
6.自定義格式化程序 Protocol Buffers (簡稱 protobuf)
Protocol Buffers 是一種輕便高效的結構化數據存儲格式,可用於結構化數據串行化,或者說序列化。它很適合作數據存儲或 RPC(遠程過程調用協議)數據交換格式。可用於通信協議,數據存儲等領域的語言無關,平臺無關,可擴展的序列化結構數據格式。好比實現一個程序返回 protobuf 格式:
建立 API 項目,添加 protobuf-net 引用。
添加 ProtobufFormatter 類:
public class ProtobufFormatter:OutputFormatter { public string ContentType { get; private set; } public ProtobufFormatter() { ContentType = "application/proto"; SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/proto")); } public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var response = context.HttpContext.Response; Serializer.Serialize(response.Body,context.Object); return Task.FromResult(0); } }
繼承 OutputFormatter ,而後實現 WriteResponseBodyAsync 方法,初始化時賦值 ContentType ,並添加支持 MediaType。在 WriteResponseBodyAsync 方法中獲取 Response ,調用 protobuf-net 的 Serializer.Serialize 方法將 Object 序列化至輸出內容。 protobuf 在序列化時必須指定順序,添加 User 類,實現 protobuf 實體:
[ProtoContract] public class User { [ProtoMember(1)] public int Id { get; set; } [ProtoMember(2)] public string Name { get; set; } [ProtoMember(3)] public int Age { get; set; } }
類上須要添加 [ProtoContract] 特性,字段上須要 ProtoMember 特性,並指定順序。而後修改 UserController:
[Route("api/[controller]")] [ApiController] [FormatFilter] public class UserController : Controller { private IEnumerable<User> users; public UserController() { users = new User[] { new User(){ Id=1,Name="Bob",Age = 20}, new User(){ Id=2,Name="Tom",Age = 22} }; } // GET: api/User [HttpGet] [Produces("application/proto")] public IEnumerable<User> Get() { return users; } }
修改 ConfigureServices :
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { options.OutputFormatters.Add(new ProtobufFormatter()); }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
運行程序,會返回一個二進制文件。
建立一個控制檯,檢查序列化:
class Program { static void Main(string[] args) { HttpClient client = new HttpClient(); var stream = client.GetStreamAsync("https://localhost:44358/api/User").Result; var users = Serializer.Deserialize<List<User>>(stream); foreach (var user in users) { Console.WriteLine($"Id:{user.Id} - Name:{user.Name} - Age:{user.Age}"); } Console.ReadKey(); } }