[ASP.NET MVC] ASP.NET Web API (1) - 技術概觀

ASP.NET MVC 4.0 的其中一項新功能,就是 Web API,這項自 WCF Web API 衍生的產物,讓開發人員實作 REST-style Web Service 服務所需要的工作簡化很多,尤其是在現今 Modern Web Development 的時代,輕量化的 Web API 變成前端應用上,可以取代 Web Service 的重要技術。

ASP.NET MVC 4.0 的其中一項新功能,就是 Web API,這項自 WCF Web API 衍生的產物,讓開發人員實作 REST-style Web Service 服務所需要的工作簡化很多,尤其是在現今 Modern Web Development 的時代,輕量化的 Web API 變成前端應用上,可以取代 Web Service 的重要技術。筆者之前有寫過一篇文章,其中也介紹了幾個常用的 API 實作方式,其中筆者認為使用 Web API 的作法最簡單,因為:

  • 它具有內建的 HTTP 訊息解析功能。
  • 它具有自動化的 HTTP 動詞對應功能 (這是 REST API 的要求之一)。
  • 它具有自動化的參數對應功能,能讓 URL/POST 的資料自動對應到方法的參數。
  • 它具有管線化的處理流程,能讓開發人員適當的安插一些檢查機制。

ASP.NET Web API 本身植基於 ASP.NET MVC 架構內,它的基本架構也是以 MVC 為主,不過 Web API 本身是沒有 View 的,換句話說,這個 View 不像在 MVC 中是一個實體的 aspx (ASPX Render) 或是 .cshtml (Razor),而是化成最典型的 HTTP 訊息,並且由 HttpRequestMessage 和 HttpResponseMessage 來替代,它們只會負責封裝 HTTP 的標頭資料,至於內容是啥?得要開發人員自己決定。

如果說讀者對 Web API 沒什麼印象,可試著在 Visual Studio 2012 中建立一個新的 Web API 專案,它所預設產生的 ValuesController 長得像這樣:

namespace CodeCamper.Web.Controllers
{
    public class ValuesController : ApiController
    {
        // GET api/values
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/values/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        public void Post(string value)
        {
        }

        // PUT api/values/5
        public void Put(int id, string value)
        {
        }

        // DELETE api/values/5
        public void Delete(int id)
        {
        }
    }
}

一個 Web API 的程式的基本元素為:

  • 類別本身繼承自 ApiController。
  • 依照 MVC 的習慣配置原則,Web API 的類別要放在 Controllers 資料夾內。
  • Get/Post/Put/Delete 分別對應到 HTTP 的 GET/POST/PUT/DELETE 四個方法。
  • URL 的格式是 /api/{controller}/{id},這個可以在 WebApiConfig.cs 或是 RouteConfig.cs 中找到。

由 ValuesController 我們可以看得出來,它具備了標準的 GET/POST/PUT/DELETE 等方法,而且連在方法中使用 [HttpGet], [HttpPost] 等修飾詞都不用,Web API 的核心會自動搜尋相關的方法以呼叫,然後沒有回傳型別 (void),表示 Web API 核心會自動的處理例外狀況並回應訊息,開發人員只需要注意並專注在方法本體功能的實作即可,其他的由 Web API 核心處理就行了。

但有些人就覺得沒有自己處理回應訊息就是怪怪的 (筆者先承認自己是),所以 Web API 也提供者非回傳值的功能,ValuesController 的 Get() 方法就是如此,不過這還不夠,我們可能會需要進一步的處理 HTTP 標頭資料,這時候我們就可以使用 HttpResponseMessage 來做這件事了:

public HttpResponseMessage Post(ViewModels.Project Project)
{
    InternalSystem.ProjectService projectService = new InternalSystem.ProjectService();

    try 
    {
        string projectId = projectService.Create(Project.Name, Project.Caption, Project.Description);
        return this.Request.CreateResponse<string>(HttpStatusCode.OK, JsonConvert.SerializeObject(
            new
            {
                status = "OK",
                projectId = projectId
            }
            ));
    }
    catch (Exception e)
    {
        return this.Request.CreateResponse<string>(HttpStatusCode.BadRequest, JsonConvert.SerializeObject(
            new
            {
                status = "failed",
                message = e.Message,
                exception = e.GetType().Name                    }
            ));
    }
}

HttpRequestMessage.CreateResponse<T>() 提供了一個簡易的 Factory Pattern,由它來代為產生具有特定格式的回應訊息的 HttpResponseMessage 物件,並且可以由開發人員決定使用的 HttpStatusCode,例如 400 代表參數有問題,401 代表未經授權,403 代表禁止存取,404 代表找不到,405 代表要求方法錯誤等,開發人員能視自己的需求來回應訊息,用戶端會以回應的訊息來進行下一步動作。

它的用戶端,基本上只要是能夠發送 HTTP 要求與接收 HTTP 回應的應用程式都可以,也就是說不僅限於瀏覽器,其他可以發出 HTTP 訊息的程式 (WebClient, HttpWebRequest, Socket 與最新的 HttpClient) 都能消費使用 Web API,不過如果要使用 JSON 的話,在 .NET 來說以 Json.NET 是首選,它可以支援 LINQ to JSON,也可以將匿名型別或具名型別直接轉換成 JSON,也可以進行反向處理,因此在處理 JSON 上問題並不大,再加上 Web API 的核心能處理掉 JSON 訊息對應到方法參數的能力,所以在 Web API 的架構下,不妨大膽的引入 JSON。

如果讀者有寫過 HTTP Handler 或是 WCF Web API 的話,對這個技術的學習曲線會相對低很多。

有了這個概觀後,接下來就可以開始玩一玩了。

Reference:

http://blog.kkbruce.net/2012/03/aspnet-web-api-1.html#.UO4lxG_qlyU

http://www.dotblogs.com.tw/gelis/archive/2012/02/18/69602.aspx

http://www.asp.net/web-api

http://channel9.msdn.com/Shows/Web+Camps+TV/Dan-Roth-Takes-Us-on-a-Deep-Dive-into-Web-API

http://blogs.msdn.com/b/zxue/archive/2012/11/07/what-is-asp-net-web-api-and-how-does-it-work.aspx