在 ASP.NET Web API 2 基礎下,建立整合完備的應用程式專案範本。

  • 整合套件或自行開發來提供 RESTFul API 最佳實踐 中的建議功能。
  • 配合 開發規範 提供一致有效率的開發方式及程式品質。

這篇介紹 ASP.NET Web API 對 RESTFul best practice 最佳實踐的支援。

相關套件

  • HelpPage

網址樣式

一) 利用 RouteConfig 做樣式設定。

二) 利用 ASP.NET Web API 提供的 RoutePrefix 和 Route attribute,可在 Controller 及 Action 上指定。

Route = RoutePrefix() + Route(),Route 和 Prefix 相同也要加上 Route() 才會生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Controller
[RoutePrefix("api/values")]
public class ValuesController : ApiController

// GET api/values
[Route()]
public IEnumerable<string> Get()

// GET api/values/{id}, id 限定類型
[Route("{id:int}")]
public string Get(int id)

// POST api/values
[Route()]
public void Post([FromBody]string value)

// PUT api/values/{id}
[Route("{id:int}")]
public void Put(int id, [FromBody]string value)

// DELETE api/values/{id}
[Route("{id:int}")]
public void Delete(int id)

API 文件

ASP.NET Web API 自帶有 HelpPage 套件,可自動產生並直接在網站中提供 API 文件。

HelpPage 套件

新建專案時選擇 Web API 專案,就已包含 HelpPage 套件。

加入現有專案

套件:Install-Package Microsoft.AspNet.WebApi.HelpPage

完成後專案中會新增文件功能區域 Areas/HelpPage 並掛上 /Help 網址供叫用。

檢查 Global.asax,確保 Application_Start 有啟用 Area 功能:

1
2
3
4
5
6
protected void Application_Start()
{
// Add this code, if not present.
AreaRegistration.RegisterAllAreas();
// ...
}

啟用 XML 註解

HelpPage 預設沒有啟用 XML 格式的註解,需要手動調整啟用它。

編輯 Areas/HelpPage/App_Start/HelpPageConfig.cs,開放(反註解)以下內容:

1
2
config.SetDocumentationProvider(new XmlDocumentationProvider(
HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));

打開專案屬性設定,到 建置 修改 輸出 區段內容

啟用 XML 文件檔案:
[V] XML 文件檔案(X): [App_Data/XmlDocument.xml]

結果處理

OData 是 Web 資料存取的協定,提供一致的資料查詢及處理功能,ASP.NET Web API 支援 OData v3 和 v4 版本。

OData 相關官方文件:OData in ASP.NET Web API

在未啟用 OData 的情況下,可利用 LINQ 簡單實作出 filtering, sorting & searching 的功能。

更新或新增返回異動資訊

ASP.NET Web API 有 ApiController.Created() 方法提供狀態 201 及 Location Header 的回應。

1
2
3
responseMessage.Headers.Location = new Uri("https://api.shop.com/v1/products/123");

return Created("https://api.shop.com/v1/products/123", postData);

JSON 格式

ASP.NET Web API 預設是依據瀏覽器端送出的 Accept 標頭自動決定回應的內容格式。

修改 Global.asax 中 Application_Start() 關閉 XML 格式:

1
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

認證

配合 OpenID Connect Provider and OAuth 2.0 Authorization Server,如 IdentityServer

認證失敗,必須回傳 401 Unauthorized statue code。

ASP.NET Web API 有 ApiController.Unauthorized 方法提供狀態 401 回應。

1
return Unauthorized();


1
throw new HttpResponseException(HttpStatusCode.Unauthorized);

錯誤訊息

ASP.NET Web API 2 提供 HttpError 類別做為 Response 錯誤訊息的容器。

一般錯誤訊息的內容:

1
2
3
4
5
6
new HttpError("this is a error message.");

>>> Response >>>
{
"message": "this is a error message."
}

傳遞 Exception 的內容:

1
2
3
4
5
6
7
8
9
new HttpError(new InvalidOperationException(), true);

>>> Response >>>
{
"message": "發生錯誤。",
"exception_message": "由於該物件目前的狀態,導致作業無效。",
"exception_type": "System.InvalidOperationException",
"stack_trace": null
}

不夠用,可客製 Error 類別,如下例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ErrorContent
{
public string Message { get; set; }
public string Description { get; set; }
public string Code { get; set; }

public List<Error> Errors { get; set; }
}

public class Error
{
public string Item { get; set; }
public string Message { get; set; }
public string Code { get; set; }
}

用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public async Task<IHttpActionResult> Get()
{
var err = new ErrorContent { Message = "error message" };
err.Errors = new List<Error> { new Error { Code = "1", Item = "123" } };
return ResponseMessage(Request.CreateResponse(HttpStatusCode.NotFound, err));
}

>>> Response >>>
{
"message": "error message",
"description": null,
"code": null,
"errors": [
{
"item": "123",
"message": null,
"code": "1"
}
]
}

要讓 null 欄位不回傳,調整 WebApiConfig.cs 加上

1
config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };

HTTP 狀態碼

Web API 2 提供 2 種定義好狀態碼的 Response 方式。

一)常用狀態,ApiController 提供 Result Creator method,如下例:

  • Ok() // 200
  • Unauthorized() // 401
  • BadRequest() // 400
  • NotFound() // 404
  • InternalServerError() // 500
1
2
3
4
5
public async Task<IHttpActionResult> Get()
{
var member = new Member { Num = 1, Name = "John" };
return Ok(member);
}

二)HttpStatusCode 列舉 (官方文件中有完整表列)

1
2
3
4
5
public async Task<IHttpActionResult> Get()
{
var member = new Member { Num = 1, Name = "John" };
return ResponseMessage(Request.CreateResponse(HttpStatusCode.OK, member));
}

若是錯誤,可以用以下方法更明確,會轉為 status code 回傳

1
throw new HttpResponseException(HttpStatusCode.NotImplemented);

系列文章