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)

如果使用 Visual Studio 2010,请将目标框架更改为 .NET Framework 4.0。 (默认情况下,项目模板面向 .Net Framework 客户端配置文件.)

在Průzkumník řešení中,右键单击项目并选择“属性”。 在“目标框架”下拉列表中,将目标框架更改为 .NET Framework 4.0。 当系统提示应用更改时,单击“ ”。

“Průzkumník řešení”窗口的屏幕截图,其中显示了“目标框架”下拉列表,其中点 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 S P 点 Net Web A P I 自我主机。

创建模型和控制器

本教程使用与Začínáme教程相同的模型和控制器类。

添加名为 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));
        }
    }
}

有关此控制器中的代码的详细信息,请参阅Začínáme教程。 此控制器定义三个 GET 操作:

URI 说明
/api/products 获取所有产品的列表。
/api/products/id 按 ID 获取产品。
/api/products/?category=category 按类别获取产品列表。

托管 Web API

打开 File 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

其中 计算机\用户名 是用户帐户。

完成自承载后,请务必删除预留:

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

从客户端应用程序 (C#) 调用 Web API

让我们编写一个调用 Web API 的简单控制台应用程序。

将新的控制台应用程序项目添加到解决方案:

  • 在Průzkumník řešení中,右键单击解决方案,然后选择“添加新项目”。
  • 创建名为“ClientApp”的新控制台应用程序。

Průzkumník řešení的屏幕截图,其中显示了右键单击菜单项“添加”和“新建项目”,以白色突出显示。

使用 NuGet 包管理器添加 ASP.NET Web API核心库包:

  • 在“工具”菜单中,选择 “NuGet 包管理器”。
  • 选择“管理解决方案的 NuGet 包
  • 在“ 管理 NuGet 包 ”对话框中,选择“ 联机”。
  • 在搜索框中,键入“Microsoft.AspNet.WebApi.Client”。
  • 选择 Microsoft ASP.NET Web API客户端库包,然后单击“安装”。

在 ClientApp 中添加对 SelfHost 项目的引用:

  • 在Průzkumník řešení中,右键单击 ClientApp 项目。
  • 选择“添加引用”。
  • “引用管理器 ”对话框中的 “解决方案”下,选择“ 项目”。
  • 选择 SelfHost 项目。
  • 单击 “确定”

“引用管理器”对话框的屏幕截图,其中显示了“自承载”项目,其中突出显示了蓝色框。

打开 Client/Program.cs 文件。 添加以下 using 语句:

using System.Net.Http;

添加静态 HttpClient 实例:

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

添加以下方法来列出所有产品、按 ID 列出产品,以及按类别列出产品。

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 方法都是异步方法。 它们 返回表示 异步操作的任务对象。 获取 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.

控制台窗口的屏幕截图,其中显示了与 I D 和类别关联的产品的输出列表。