// GET: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63 /// <summary> /// 获取特定产品 /// </summary> /// <param name="id">产品标识</param> /// <returns></returns> [Route("~/api/v1/Products/{id}")] [ResponseType(typeof(ProductOutput))] public IHttpActionResult GetProduct(Guid id) { var result = productService.GetProductById(id); return Ok(result); }
规范:编程
// GET: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63 /// <summary> /// 获取特定产品 /// </summary> /// <param name="id">产品标识</param> /// <returns></returns> [Route("~/api/v1/Products/{id}")] [ResponseType(typeof(ProductOuput))] [SwaggerResponse(HttpStatusCode.NotFound)] public IHttpActionResult GetProduct(Guid id) { var result = productService.GetProductById(id); if (result == null) { return NotFound(); } return Ok(result); }
规范:api
使用XML Documentation的response配置节也能够达到与SwaggerResponse相似的效果,以下所示。须要注意的是,二者出现冲突时,SwaggerResponse的优先级更高。ui
/// <response code="404">Not Found</response>
// GET: api/v1/Products /// <summary> /// 获取全部产品 /// </summary> /// <returns>产品集合</returns> [Route("~/api/v1/Products")] public IEnumerable<ProductOutput> GetProducts() { var result = productService.GetProducts(); return result; }
规范:3d
// GET: api/v1/Products?Pager.PageIndex=1&Pager.PageSize=10 /// <summary> /// 获取全部产品的分页列表 /// </summary> /// <returns>产品分页列表</returns> [Route("~/api/v1/Products")] public IPagedList<ProductOutput> GetPagedProducts([FromUri] Pager pager) { var result = productService.GetPagedProducts(pager); return result; }
规范:调试
// POST: api/v1/Products /// <summary> /// 建立产品 /// </summary> /// <param name="product">产品</param> /// <returns></returns> [Route("~/api/v1/Products")] [SwaggerResponseRemoveDefaults] [SwaggerResponse(HttpStatusCode.BadRequest)] [SwaggerResponse(HttpStatusCode.Created, Type = typeof(ProductOutput))] public IHttpActionResult PostProduct([FromBody]ProductInput product) { if (ModelState.IsValid) { return BadRequest(ModelState); } var result = productService.CreateProduct(product); return CreatedAtRoute("DefaultApi", new { id = product.Id }, result); }
规范:日志
使用CreatedAtRoute能够应用一个现成的路由。本例中使用了名称为DefaultApi的默认路由,此默认路由一般定义在WebApiConfig.cs文件中。但更多的状况是,使用一个已存在的自定义路由,此时须要将这一路由声明为一个具名路由。例如,前例中GET方法的路由,能够改写为以下方式,使之成为一个具名路由,并使用GetProductById这一名称(替换本例中的DefaultApi),此路由即用于建立新资源的URL。本例中new { id = product.Id }中的参数id,将会替换该路由中的参数id,而result则做为Content中的内容返回。code
[Route("~/api/v1/Products/{id}", Name = "GetProductById")]
本例中,方法的入参product应当为一个做为Input的DTO,而result变量应当为一个做为Output的DTO。相关的DTO的命名以Input或Output做为后缀。后缀不并仅限于使用Input和Output,也可使用Create或Update等,进一步区分用途。排序
// POST: api/v1/Products/Last/Remove /// <summary> /// 删除最后一个产品 /// </summary> /// <returns></returns> [Route("~/api/v1/Products/Last/Remove")] [SwaggerResponseRemoveDefaults] [SwaggerResponse(HttpStatusCode.NotFound)] [SwaggerResponse(HttpStatusCode.NoContent)] public IHttpActionResult RemoveLastProduct() { var result = productService.RemoveLastProduct(); if (!result) { return NotFound(); } return StatusCode(HttpStatusCode.NoContent); }
规范:接口
// PUT: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63 /// <summary> /// 更新产品 /// </summary> /// <param name="id">产品标识</param> /// <param name="product">产品</param> /// <returns></returns> [Route("~/api/v1/Products/{id}")] [SwaggerResponseRemoveDefaults] [SwaggerResponse(HttpStatusCode.NotFound)] [SwaggerResponse(HttpStatusCode.NoContent)] public IHttpActionResult PutProduct(Guid id, [FromBody]ProductInput product) { if (ModelState.IsValid) { return BadRequest(ModelState); } var result = productService.GetProductById(id); if (result == null) { return NotFound(); } productService.UpdateProduct(id, product); return StatusCode(HttpStatusCode.NoContent); }
规范:ip
// PUT: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63/Disable /// <summary> /// 下架产品 /// </summary> /// <param name="id">产品标识</param> /// <returns></returns> [HttpPut] [Route("~/api/v1/Products/{id}/Disable")] [SwaggerResponseRemoveDefaults] [SwaggerResponse(HttpStatusCode.NotFound)] [SwaggerResponse(HttpStatusCode.NoContent)] public IHttpActionResult DisableProduct(Guid id) { var result = productService.GetProductById(id); if (result == null) { return NotFound(); } productService.DisableProduct(id); return StatusCode(HttpStatusCode.NoContent); }
规范:
// DELETE: api/v1/Products/1455ebe0-832b-46c5-8772-b9483d947a63 /// <summary> /// 删除产品 /// </summary> /// <param name="id">产品标识</param> /// <returns></returns> [Route("~/api/v1/Products/{id}")] [SwaggerResponseRemoveDefaults] [SwaggerResponse(HttpStatusCode.NotFound)] [SwaggerResponse(HttpStatusCode.NoContent)] public IHttpActionResult DeleteProduct(Guid id) { var result = productService.GetProductById(id); if (result == null) { return NotFound(); } productService.DeleteProduct(id); return StatusCode(HttpStatusCode.NoContent); }
规范:
幂等性应关注发送多个重复的操做,系统状态的结果是否始终一致,而不是关注接口返回是否一致。系统状态在这里主要指的是业务状态,而不包括那些业务以外额外生成的状态变动,例如日志、统计数据等。符合幂等性的写操做,可使用POST、DELETE方法;不然,即便语义上属于更新或删除操做,也应当使用POST方法,以符合HTTP协议规定,确保基于协议之上的一些外部行为的结果是符合预期的。