博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Core 2 学习笔记(十二)REST-Like API
阅读量:6297 次
发布时间:2019-06-22

本文共 7224 字,大约阅读时间需要 24 分钟。

原文:

Restful几乎已算是API设计的标准,通过HTTP Method区分新增(Create)、查询(Read)、修改(Update)和删除(Delete),简称CRUD四种数据存取方式,简约又直接的风格,让人用的爱不释手。

本篇将介绍如何通过ASP.NET Core实践REST-Like API。

为什么是REST-Like 而不是 REST?

本文API设计未符合HATEOAS(Hypermedia As The Engine Of Application State)原则,所以不得称为RESTful API。

RESTful API 有四个重要的原则要遵守:

  1. Level 0
    使用HTTP做为资料传输的媒介。
  2. Level 1
    不要提供一个包山包海的API,而是要区分资源,每个资源都该有对应的API。
  3. Level 2
    透过HTTP Method区分新增(Create)、查询(Read)、修改(Update)跟删除(Delete)。
  4. Level 3
    对同资源可以用链结表达的方式,向下延伸查询或修改。
    参考:

HTTP Method

REST-Like API 对数据的操作行为,通过HTTP Method 分为以下四种方式:

  • 新增(Create)

    用HTTP POST通过Body传递JSON或XML格式的数据给Server。例如:

POST http://localhost:5000/api/users{   "id": 1,   "name": "SnailDev"}
  • 查询(Read)

    用HTTP GET通过URL带查询参数。通常查询单一资源会用路由参数(Routing Parameter)带上唯一值(Primary Key);多笔查询会用复数,而查询条件用Query String。例如:

# 单笔查询GET http://localhost:5000/api/users/1# 多笔查询GET http://localhost:5000/api/users# 多笔查询带条件GET http://localhost:5000/api/users?q=SnailDev
  • 修改(Update)

    修改数据如同查询跟新增的组合,用HTTP PUT通过URL带路由参数,找到要修改的目标;再通过Body传递JSON或XML格式的数据给Server。例如:

PUT http://localhost:5000/api/users/1{   "name": "SnailDev"}
  • 删除(Delete)

    删除数据同查询,用HTTP DELETE通过URL带路由参数,找到要删除的目标。例如:

DELETE http://localhost:5000/api/users/1

HTTP Method Attribute

 有提到,过去ASP.NET MVC把MVC及Web API的套件分开,但在ASP.NET Core中MVC及Web API用的套件是相同的。所以只要装Microsoft.AspNetCore.Mvc套件就可以用Web API了。路由方式也跟 介绍的RouteAttribute差不多,只是改用HTTP Method Attribute。

HTTP Method Attribute 符合RESTful 原则的路由设定方式如下:

