Self-Host ASP.NET Web API 1 (C#)

作者:Mike Wasson

本教學課程說明如何在主控台應用程式內裝載 Web API。 ASP.NET Web API不需要 IIS。 您可以在自己的主機進程中自行裝載 Web API。

新的應用程式應該使用 OWIN 來自我裝載 Web API。 請參閱使用 OWIN Self-Host ASP.NET Web API 2

教學課程中使用的軟體版本

  • Web API 1
  • Visual Studio 2012

建立主控台應用程式專案

啟動 Visual Studio,然後從 [開始] 頁面中選取 [新增專案]。 或者,從 [ 檔案] 功能表中,選取 [ 新增 ],然後選取 [ 專案]。

在 [ 範本] 窗格中,選取 [ 已安裝的範本 ],然後展開 [Visual C# ] 節點。 在 [Visual C#] 底下,選取 [Windows]。 在專案範本清單中,選取 [主控台應用程式]。 將專案命名為 「SelfHost」,然後按一下 [ 確定]。

[新增專案] 對話方塊的螢幕擷取畫面,其中顯示資料夾清單中的 Visual C# 專案,以及以灰色醒目提示Windows Forms應用程式專案。

設定 Visual Studio 2010 (Target Framework)

如果您使用 Visual Studio 2010,請將目標 Framework 變更為 .NET Framework 4.0。 (根據預設,專案範本會以 .Net Framework Client Profile.) 為目標

在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [屬性]。 在 [目標 Framework] 下拉式清單中,將目標 Framework 變更為 .NET Framework 4.0。 當系統提示您套用變更時,按一下 [ ]。

方案總管視窗的螢幕擷取畫面,其中顯示 [目標 Framework] 下拉式清單,其中點 NET Framework 4 專案以藍色醒目提示。

安裝 NuGet 套件管理員

NuGet 套件管理員是將 Web API 元件新增至 non-ASP.NET 專案最簡單的方式。

若要檢查是否已安裝 NuGet 套件管理員,請按一下 Visual Studio 中的 [工具 ] 功能表。 如果您看到名為 NuGet 套件管理員的功能表項目,則您有 NuGet 套件管理員。

若要安裝 NuGet 套件管理員:

  1. 啟動 Visual Studio。
  2. 從 [工具] 功能表中,選取 [擴充功能和更新]
  3. 在 [擴充功能和更新] 對話方塊中,選取 [線上]。
  4. 如果您沒有看到 [NuGet 套件管理員],請在搜尋方塊中輸入 「nuget 套件管理員」。
  5. 選取 NuGet 套件管理員,然後按一下 [ 下載]。
  6. 下載完成之後,系統會提示您安裝。
  7. 安裝完成之後,系統可能會提示您重新開機 Visual Studio。

[延伸模組和更新] 對話方塊的螢幕擷取畫面,其中顯示搜尋結果中的 NuGet 套件管理員,以灰色醒目提示。

新增 Web API NuGet 套件

安裝 NuGet 套件管理員之後,請將 Web API Self-Host套件新增至您的專案。

  1. 從 [ 工具] 功能表中,選取 [NuGet 套件管理員]。 注意:如果您沒有看到此功能表項目,請確定 NuGet 套件管理員已正確安裝。
  2. 選取 [管理方案的 NuGet 套件]
  3. 在 [ 管理 NugGet 套件 ] 對話方塊中,選取 [ 線上]。
  4. 在搜尋方塊中,輸入 「Microsoft.AspNet.WebApi.SelfHost」。
  5. 選取 [自我裝載] 套件 ASP.NET Web API,然後按一下 [安裝]。
  6. 安裝套件之後,按一下 [ 關閉 ] 以關閉對話方塊。

注意

請務必安裝名為 Microsoft.AspNet.WebApi.SelfHost 的套件,而不是 AspNetWebApi.SelfHost。

[管理 NuGet 套件] 對話方塊的螢幕擷取畫面,其中顯示 Microsoft A P 點 Net Web A P I 自我主機,以藍色醒目提示。

建立模型和控制器

本教學課程使用與消費者入門教學課程相同的模型和控制器類別。

新增名為 的 Product 公用類別。

namespace SelfHost
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }
}

新增名為 的 ProductsController 公用類別。 從 System.Web.Http.ApiController衍生此類別。

namespace SelfHost
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Web.Http;
    
    public class ProductsController : ApiController
    {
        Product[] products = new Product[]  
        {  
            new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },  
            new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },  
            new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }  
        };

        public IEnumerable<Product> GetAllProducts()
        {
            return products;
        }

        public Product GetProductById(int id)
        {
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return product;
        }

        public IEnumerable<Product> GetProductsByCategory(string category)
        {
            return products.Where(p => string.Equals(p.Category, category,
                    StringComparison.OrdinalIgnoreCase));
        }
    }
}

如需此控制器中程式碼的詳細資訊,請參閱消費者入門教學課程。 此控制器會定義三個 GET 動作:

URI 描述
/api/products 取得所有產品的清單。
/api/products/id 依識別碼取得產品。
/api/products/?category=category 依類別取得產品清單。

裝載 Web API

開啟 Program.cs 檔案,並新增下列 using 語句:

using System.Web.Http;
using System.Web.Http.SelfHost;

將下列程式碼新增至 Program 類別。

var config = new HttpSelfHostConfiguration("http://localhost:8080");

config.Routes.MapHttpRoute(
    "API Default", "api/{controller}/{id}", 
    new { id = RouteParameter.Optional });

using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
    server.OpenAsync().Wait();
    Console.WriteLine("Press Enter to quit.");
    Console.ReadLine();
}

