[Web API] 進擊的 Web API : 建立 Web API 專案

在第一篇 初探 Web API 後,大概已經對 Web API 有基本的瞭解了,接下來就是要開始動手嘍!首先因為我使用 Visual Studio 2010 開發,所以必須要先安裝 ASP.NET MVC 4 套件,此套件的下載路徑於第一篇文章中有提到,待安裝好後就可以繼續往下了,就先從建立一個基礎的專案開始吧。

前言


  當城牆被打破了之後,我也不得不面對敵人了... 在第一篇 初探 Web API 後,大概已經對 Web API 有基本的瞭解了,接下來就是要開始動手嘍!首先因為我使用 Visual Studio 2010 開發,所以必須要先安裝 ASP.NET MVC 4 套件,此套件的下載路徑於第一篇文章中有提到,待安裝好後就可以繼續往下了,就先從建立一個基礎的專案開始吧。

 

建立 Web API 專案


  讓我們啟動 Visual Studio 2010 ,於 「檔案」→「新增」→「專案」開啟新增專案視窗,選擇範本中的 ASP.NET MVC 4 Web 應用程式。

  在次跳出來的 MVC 4 範本視窗中選擇 Web API 後確定。

  建立完成一開始將看到預設產生了一個 ValuesContorller 。


public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable Get()
    {
        return new string[] { "value1", "value2" };
    }

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

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

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

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

  在 ValuesController 裡預設產生了四種 HTTP 動詞 GET、POST、PUT、DELETE,因為架構在 MVC 之上所以可以看到每個方法上的註解有註明路由的位置,而路由的設定我們可以從 RouteConfig.cs 或 WebApiConfig.cs 裡設定,這兩個路由設定差別在於 RouteConfig.cs 是給 Web Controller 使用而 WebApiConfig.cs 是給 Web API Controller 使用 (另外可參考 Configuring ASP.NET Web API )。

 

  我們先針對此預先產生出來的 ApiController 來測試一下,心急的你一定會想先看到使用的結果,以 Debug 模式啟動程式開發伺服器瀏覽網站。

  試著在網址上輸入「http://localhost:51370/api/values」,會發現 IE 會返回一下要求下載的內容,點選下載開啟。

  開啟後可以發現回傳的內容就如同 ValuesController 裡的 IEnumerable<string> Get() 方法所設定的值一樣,這就是一個基本的 Web API 使用方式。

 

實作 CRUD 功能


  最基本的呼叫方式看過了之後,現在我們來稍微調整一下這個新專案,讓此 Web API 能夠包含新增、修改、更新、刪除的功能,首先在 Models 加入一個 Product 類別並撰寫相關的屬性。


namespace TWebApi_01.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public string Price { get; set; }
        public int Stock { get; set; }
    }
}

  接著在 Controller 加入一個新的 ApiController,修改名稱為「ProductsController」、範本選擇「空白 API 控制器」後按加入,Web API 的 Controller 都必須繼承於 ApiController 類。

 


public class ProductsController : ApiController
{
}

 

  接下來就來開使撰寫針對 HTTP 動詞 GET、POST、PUT、DELETE 對應的方法嘍,但這裡要注意一點,因為 Web API 是透過路由設定與上述的四種動詞去進行判斷指向哪一個方法,所以在方法的命名規則中都必須要使用 Get、Post、Put、Delete 這四種名稱作為方法名稱開頭,如你真的不想遵守這個原則,你可以使用額外標註 [HttpGet]、[HttpPost]、[HttpPut]、[HttpDelete] 屬性於方法名稱上之方式定義。

 

查詢方法


/// <summary>
/// 取得所有產品清單
/// URI: /api/products
/// Method: GET
/// </summary>
/// <returns></returns>
public IEnumerable<Product> GetAllProducts()
{
    return new ProductDao().GetProducts();
}

/// <summary>
/// 取得指定編號產品
/// URI: /api/products/1
/// Method: GET
/// </summary>
/// <param name="pId"></param>
/// <returns></returns>
public Product GetProductById(int id)
{
    IEnumerable<Product> products = new ProductDao().GetProducts();
    var product = products.Where(p => p.Id == id);
    if (product.FirstOrDefault<Product>() != null)
        return product.First<Product>();
    else
        throw new HttpResponseException(HttpStatusCode.NotFound);
}