[Route("api/[controller]s")]public class UserController : Controller{    [HttpGet]    public List
Get(string q) { // ... } [HttpGet("{id}")] public UserModel Get(int id) { // ... } [HttpPost] public int Post([FromBody]UserModel user) { // ... } [HttpPut("{id}")] public void Put(int id, [FromBody]UserModel user) { // ... } [HttpDelete("{id}")] public void Delete(int id) { // ... }}

目前ASP.NET Core 还没有像ASP.NET MVC 的MapHttpAttributeRoutes 可以绑Http Method 的全局路由,都要在Action 加上HTTP Method Attribute。

SerializerSettings

 用以下代码,说明SerializerSettings

public class UserModel{    public int Id { get; set; }    public string Name { get; set; }    public string Email { get; set; }        public string PhoneNumber { get; set; }    public string Address { get; set; }}// ...[Route("api/[controller]s")]public class UserController : Controller{  [HttpGet("{id}")]  public UserModel Get(int id)  {      return new UserModel {          Id = 1,          Name = "SnailDev"      };  }}

camel Case

过去ASP.NET Web API 2预设是Pascal Case;而ASP.NET Core预设是使用camel Case。

若想要指定用ContractResolver,可以在Startup.csConfigureServices加入MVC服务时,使用AddJsonOptions设定如下:

// ...public class Startup{    public void ConfigureServices(IServiceCollection services)    {                services.AddMvc()                .AddJsonOptions(options =>                 {                    options.SerializerSettings.ContractResolver                         = new CamelCasePropertyNamesContractResolver();                });        // 同以下写法:        // services.AddMvc();    }}

访问http://localhost:5000/api/users/1会返回JSON如下:

{    "id": 1,    "name": "SnailDev",    "email": null,    "phoneNumber": null,    "address": null}

Pascal Case

若想保持跟ASP.NET Web API 2一样使用Pascal Case,ContractResolver则改用DefaultContractResolver

// ...public class Startup{    public void ConfigureServices(IServiceCollection services)    {                services.AddMvc()                .AddJsonOptions(options =>                 {                    options.SerializerSettings.ContractResolver                         = new DefaultContractResolver();                });    }}

DefaultContractResolver名称是延续ASP.NET,虽然名称叫Default,但在ASP.NET Core它不是Default。CamelCasePropertyNamesContractResolver才是ASP.NET Core的Default ContractResolver。

访问http://localhost:5000/api/users/1会返回JSON如下:

{    "Id": 1,    "Name": "SnailDev",    "Email": null,    "PhoneNumber": null,    "Address": null}

Ignore Null

上述两个JSON 回传,都带有null 的字段。在序列化的过程,找不到字段会自动转成null,传送的过程忽略掉也没错,反而可以节省到一点流量。

// ...public class Startup{    public void ConfigureServices(IServiceCollection services)    {                services.AddMvc()                .AddJsonOptions(options =>                 {                    options.SerializerSettings.NullValueHandling                         = Newtonsoft.Json.NullValueHandling.Ignore;                });    }}

访问http://localhost:5000/api/users/1会返回JSON如下:

{    "id": 1,    "name": "SnailDev"}

示例程序

Startup.cs

public class Startup{    public void ConfigureServices(IServiceCollection services)    {        services.AddMvc()                .AddJsonOptions(options => {                    options.SerializerSettings.NullValueHandling                        = Newtonsoft.Json.NullValueHandling.Ignore;                });    }    public void Configure(IApplicationBuilder app)    {        app.UseMvc();    }}

Models\ResultModel.cs

namespace MyWebsite.Models{    public class ResultModel    {        public bool IsSuccess { get; set; }        public string Message { get; set; }        public object Data { get; set; }    }}

用一个ResultModel 来包装每个API 回传的内容,不论调用Web API 成功失败都用此对象包装,避免直接throw exception 到Client,产生HTTP Status 200 以外的状态。 

Controllers/UserController.cs

using System.Collections.Generic;using System.Linq;using System.Text.RegularExpressions;using Microsoft.AspNetCore.Mvc;using MyWebsite.Models;namespace MyWebsite.Controllers{    [Route("api/[controller]s")]    public class UserController : Controller    {        private static List
_users = new List
(); [HttpGet] public ResultModel Get(string q) { var result = new ResultModel(); result.Data = _users.Where(c => string.IsNullOrEmpty(q) || Regex.IsMatch(c.Name, q, RegexOptions.IgnoreCase)); result.IsSuccess = true; return result; } [HttpGet("{id}")] public ResultModel Get(int id) { var result = new ResultModel(); result.Data = _users.SingleOrDefault(c => c.Id == id); result.IsSuccess = true; return result; } [HttpPost] public ResultModel Post([FromBody]UserModel user) { var result = new ResultModel(); user.Id = _users.Count() == 0 ? 1 : _users.Max(c => c.Id) + 1; _users.Add(user); result.Data = user.Id; result.IsSuccess = true; return result; } [HttpPut("{id}")] public ResultModel Put(int id, [FromBody]UserModel user) { var result = new ResultModel(); int index; if ((index = _users.FindIndex(c => c.Id == id)) != -1) { _users[index] = user; result.IsSuccess = true; } return result; } [HttpDelete("{id}")] public ResultModel Delete(int id) { var result = new ResultModel(); int index; if ((index = _users.FindIndex(c => c.Id == id)) != -1) { _users.RemoveAt(index); result.IsSuccess = true; } return result; } }}

执行结果

通过Postman 测试API。

  • 新增(Create)

  • 查询(Read)

  • 修改(Update)

  • 删除(Delete)

参考

 

老司机发车啦:

转载地址:http://jxlta.baihongyu.com/

你可能感兴趣的文章
Android 高效安全加载图片
查看>>
vue中数组变动不被监测问题
查看>>
3.31
查看>>
类对象定义 二
查看>>
收费视频网站Netflix:用户到底想要“点”什么?
查看>>
MacOS High Sierra 12 13系统转dmg格式
查看>>
关于再次查看已做的多选题状态逻辑问题
查看>>
动态下拉菜单,非hover
查看>>
政府安全资讯精选 2017年第十六期 工信部发布关于规范互联网信息服务使用域名的通知;俄罗斯拟建立备用DNS;Google打击安卓应用在未经同意情况下收集个人信...
查看>>
简单易懂的谈谈 javascript 中的继承
查看>>
iOS汇编基础(四)指针和macho文件
查看>>
Laravel 技巧锦集
查看>>
Android 使用 ViewPager+RecyclerView+SmartRefreshLayout 实现顶部图片下拉视差效果
查看>>
Flutter之基础Widget
查看>>
写给0-3岁产品经理的12封信(第08篇)——产品运营能力
查看>>
ArcGIS Engine 符号自动化配置工具实现
查看>>
小程序 · 跳转带参数写法,兼容url的出错
查看>>
flutter error
查看>>
Flask框架从入门到精通之模型数据库配置(十一)
查看>>
10年重新出发
查看>>