介绍 在我的学习WebAPI系列中,我已经写了很多关于WebAPI的东西,但是我错过了一个重要的主题,那就是托管一个ASP。净之前。您可以从下面的系列文章开始了解WebAPI。 RESTful日#1:企业级应用程序架构,使用实体框架、通用存储库模式和工作单元的Web api。RESTful日#2:使用Unity容器和引导程序在Web api中使用依赖注入实现控制反转。RESTful日#3:在ASP中使用控制反转和依赖注入解决依赖关系的依赖关系。NET Web api与Unity容器和管理扩展框架(MEF)。RESTful日#4:使用MVC 4 Web api中的属性路由自定义URL重写/路由。RESTful日#5:使用操作过滤器的Web api中基于基本身份验证和令牌的自定义授权。RESTful日#6:使用操作过滤器、异常过滤器和NLog在Web api中进行请求日志记录和异常处理/日志记录。RESTful日#7:使用NUnit和Moq框架在WebAPI中进行单元测试和集成测试(第一部分)。使用NUnit和Moq框架在WebAPI中进行单元测试和集成测试(第二部分)。净Web api。RESTful日#10:创建自托管的ASP。NET WebAPI与CRUD操作在Visual Studio 2010 在IIS中托管WebAPI非常简单,与托管典型的ASP的方式更类似。净的web应用程序。在本文中,我将解释如何在独立于IIS的另一个进程中托管WebAPI。 我将解释如何使用Entity Framework 4.0快速创建具有CRUD操作的WebAPI,然后将其托管在独立的服务器上。我将通过充当客户机的控制台应用程序调用服务端点。您可以使用任何客户机来检查服务端点并验证其功能。我将尝试用实际实现来解释这个主题,然后在Visual Studio 2010中围绕。net framework 4.0这样的目标框架创建一个服务和一个测试客户端。 之前的项目 创建ASP的传统方法。NET REST服务从Visual Studio中选择一个WebAPI项目,创建一个控制器,公开端点并将其托管在IIS上。但是,在Windows上创建一个自托管的web API时,我们需要使用一个基于Windows或控制台的应用程序,该应用程序在编译时生成一个EXE,该EXE可以通过命令提示符用于托管。你可以宿主WebAPI 2与OWIN,这是非常直接的帮助与下面提到的两个NuGet包: Microsoft.Owin.SelfHost Microsoft.AspNet.WebApi.OwinSelfHost 但我们会为WebAPI 1做托管不会在这个应用中使用OWINn。 步骤1:创建控制台应用程序 打开Visual Studio并创建一个名为SelfHostedAPI的新控制台应用程序 我们将向它添加一个WebAPI控制器并编写用于CRUD操作的代码,但在此之前,我们需要一个数据库和用于执行数据库事务的通信。我将使用EntityFramework处理数据库事务。 步骤2:创建数据库 您可以创建任何您想要的数据库。我使用SQL Server并将创建一个名为WebAPIdb的数据库,其中包含一个名为Products的表,用于执行CRUD操作。这个数据库中还有更多的表,但我们不会使用它们。 我将随本文提供该数据库脚本。product表的脚本如下: 隐藏,收缩,复制Code
1: 2: USE [WebApiDb] 3: GO 4: /****** Object: Table [dbo].[Products] Script Date: 5: 04/14/2016 11:02:51 ******/ 6: SET ANSI_NULLS ON 7: GO 8: SET QUOTED_IDENTIFIER ON 9: GO 10: SET ANSI_PADDING ON 11: GO 12: CREATE TABLE [dbo].[Products]( 13: [ProductId] [int] 14: IDENTITY(1,1) NOT NULL, 15: [ProductName] [varchar](50) NOT 16: NULL, 17: CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED 18: 19: ( 20: [ProductId] ASC 21: )WITH (PAD_INDEX = OFF, 22: STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS 23: = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 24: ) ON [PRIMARY] 25: GO 26: SET ANSI_PADDING OFF 27: GO
我们已经完成了数据库的创建,现在让我们建立用于通信的实体层。 步骤3:使用实体框架设置数据访问 在您的Visual Studio中,选择Tool->Packet Manager->Packet Manager控制台来添加实体框架包: 我将安装Entity Framework 5.0,因为它与。net Framework 4.0一起工作得很好。因此,选择SelfHostedAPI作为默认项目,输入命令Install-Package entityframework- version 5.0.0并按回车。 成功安装后,您将看到Entity framework dll被添加到项目中。 现在右键单击项目并添加新项目。选择ADO。Net实体数据模型来自Visual c#项目列表。 系统会提示您生成模型的选项。选择从数据库生成选项并继续。 在下一步中提供数据库详细信息之后,选择您想要与模型映射的数据库表。我只选择了products表,因为我们将只对这个表执行CRUD。 单击Finish,您的实体数据模型将与数据库表映射一起准备好。您将看到生成了一个App.Config文件,并将特定于所选数据库的连接字符串添加到该配置文件中。 现在我们需要生成一个对象上下文来处理事务,objectset充当映射到表的模型类。 右键单击edmx视图,并在上下文菜单中单击“添加代码生成项目”。 在打开的项目列表窗口中选择ADO。净EntityObject属如下图所示。 选择它并按OK,这将生成您的模型1。包含同一类中的上下文和实体的tt类。现在我们已经完成了所有与数据库相关的内容。现在,我将创建一个WebAPI控制器,并在其中放置所有CRUD操作。 步骤4:添加WebAPI控制器 因为我们需要一个API来对数据库执行所有凝块操作,所以我们必须在项目中添加一个WebAPI控制器类。由于这是一个控制台应用程序而不是WebAPI项目,所以我们没有为添加控制器定义适当的结构。为了便于理解,您可以创建自己的文件夹结构。我直接在项目中添加一个名为ProductController的API控制器类。 右键单击project,添加一个新项目,并从项目列表中选择WebAPI controller类。你可以任意命名它。我将其命名为ProductController 生成的类派生自APIController类。这意味着它是一个有效的WebAPI控制器类。这个类默认情况下包含了默认的CRUD方法,这些方法有以下实现: 隐藏,收缩,复制Code
1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Net; 5: using System.Net.Http; 6: using System.Web.Http; 7: 8: namespace SelfHostedAPI 9: { 10: public class ProductController : ApiController 11: { 12: // GET api/<controller> 13: public IEnumerable<string> Get() 14: { 15: return new string[] { "value1", "value2" }; 16: } 17: 18: // GET api/<controller>/5 19: public string Get(int id) 20: { 21: return "value"; 22: } 23: 24: // POST api/<controller> 25: public void Post([FromBody]string value) 26: { 27: } 28: 29: // PUT api/<controller>/5 30: public void Put(int id, [FromBody]string value) 31: { 32: } 33: 34: // DELETE api/<controller>/5 35: public void Delete(int id) 36: { 37: } 38: } 39: }
我们将使用这些默认方法,但为DB操作编写我们自己的业务逻辑。 步骤5:添加CRUD方法 我们将添加用于创建、读取、更新和删除的所有四个方法。注意,我们不会使用UnitOfWork或Repository之类的设计模式进行数据持久化,因为我们的主要目标是自托管此服务并公开其CRUD端点。 1. 获取所有记录 修改Get()方法以返回一个产品实体列表,并使用Model1.cs文件中生成的WebAPIEntities类来获取产品列表。这里的方法名也表示方法的类型,所以基本上这是服务的Get方法,也应该作为方法类型Get从客户端调用。这同样适用于我们在这个类中为所有CRUD操作编写的每个方法。 隐藏,复制Code
1: // GET api/<controller> 2: public IEnumerable<Product> Get() 3: { 4: var entities=new WebApiDbEntities(); 5: return entities.Products; 6: }
在上面提到的代码库中,我们返回产品实体的IEnumerable of,并使用WebApiDbEntities(自动生成的上下文类)的object来获取使用entity . products的所有对象。 2. 按id获取产品 修改Get(int id)方法以返回产品实体。该方法接受一个id,并返回特定于该id的产品。您可以使用验证和检查增强该方法,以使其更健壮,但为了理解这个概念,我只是直接这样做。 隐藏,复制Code
1: // GET api/<controller>/5 2: public Product Get(int id) 3: { 4: var entities = new WebApiDbEntities(); 5: return entities.Products.FirstOrDefault(p=>p.ProductId==id); 6: }
3.创建产品 隐藏,复制Code
1: // POST api/<controller> 2: public bool Post([FromBody]Product product) 3: { 4: var entities = new WebApiDbEntities(); 5: entities.AddToProducts(product); 6: var i = entities.SaveChanges(); 7: return i > 0; 8: }
顾名思义,这是一个Post方法,它从请求主体中获取产品类对象,并将该产品添加到实体中。注意,只有在执行entity . savechanges()时,产品才会被添加到实际的数据库中。该方法实际上是将记录插入到数据库中,如果成功插入else 0,则返回1。 4. 编辑/更新产品 隐藏,复制Code
1: // PUT api/<controller>/5 2: public bool Put(int id, [FromBody]Product product) 3: { 4: using (var entities = new WebApiDbEntities()) 5: { 6: var prod = (from p in entities.Products 7: where p.ProductId == id 8: select p).FirstOrDefault(); 9: 10: prod.ProductName = product.ProductName; 11: var i=entities.SaveChanges(); 12: return i > 0; 13: } 14: }
由于这是一个更新操作,我们将其命名为Put方法,并且正如名称所表示的,它是Put类型。该方法将id和product对象作为参数,其中首先从数据库中获取具有作为参数传递的id的实际产品,然后使用参数product的详细信息修改该产品,然后再次保存到数据库中。在本例中,我们只有可以更改的产品名称,因为id是固定的主键,因此我们在此方法中更新产品的产品名称,并将更改保存到该实体。 5. 删除产品 隐藏,复制Code
1: // DELETE api/<controller>/5 2: public bool Delete(int id) 3: { 4: using (var entities = new WebApiDbEntities()) 5: { 6: var prod = (from p in entities.Products 7: where p.ProductId == id 8: select p).FirstOrDefault(); 9: 10: entities.Products.DeleteObject(prod); 11: var i=entities.SaveChanges(); 12: return i > 0; 13: } 14: }
上述delete方法为delete类型,并接受产品的id作为参数。该方法从数据库w.r.t.传递的id中获取product,然后删除该产品并保存更改。这个实现非常简单,而且不言自明。 通过这种方法,我们已经完成了需要公开的所有凝乳端点。正如你所看到的,我没有为端点应用任何特殊的路由,而是依赖于WebAPI提供的默认路由,即api/<controller> 步骤6:托管WebAPI 这是这篇文章最重要的部分,“自我托管”。还记得在创建SelfHostedAPI项目时,它是一个控制台应用程序,因此它附带在项目中创建的Program.cs文件。cs文件包含主方法,即应用程序的入口点。我们将使用这个main方法为WebAPI编写自托管代码。 在我们编写任何代码之前,我们需要通过包管理器控制台添加一个nuget包。这个包包含托管特定的类需要主机API在控制台应用,即独立在单独的进程其他;IIS。请注意,在WebAPI 2中,我们有提供这种灵活性的OWIN中间件。 因为我们使用的是Visual Studio 2010和。net Framework 4.0,所以我们需要安装一个特定版本的包,名为Microsoft.AspNet.WebApi.SelfHost。我找到的兼容版本是版本4.0.20710 因此,打开包管理器控制台,选择默认项目,并执行命令“Install-Package Microsoft.AspNet.WebApi”。SelfHost - version 4.0.20710” 这将为您的项目安装包,现在您可以使用它来实现。 打开Program.cs文件并添加一个名称空间 隐藏,复制Code
1: using System.Web.Http.SelfHost;
在main方法中,定义要公开的端点的基地址。我选择端点为8082。确保您在管理员模式下运行Visual Studio,否则您将不得不更改一些配置来让它为您工作。我从这个ASP中得到了以下解释。NET文章解释配置变化, 添加一个HTTP URL名称空间保留 此应用程序侦听http://localhost:8080/。默认情况下,监听特定HTTP地址需要管理员权限。因此,当您运行教程时,您可能会得到以下错误:“HTTP无法注册URL http://+:8080/”。有两种方法可以避免此错误: 以提升的管理员权限运行Visual Studio,或使用Netsh.exe给您的帐户保留URL的权限。 使用Netsh。exe,打开一个具有管理员权限的命令提示符,输入以下命令: 隐藏,复制Code
netsh http add urlacl url=http://+:8080/ user=machineusername
其中,machineusername是您的用户帐户。 当您完成自托管时,请务必删除预订: 隐藏,复制Code
netsh http delete urlacl url=http://+:8080/"
1. 为SelfHostConfiguration定义一个对象,如下所示 隐藏,复制Code
1: var config = new HttpSelfHostConfiguration("http://localhost:8082");
2. 定义WebAPI的默认路由 隐藏,复制Code
1: config.Routes.MapHttpRoute( 2: "API Default", "api/{controller}/{id}", 3: new { id = RouteParameter.Optional });
这是我们的服务在运行时将遵循的默认路径。 3.在进程中启动服务器 隐藏,复制Code
1: using (var server = new HttpSelfHostServer(config)) 2: { 3: server.OpenAsync().Wait(); 4: Console.WriteLine("Server started...."); 5: Console.WriteLine("Press Enter to quit."); 6: Console.ReadLine(); 7: }
上面的代码用于托管和启动我们创建的服务的服务器。正如您所看到的,在单独的进程中启动我们的服务只需几行代码,而且我们实际上不需要依赖IIS服务器。 因此,我们的程序。cs成为 隐藏,复制Code
1: using System; 2: using System.Web.Http; 3: using System.Web.Http.SelfHost; 4: 5: namespace SelfHostedAPI 6: { 7: class Program 8: { 9: static void Main(string[] args) 10: { 11: var config = new HttpSelfHostConfiguration("http://localhost:8082"); 12: 13: config.Routes.MapHttpRoute( 14: "API Default", "api/{controller}/{id}", 15: new { id = RouteParameter.Optional }); 16: 17: using (var server = new HttpSelfHostServer(config)) 18: { 19: server.OpenAsync().Wait(); 20: Console.WriteLine("Server started...."); 21: Console.WriteLine("Press Enter to quit."); 22: Console.ReadLine(); 23: } 24: } 25: } 26: }
现在,当您按F5启动应用程序时,您将启动服务器,服务端点将侦听您的请求。我们将使用即将创建的自己的测试客户端测试端点。但在那之前,让我们启动服务器。 编译应用程序,并在windows资源管理器中导航到bindebug文件夹中的SelfHostedAPI.exe,并作为管理员运行它。 您的服务器将立即启动。 当您在浏览器中输入URL http://localhost:8082时,您将看到服务器实际上返回了一个资源not found的响应 这意味着我们的端口正在监听请求。 WebAPI测试客户端 既然我们知道我们的服务已经启动并运行,现在就可以通过测试客户机对它们进行测试了。您可以使用自己的测试客户机,也可以构建一个作为控制台应用程序的测试客户机。我正在。net中构建一个单独的测试客户端来测试这些服务。 步骤1:添加一个控制台应用程序 使用名称APITestClient或您选择的名称在相同或其他解决方案中添加控制台应用程序。我们将使用Program.cs来编写调用WebAPI方法的所有代码。但在此之前,我们需要安装nuget包来帮助我们创建httpclient,我们将通过它进行API调用。 步骤2:添加web客户端包 打开库包管理器,选择APITestClient作为默认项目,执行命令“Install-Package Microsoft.AspNet.WebApi”。客户- version 4.0.20710” 这将在您的测试客户端项目中安装必要的包及其依赖项。 步骤3:安装客户端 时间到代码,打开program.cs并添加名称空间 隐藏,复制Code
1: using System.Net.Http; 2: using System.Net.Http.Headers;
定义HttpClient变量 隐藏,复制Code
1: private static readonly HttpClient Client = new HttpClient();
在Main方法中,用基本需求初始化客户端,比如要调用的服务的基本地址和媒体类型 隐藏,复制Code
1: Client.BaseAddress = new Uri("http://localhost:8082"); 2: Client.DefaultRequestHeaders.Accept.Clear(); 3: Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
现在我们可以编写CRUD调用方法并从main方法中调用它们。 步骤4:调用方法 1. GetAllProducts 隐藏,复制Code
1: /// <summary> 2: /// Fetch all products 3: /// </summary> 4: private static void GetAllProducts() 5: { 6: HttpResponseMessage resp = Client.GetAsync("api/product").Result; 7: resp.EnsureSuccessStatusCode(); 8: 9: var products = resp.Content.ReadAsAsync<IEnumerable<SelfHostedAPI.Product>>().Result.ToList(); 10: if (products.Any()) 11: { 12: Console.WriteLine("Displaying all the products..."); 13: foreach (var p in products) 14: { 15: Console.WriteLine("{0} {1} ", p.ProductId, p.ProductName); 16: } 17: } 18: }
上面的方法通过HttpClient实例调用“api/product”端点,并期望从服务得到HttpResponseMessage结果。注意,它使用方法GetAsync来进行端点调用,这表明它正在调用REST API的Get方法。 我们的数据库中有大约6条记录需要显示 让我们通过从主方法中调用方法来运行应用程序,但在那之前,确保你的WebAPI在控制台应用程序中运行,就像我们之前做的那样: 隐藏,复制Code
1: private static void Main(string[] args) 2: { 3: Client.BaseAddress = new Uri("http://localhost:8082"); 4: Client.DefaultRequestHeaders.Accept.Clear(); 5: Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 6: GetAllProducts(); 7: 8: Console.WriteLine("Press Enter to quit."); 9: Console.ReadLine(); 10: }
结果如下所示。 华友好,我们把所有的产品从数据库送到这个客户那里。 这证明了我们的服务是良好的托管和工作良好。我们也可以以类似的方式定义其他方法并测试API端点。 2. GetProduct () 此方法按id获取product。 隐藏,复制Code
1: /// <summary> 2: /// Get product by id 3: /// </summary> 4: private static void GetProduct() 5: { 6: const int id = 1; 7: var resp = Client.GetAsync(string.Format("api/product/{0}", id)).Result; 8: resp.EnsureSuccessStatusCode(); 9: 10: var product = resp.Content.ReadAsAsync<SelfHostedAPI.Product>().Result; 11: Console.WriteLine("Displaying product having id : " + id); 12: Console.WriteLine("ID {0}: {1}", id, product.ProductName); 13: }
同样,这个方法是不言自明的。我默认有卡尔led产品id为“1”的方法,您可以根据您的需要定制方法。只需编译并运行该方法。我们得到, 因此我们得到了结果。 3.AddProduct () 隐藏,复制Code
1: /// <summary> 2: /// Add product 3: /// </summary> 4: private static void AddProduct() 5: { 6: var newProduct = new Product() { ProductName = "Samsung Phone" }; 7: var response = Client.PostAsJsonAsync("api/product", newProduct); 8: response.Wait(); 9: if (response.Result.IsSuccessStatusCode) 10: { 11: Console.WriteLine("Product added."); 12: } 13: }
在上述方法,我试图添加一个新产品名为“三星手机”在我们现有的产品列表。由于我们在database中自动生成id,所以不需要提供产品的id。它将以唯一的id自动插入到数据库中。注意,该方法使用Post类型方法调用API端点。运行应用程序。 上面说产品添加了。现在让我们转到数据库并检查我们的表。在SQL Server数据库中对表执行select查询,我们将在表中添加一个id为“7”的新产品,其名称为“Samsung Phone”, 4. EditProduct () 隐藏,复制Code
1: /// <summary> 2: /// Edit product 3: /// </summary> 4: private static void EditProduct() 5: { 6: const int productToEdit = 4; 7: var product = new Product() { ProductName = "Xamarin" }; 8: 9: var response = 10: Client.PutAsJsonAsync("api/product/" + productToEdit, product); 11: response.Wait(); 12: if (response.Result.IsSuccessStatusCode) 13: { 14: Console.WriteLine("Product edited."); 15: } 16: 17: }
在上面的代码中,我正在编辑一个产品id为“4”的产品,并将现有的产品名称,即iPad更改为Xamarin。注意,该方法使用Put类型方法调用API端点。运行应用程序。 在数据库中 我们在这里看到,我们现有的产品iPad被更新为新名字“Xamarin”。我们看到还添加了一个id为8的新产品。这是因为我们再次从main方法中调用了add方法。理想情况下,我们应该在测试edit方法时将其注释掉。 5. DeleteProduct () 隐藏,复制Code
1: /// <summary> 2: /// Delete product 3: /// </summary> 4: private static void DeleteProduct() 5: { 6: const int productToDelete = 2; 7: var response = Client.DeleteAsync("api/product/" + productToDelete); 8: response.Wait(); 9: if (response.Result.IsSuccessStatusCode) 10: { 11: Console.WriteLine("Product deleted."); 12: } 13: }
在上面的方法中,我们删除了id为2的产品。注意,该方法使用Delete类型方法调用API端点。运行应用程序。 产品被删除。让我们检查一下数据库, 我们看到id为“2”的产品已被删除。 因此,我们已经在一个自托管的WebAPI上执行了所有的CRUD操作。结果和预期的一样。下面是Program.cs文件的合并代码。 隐藏,收缩,复制Code
1: #region Using namespaces 2: using System; 3: using System.Collections.Generic; 4: using System.Linq; 5: using System.Net.Http; 6: using System.Net.Http.Headers; 7: using SelfHostedAPI; 8: #endregion 9: 10: namespace APITestClient 11: { 12: internal class Program 13: { 14: #region Private member variables 15: private static readonly HttpClient Client = new HttpClient(); 16: #endregion 17: 18: #region Main method for execution entry 19: /// <summary> 20: /// Main method 21: /// </summary> 22: /// <paramname="args"></param> 23: private static void Main(string[] args) 24: { 25: Client.BaseAddress = new Uri("http://localhost:8082"); 26: Client.DefaultRequestHeaders.Accept.Clear(); 27: Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 28: GetAllProducts(); 29: GetProduct(); 30: AddProduct(); 31: EditProduct(); 32: DeleteProduct(); 33: Console.WriteLine("Press Enter to quit."); 34: Console.ReadLine(); 35: } 36: #endregion 37: 38: #region Private client methods 39: /// <summary> 40: /// Fetch all products 41: /// </summary> 42: private static void GetAllProducts() 43: { 44: HttpResponseMessage resp = Client.GetAsync("api/product").Result; 45: resp.EnsureSuccessStatusCode(); 46: 47: var products = resp.Content.ReadAsAsync<IEnumerable<SelfHostedAPI.Product>>().Result.ToList(); 48: if (products.Any()) 49: { 50: Console.WriteLine("Displaying all the products..."); 51: foreach (var p in products) 52: { 53: Console.WriteLine("{0} {1} ", p.ProductId, p.ProductName); 54: } 55: } 56: } 57: 58: /// <summary> 59: /// Get product by id 60: /// </summary> 61: private static void GetProduct() 62: { 63: const int id = 1; 64: var resp = Client.GetAsync(string.Format("api/product/{0}", id)).Result; 65: resp.EnsureSuccessStatusCode(); 66: 67: var product = resp.Content.ReadAsAsync<SelfHostedAPI.Product>().Result; 68: Console.WriteLine("Displaying product having id : " + id); 69: Console.WriteLine("ID {0}: {1}", id, product.ProductName); 70: } 71: 72: /// <summary> 73: /// Add product 74: /// </summary> 75: private static void AddProduct() 76: { 77: var newProduct = new Product() { ProductName = "Samsung Phone" }; 78: var response = Client.PostAsJsonAsync("api/product", newProduct); 79: response.Wait(); 80: if (response.Result.IsSuccessStatusCode) 81: { 82: Console.WriteLine("Product added."); 83: } 84: } 85: 86: /// <summary> 87: /// Edit product 88: /// </summary> 89: private static void EditProduct() 90: { 91: const int productToEdit = 4; 92: var product = new Product() { ProductName = "Xamarin" }; 93: 94: var response = 95: Client.PutAsJsonAsync("api/product/" + productToEdit, product); 96: response.Wait(); 97: if (response.Result.IsSuccessStatusCode) 98: { 99: Console.WriteLine("Product edited."); 100: } 101: 102: } 103: 104: /// <summary> 105: /// Delete product 106: /// </summary> 107: private static void DeleteProduct() 108: { 109: const int productToDelete = 2; 110: var response = Client.DeleteAsync("api/product/" + productToDelete); 111: response.Wait(); 112: if (response.Result.IsSuccessStatusCode) 113: { 114: Console.WriteLine("Product deleted."); 115: } 116: } 117: 118: #endregion 119: } 120: }
结论 我试图使本教程保持简单和直观,并解释了使用实体框架创建具有所有CRUD操作的简单WebAPI的每个步骤,最后self托管该API并对其进行测试。我希望你喜欢阅读这篇文章。您可以从github下载完整的源代码。 本文转载于:http://www.diyabc.com/frontweb/news414.html