/// <summary>
/// 取得指定類別產品清單
/// URI: /api/products?category=MVC
/// Method: GET
/// </summary>
/// <param name="pCategory"></param>
/// <returns></returns>
public IEnumerable<Product> GetProductsByCategory(string category)
{
    IEnumerable<Product> products = new ProductDao().GetProducts();
    var cProducts = products.Where(p => p.Category == category);
    if (cProducts.FirstOrDefault<Product>() != null)
        return cProducts;
    else
        throw new HttpResponseException(HttpStatusCode.NotFound);
}

  以上三個方法都是作用於查詢資料使用,其差異如下。

  • IEnumerable<Product> GetAllProducts():
    • GET,取得所有產品資料,URI 為 http://localhost:51370/api/Products 。
  • Product GetProductById(int id):
    • GET,取得指定產品資料,透過網址帶入 ID 後交由 Web API 自動判斷路由到指定方法,URI 為 http://localhost:51370/api/Products/1 。
  • IEnumerable<Product> GetProductsByCategory(string category):
    • GET,取得指定類別資料,透過網址帶入 Category 參數後交由 Web API 自動判斷路由到指定方法,URI 為 http://localhost:51370/api/Products?category=MVC 。

 

  Web API 會自動透過網址與 HTTP 動詞進行分析後再呼叫對應參數的網址,或者也能夠自己額外定義新的路由位置。

 

新增方法


/// <summary>
/// 新增產品資料後回傳清單
/// URI: /api/products/name/category/price/stock
/// Method: POST
/// </summary>
/// <param name="name"></param>
/// <param name="category"></param>
/// <param name="price"></param>
/// <param name="stock"></param>
/// <returns></returns>
public IEnumerable<Product> PostProduct(string name, string category, string price, int stock)
{
    ProductDao productDao = new ProductDao();
    try
    {
        return productDao.InsertProduct(name, category, price, stock);
    }
    catch (Exception)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
}

  新增需要使用 POST 動詞,除了以上的程式碼之外,我們還需要去 WebApiConfig.cs 中添加一個新增的路由設定,如下


config.Routes.MapHttpRoute(
    name: "InsertApi",
    routeTemplate: "api/{controller}/{name}/{category}/{price}/{stock}",
    defaults: new { name = RouteParameter.Optional }
);

  加入此路由設定後就能夠使用 http://localhost:51370/api/Products/ASP.NET/WEB/300/10 此 URI 呼叫 Web API。

 

更新方法


/// <summary>
/// 更新指定產品後回傳清單
/// URI: /api/products/id/name/category/price/stock
/// Method: PUT
/// </summary>
/// <param name="id"></param>
/// <param name="name"></param>
/// <param name="category"></param>
/// <param name="price"></param>
/// <param name="stock"></param>
/// <returns></returns>
public IEnumerable<Product> PutProduct(int id, string name, string category, string price, int stock)
{
    ProductDao productDao = new ProductDao();
    try
    {
        return productDao.UpdateProduct(id, name, category, price, stock);
    }
    catch (Exception)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
}

  更新需要使用 PUT 動詞,除了以上的程式碼之外,也需要跟新增一樣增加 WebApiConfig.cs 中添加一個更新的路由設定,如下


config.Routes.MapHttpRoute(
    name: "UpdateApi",
    routeTemplate: "api/{controller}/{id}/{name}/{category}/{price}/{stock}",
    defaults: new { name = RouteParameter.Optional }
);

  加入此路由設定後就能夠使用 http://localhost:51370/api/Products/1/ASP.NET/NET/350/10 此 URI 呼叫 Web API。

 

刪除方法


/// <summary>
/// 刪除指定編號產品後回傳清單
/// URI: /api/products/1
/// Method: DELETE
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public IEnumerable<Product> DeleteProductById(int id)
{
    ProductDao productDao = new ProductDao();
    try
    {
        return productDao.DeleteProduct(id);
    }
    catch (Exception)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
}

  刪除需要使用 DELETE 動詞,此處就不需要額外添加路由,因為透過 DELETE 動詞可以區分跟 GET 動詞同樣 http://localhost:51370/api/Products/1 網址的方法。

 

  當參考以上的程式碼處理完成後就可以開始測試看看,在此我使用 Fiddler 這個抓取封包的軟體來測試,第一篇文章中也有提到下載點可以去下載用用看,測試如下

取得所有清單

取得編號1的產品

取得 MVC 類別的產品

新增新產品

更新編號1產品

刪除編號1產品

 

  以上就是測試後的畫面,這邊要注的是呼叫 URI 時使用的 HTTP Method 一定要正確,不然就會出現不允許用於存取路徑的錯誤產生,如有遺漏的部分日後將在進行補充。

 

補充


  如要讓 Web API 強制回傳 JSON 格式,可參考保哥此篇文章 如何讓 ASP.NET Web API 無論任何要求都回應 JSON 格式

 

範例程式碼


TWebApi_01.part1.rar

TWebApi_01.part2.rar

 

參考資料


Your First ASP.NET Web API (C#)

ASP.NET WEB API 心得筆記 (1)

[ASP.NET MVC] ASP.NET Web API (2) - 方法與路由

 

 


以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教
如有侵權內容也請您與我反應~謝謝您 :)