(選擇性) 新增 HTTP URL 命名空間保留

此應用程式會接 http://localhost:8080/ 聽 。 根據預設,在特定 HTTP 位址上接聽需要系統管理員許可權。 因此,當您執行本教學課程時,可能會收到此錯誤:「HTTP 無法註冊 URL http://+:8080/" ;有兩種方式可避免此錯誤:

  • 使用提高的系統管理員許可權執行 Visual Studio,或
  • 使用Netsh.exe授與帳戶保留 URL 的許可權。

若要使用Netsh.exe,請使用系統管理員許可權開啟命令提示字元,然後輸入下列命令:下列命令:

netsh http add urlacl url=http://+:8080/ user=machine\username

其中 machine\username 是您使用者帳戶。

當您完成自我裝載時,請務必刪除保留:

netsh http delete urlacl url=http://+:8080/

從用戶端應用程式 (C#) 呼叫 Web API

讓我們撰寫呼叫 Web API 的簡單主控台應用程式。

將新的主控台應用程式專案新增至方案:

  • 在 [方案總管] 中,以滑鼠右鍵按一下方案,然後選取 [新增專案]。
  • 建立名為 「ClientApp」 的新主控台應用程式。

方案總管螢幕擷取畫面,其中顯示以白色醒目提示的滑鼠右鍵功能表項目 [新增] 和 [新增專案]。

使用 NuGet 套件管理員來新增 ASP.NET Web API核心程式庫套件:

  • 從 [工具] 功能表中,選取 [NuGet 套件管理員]。
  • 選取 [管理方案的 NuGet 套件]
  • 在 [ 管理 NuGet 套件] 對話方塊中,選取 [ 線上]。
  • 在搜尋方塊中,輸入 「Microsoft.AspNet.WebApi.Client」。
  • 選取 [Microsoft ASP.NET Web API 用戶端程式庫套件],然後按一下 [安裝]。

將 ClientApp 中的參考新增至 SelfHost 專案:

  • 在 方案總管中,以滑鼠右鍵按一下 ClientApp 專案。
  • 選取 [新增參考]
  • 在 [ 參考管理員] 對話方塊的 [ 方案] 底下,選取 [ 專案]。
  • 選取 SelfHost 專案。
  • 按一下 [確定]。

[參考管理員] 對話方塊的螢幕擷取畫面,其中顯示 [自我裝載] 專案,其中以藍色方塊反白顯示。

開啟 Client/Program.cs 檔案。 新增下列 using 語句:

using System.Net.Http;

新增靜態 HttpClient 實例:

namespace Client
{
    class Program
    {
        static HttpClient client = new HttpClient();
    }
}

新增下列方法來列出所有產品、依識別碼列出產品,以及依類別列出產品。

static void ListAllProducts()
{
    HttpResponseMessage resp = client.GetAsync("api/products").Result;
    resp.EnsureSuccessStatusCode();

    var products = resp.Content.ReadAsAsync<IEnumerable<SelfHost.Product>>().Result;
    foreach (var p in products)
    {
        Console.WriteLine("{0} {1} {2} ({3})", p.Id, p.Name, p.Price, p.Category);
    }
}

static void ListProduct(int id)
{
    var resp = client.GetAsync(string.Format("api/products/{0}", id)).Result;
    resp.EnsureSuccessStatusCode();

    var product = resp.Content.ReadAsAsync<SelfHost.Product>().Result;
    Console.WriteLine("ID {0}: {1}", id, product.Name);
}

static void ListProducts(string category)
{
    Console.WriteLine("Products in '{0}':", category);

    string query = string.Format("api/products?category={0}", category);

    var resp = client.GetAsync(query).Result;
    resp.EnsureSuccessStatusCode();

    var products = resp.Content.ReadAsAsync<IEnumerable<SelfHost.Product>>().Result;
    foreach (var product in products)
    {
        Console.WriteLine(product.Name);
    }
}

每個方法都遵循相同的模式:

  1. 呼叫 HttpClient.GetAsync 以將 GET 要求傳送至適當的 URI。
  2. 呼叫 HttpResponseMessage.EnsureSuccessStatusCode。 如果 HTTP 回應狀態為錯誤碼,這個方法會擲回例外狀況。
  3. 呼叫ReadAsAsync < T >以從 HTTP 回應還原序列化 CLR 類型。 此方法是在 System.Net.Http.HttpContentExtensions中定義的擴充方法。

GetAsyncReadAsAsync方法都是非同步。 它們會傳回代表非同步作業的 Task 物件。 取得 Result 屬性會封鎖執行緒,直到作業完成為止。

如需使用 HttpClient 的詳細資訊,包括如何進行非封鎖呼叫,請參閱 從 .NET 用戶端呼叫 Web API

呼叫這些方法之前,請將 HttpClient 實例上的 BaseAddress 屬性設定為 「 http://localhost:8080 」。 例如:

static void Main(string[] args)
{
    client.BaseAddress = new Uri("http://localhost:8080");

    ListAllProducts();
    ListProduct(1);
    ListProducts("toys");

    Console.WriteLine("Press Enter to quit.");
    Console.ReadLine();
}

這應該會輸出下列內容。 (請記得先執行 SelfHost 應用程式。)

1 Tomato Soup 1.0 (Groceries)
2 Yo-yo 3.75 (Toys)
3 Hammer 16.99 (Hardware)
ID 1: Tomato Soup
Products in 'toys':
Yo-yo
Press Enter to quit.

主控台視窗的螢幕擷取畫面,其中顯示與識別碼和類別相關聯的輸出產品清單。