// 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協議規定,確保基於協議之上的一些外部行爲的結果是符合預期的。