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

作者: Mike Wassonby Mike Wasson

本教程介绍如何在控制台应用程序中承载 web API。This tutorial shows how to host a web API inside a console application. ASP.NET Web API 不需要 IIS。ASP.NET Web API does not require IIS. 你可以在自己的主机进程中自承载 web API。You can self-host a web API in your own host process.

新应用程序应使用 OWIN 到自承载 Web API。New applications should use OWIN to self-host Web API. 请参阅使用 OWIN ASP.NET Web API 2See Use OWIN to Self-Host ASP.NET Web API 2.

本教程中使用的软件版本Software versions used in the tutorial

  • Web API 1Web API 1
  • Visual Studio 2012Visual Studio 2012

创建控制台应用程序项目Create the Console Application Project

启动 Visual Studio,然后从起始页中选择 "新建项目"。Start Visual Studio and select New Project from the Start page. 或者,从 "文件" 菜单中选择 "新建",然后选择 "项目"。Or, from the File menu, select New and then Project.

在 "模板" 窗格中,选择 "已安装模板",然后展开视觉对象C# 节点。In the Templates pane, select Installed Templates and expand the Visual C# node. " C#视觉对象" 下选择 " Windows"。Under Visual C#, select Windows. 在项目模板列表中,选择 "控制台应用程序"。In the list of project templates, select Console Application. 将项目命名为 "SelfHost" 并单击 "确定"Name the project "SelfHost" and click OK.

设置目标框架(Visual Studio 2010)Set the Target Framework (Visual Studio 2010)

如果使用的是 Visual Studio 2010,请将目标框架更改为 .NET Framework 4.0。If you are using Visual Studio 2010, change the target framework to .NET Framework 4.0. (默认情况下,项目模板以.Net Framework 客户端配置文件为目标。)(By default, the project template targets the .Net Framework Client Profile.)

在解决方案资源管理器中,右键单击项目,然后选择 "属性"。In Solution Explorer, right-click the project and select Properties. 在 "目标框架" 下拉列表中,将 "目标框架" 更改为 .NET Framework 4.0。In the Target framework dropdown list, change the target framework to .NET Framework 4.0. 出现应用更改提示时,单击 "是"When prompted to apply the change, click Yes.

安装 NuGet 包管理器Install NuGet Package Manager

NuGet 包管理器是将 Web API 程序集添加到 non-ASP.NET 项目的最简单方法。The NuGet Package Manager is the easiest way to add the Web API assemblies to a non-ASP.NET project.

若要检查是否安装了 NuGet 包管理器,请单击 Visual Studio 中的 "工具" 菜单。To check if NuGet Package Manager is installed, click the Tools menu in Visual Studio. 如果你看到名为 " Nuget 包管理器" 的菜单项,则具有 Nuget 包管理器。If you see a menu item called NuGet Package Manager, then you have NuGet Package Manager.

安装 NuGet 包管理器:To install NuGet Package Manager:

  1. 启动 Visual Studio。Start Visual Studio.
  2. 在“工具”菜单上,选择“扩展和更新”。From the Tools menu, select Extensions and Updates.
  3. 在 "扩展和更新" 对话框中,选择 "联机"。In the Extensions and Updates dialog, select Online.
  4. 如果看不到 "NuGet 程序包管理器",请在 "搜索" 框中键入 "nuget 包管理器"。If you don't see "NuGet Package Manager", type "nuget package manager" in the search box.
  5. 选择 NuGet 包管理器,然后单击 "下载"。Select the NuGet Package Manager and click Download.
  6. 下载完成后,系统会提示你进行安装。After the download completes, you will be prompted to install.
  7. 安装完成后,系统可能会提示你重启 Visual Studio。After the installation completes, you might be prompted to restart Visual Studio.

添加 Web API NuGet 包Add the Web API NuGet Package

安装 NuGet 包管理器后,将 Web API 自承载包添加到项目。After NuGet Package Manager is installed, add the Web API Self-Host package to your project.

  1. 从 "工具" 菜单中选择 " NuGet 包管理器"。From the Tools menu, select NuGet Package Manager. 注意:如果看不到此菜单项,请确保已正确安装 NuGet 包管理器。Note: If do you not see this menu item, make sure that NuGet Package Manager installed correctly.
  2. 选择 "管理解决方案的 NuGet 包"Select Manage NuGet Packages for Solution
  3. 在 "管理 NugGet 包" 对话框中,选择 "联机"。In the Manage NugGet Packages dialog, select Online.
  4. 在搜索框中,键入 "WebApi"""。In the search box, type "Microsoft.AspNet.WebApi.SelfHost".
  5. 选择 ASP.NET Web API 己方主机包,然后单击 "安装"。Select the ASP.NET Web API Self Host package and click Install.
  6. 安装包后,单击 "关闭" 以关闭对话框。After the package installs, click Close to close the dialog.

Note

请确保安装名为 WebApi 的包,而不是 AspNetWebApi. SelfHost。Make sure to install the package named Microsoft.AspNet.WebApi.SelfHost, not AspNetWebApi.SelfHost.

创建模型和控制器Create the Model and Controller

本教程使用与入门教程相同的模型和控制器类。This tutorial uses the same model and controller classes as the Getting Started tutorial.

添加一个名为 Product的公共类。Add a public class named 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的公共类。Add a public class named ProductsController. ApiController派生此类。Derive this class from 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));
        }
    }
}

有关此控制器中代码的详细信息,请参阅入门教程。For more information about the code in this controller, see the Getting Started tutorial. 此控制器定义三个 GET 操作:This controller defines three GET actions:

URIURI 说明Description
/api/products/api/products 获取所有产品的列表。Get a list of all products.
/api/products/id/api/products/id 按 ID 获取产品。Get a product by ID.
/api/products/? category =类别/api/products/?category=category 按类别获取产品列表。Get a list of products by category.

承载 Web APIHost the Web API

打开文件 Program.cs 并添加以下 using 语句:Open the file Program.cs and add the following using statements:

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

将以下代码添加到Program类。Add the following code to the Program class.

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 命名空间保留(Optional) Add an HTTP URL Namespace Reservation

此应用程序侦听 http://localhost:8080/This application listens to http://localhost:8080/. 默认情况下,侦听特定的 HTTP 地址需要管理员权限。By default, listening at a particular HTTP address requires administrator privileges. 因此,当你运行本教程时,你可能会收到以下错误: "HTTP 无法注册 URL http://+:8080/" 可通过两种方法来避免此错误:When you run the tutorial, therefore, you may get this error: "HTTP could not register URL http://+:8080/" There are two ways to avoid this error:

  • 以提升的管理员权限运行 Visual Studio,或Run Visual Studio with elevated administrator permissions, or
  • 使用 dism.exe 为你的帐户授予保留 URL 的权限。Use Netsh.exe to give your account permissions to reserve the URL.

若要使用 dism.exe,请使用管理员权限打开命令提示符,然后输入以下命令:To use Netsh.exe, open a command prompt with administrator privileges and enter the following command:following command:

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

其中,*计算机 * 是你的用户帐户。where machine\username is your user account.

完成自承载后,请确保删除该保留:When you are finished self-hosting, be sure to delete the reservation:

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

从客户端应用程序调用 Web API (C#)Call the Web API from a Client Application (C#)

让我们编写一个简单的控制台应用程序来调用 web API。Let's write a simple console application that calls the web API.

向解决方案添加新的控制台应用程序项目:Add a new console application project to the solution:

  • 在解决方案资源管理器中,右键单击解决方案并选择 "添加新项目"。In Solution Explorer, right-click the solution and select Add New Project.
  • 创建一个名为 "ClientApp"的新控制台应用程序。Create a new console application named "ClientApp".

使用 NuGet 包管理器添加 ASP.NET Web API 核心库包:Use NuGet Package Manager to add the ASP.NET Web API Core Libraries package:

  • 从 "工具" 菜单中选择 " NuGet 包管理器"。From the Tools menu, select NuGet Package Manager.
  • 选择 "管理解决方案的 NuGet 包"Select Manage NuGet Packages for Solution
  • 在 "管理 NuGet 包" 对话框中,选择 "联机"。In the Manage NuGet Packages dialog, select Online.
  • 在搜索框中,键入 "WebApi"""。In the search box, type "Microsoft.AspNet.WebApi.Client".
  • 选择 Microsoft ASP.NET Web API 客户端库 "包,然后单击"安装"。Select the Microsoft ASP.NET Web API Client Libraries package and click Install.

将 ClientApp 中的引用添加到 SelfHost 项目:Add a reference in ClientApp to the SelfHost project:

  • 在解决方案资源管理器中,右键单击 ClientApp 项目。In Solution Explorer, right-click the ClientApp project.
  • 选择“添加引用”。Select Add Reference.
  • 在 "引用管理器" 对话框中的 "解决方案" 下,选择 "项目"。In the Reference Manager dialog, under Solution, select Projects.
  • 选择 SelfHost 项目。Select the SelfHost project.
  • 单击“确定”。Click OK.

打开客户端/Program .cs 文件。Open the Client/Program.cs file. 添加以下 using 语句:Add the following using statement:

using System.Net.Http;

添加静态HttpClient实例:Add a static HttpClient instance:

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

添加以下方法以列出所有产品,按 ID 列出产品,并按类别列出产品。Add the following methods to list all products, list a product by ID, and list products by category.

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);
    }
}

上述每种方法都遵循相同的模式:Each of these methods follows the same pattern:

  1. 调用HttpClient GetAsync将 GET 请求发送到相应的 URI。Call HttpClient.GetAsync to send a GET request to the appropriate URI.
  2. 调用HttpResponseMessage. EnsureSuccessStatusCodeCall HttpResponseMessage.EnsureSuccessStatusCode. 如果 HTTP 响应状态是错误代码,则此方法将引发异常。This method throws an exception if the HTTP response status is an error code.
  3. 调用ReadAsAsync<t> 从 HTTP 响应反序列化 CLR 类型。Call ReadAsAsync<T> to deserialize a CLR type from the HTTP response. 此方法是在HttpContentExtensions中定义的扩展方法。This method is an extension method, defined in System.Net.Http.HttpContentExtensions.

GetAsyncReadAsAsync方法都是异步的。The GetAsync and ReadAsAsync methods are both asynchronous. 它们返回表示异步操作的任务对象。They return Task objects that represent the asynchronous operation. 获取Result属性会阻止线程,直到操作完成。Getting the Result property blocks the thread until the operation completes.

有关使用 HttpClient 的详细信息,包括如何发出非阻塞调用,请参阅从 .Net 客户端调用 WEB APIFor more information about using HttpClient, including how to make non-blocking calls, see Calling a Web API From a .NET Client.

在调用这些方法之前,请将 HttpClient 实例上的 BaseAddress 属性设置为 "http://localhost:8080"。Before calling these methods, set the BaseAddress property on the HttpClient instance to "http://localhost:8080". 例如:For example:

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();
}

这应输出以下。This should output the following. (请记得先运行 SelfHost 应用程序。)(Remember to run the SelfHost application first.)

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.