程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 【ASP.NET Web API教程】2.1 創建支持CRUD操作的Web API,apicrud

【ASP.NET Web API教程】2.1 創建支持CRUD操作的Web API,apicrud

編輯:關於.NET

【ASP.NET Web API教程】2.1 創建支持CRUD操作的Web API,apicrud


參考頁面:

http://www.yuanjiaocheng.net/ASPNET-CORE/core-middleware.html

http://www.yuanjiaocheng.net/ASPNET-CORE/core-exception.html

http://www.yuanjiaocheng.net/ASPNET-CORE/core-static-files.html

http://www.yuanjiaocheng.net/ASPNET-CORE/setup-mvc.html

http://www.yuanjiaocheng.net/ASPNET-CORE/mvc-design-pattern.html

2.1 Creating a Web API that Supports CRUD Operations
2.1 創建支持CRUD操作的Web API

By Mike Wasson | January 28, 2012
作者:Mike Wasson | 日期:2012-1-28

本文引自:http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web-api-that-supports-crud-operations

注:本文是ASP.NET Web API系列教程第2章中的第1篇,因此標題采用了“2.1” — 譯者注

This tutorial shows how to support CRUD operations in an HTTP service using ASP.NET Web API.
本教程展示如果在使用ASP.NET Web API的HTTP服務中支持CRUD操作。

CRUD stands for "Create, Read, Update, and Delete," which are the four basic database operations. Many HTTP services also model CRUD operations through REST or REST-like APIs.
CRUD是指“創建(C)、讀取(R)、更新(U)和刪除(D)”,它們是四個基本的數據庫操作。許多HTTP服務也會通過REST或類REST的API模擬CRUD操作。

In this tutorial, you will build a very simple web API to manage a list of products. Each product will contain a name, price, and category (such as "toys" or "hardware"), plus a product ID.
在本教程中,你將建立一個十分簡單的Web API來管理一列產品。每個產品包含一個name(名稱)、price(價格)和category(分類)(如,“toys(玩具)”、“hardware(硬件)”等),還有一個產品的ID。

Download the completed project.
下載完整的項目

The products API will expose following methods.
這個產品API將暴露以下方法(見表2-1)。

表2-1. Products API暴露的HTTP方法 Action
動作 HTTP method
HTTP方法 Relative URI
相對URI Get a list of all products
獲取全部產品列表 GET /api/products Get a product by ID
通過ID獲取一個產品 GET /api/products/id Get a product by category
通過分類獲取產品 GET /api/products?category=category Create a new product
創建一個新產品 POST /api/products Update a product
更新一個產品 PUT /api/products/id Delete a product
刪除一個產品 DELETE /api/products/id

Notice that some of the URIs include the product ID in path. For example, to get the product whose ID is 28, the client sends a GET request for http://hostname/api/products/28.
注意,有些URI在路徑中包含了產品ID。例如,要得到ID為28的產品,客戶端要發送一個http://hostname/api/products/28的GET請求。

Resources
資源

The products API defines URIs for two resource types:
這個產品API定義了兩種資源類型的URI(見表2-2):

表2-2. 資源類型 Resource
資源 URI The list of all the products.
所有產品的列表 /api/products An individual product.
個別產品 /api/products/id

Methods
方法

The four main HTTP methods (GET, PUT, POST, and DELTETE) can be mapped to CRUD operations as follows:
四種主要的HTTP方法(GET、PUT、POST和DELETE)可以按如下方式映射到CRUD操作:

  • GET retrieves the representation of the resource at a specified URI. GET should have no side effects on the server.
    GET接收指定URI上的資源表達式。GET在服務器上應當沒有副效應。
  • PUT updates a resource at a specified URI. PUT can also be used to create a new resource at a specified URI, if the server allows clients to specify new URIs. For this tutorial, the API will not support creation through PUT.
    PUT更新指定URI上的資源。如果服務器允許客戶端指定新URI,PUT也可以用於在指定URI上創建新資源。對於本教程,API將不支持通過PUT的創建。
  • POST creates a new resource. The server assigns the URI for the new object and returns this URI as part of the response message.
    POST創建新資源。服務器為新對象分配URI,並把這個URI作為響應消息的一部分加以返回。
  • DELETE deletes a resource at a specified URI.
    DELETE刪除指定URI上的資源。

Note: The PUT method replaces the entire product entity. That is, the client is expected to send a complete representation of the updated product. If you want to support partial updates, the PATCH method is preferred. This tutorial does not implement PATCH.
注:PUT方法替換整個產品實體。即,期望客戶端發送一個更新產品的完整表達式。如果想支持部分更新,最好用PATCH方法。本教程不實現PATCH。

Create a New Web API Project
創建新的Web API項目

Start by running Visual Studio 2010 and select New Project from the Start page. Or, from the File menu, select New and then Project.
啟動VS 2012,並在“開始頁”選擇“新項目”。或從“文件”菜單選擇“新建”,然後選擇“項目”。

In the Templates pane, select Installed Templates and expand the Visual C# node. Under Visual C#, select Web. In the list of project templates, select ASP.NET MVC 4 Web Application. Name the project "ProductStore" and click OK.
在“模板”面板中選擇“已安裝模板”,並展開“Visual C#”節點。選擇該節點下的“Web”。在項目模板列表中選擇“ASP.NET MVC 4 Web應用程序”。將此項目命名為“ProductStore”,點擊“OK”(見圖2-1)。

WebAPI2-1

圖2-1. 創建ProductStore項目

In the New ASP.NET MVC 4 Project dialog, select Web API and click OK.
在“新的ASP.NET MVC 4項目”對話框中選擇“Web API”,點擊“OK”(如圖2-2)。

WebAPI2-2

圖2-2. 選擇Web API模板

Adding a Model
添加模型

A model is an object that represents the data in your application. In ASP.NET Web API, you can use strongly typed CLR objects as models, and they will automatically be serialized to XML or JSON for the client.
模型是表示你應用程序中數據的一種對象。在ASP.NET Web API中,你可以使用強類型的CRL(公共語言運行時)對象作為模型,而它們將被自動化地序列化成用於客戶端的XML或JSON。

For the ProductStore API, our data consists of products, so we'll create a new class named Product.
對於這個ProductStore API,其數據由產品組成,因此,我們將創建一個名為Product的新類。

If Solution Explorer is not already visible, click the View menu and select Solution Explorer. In Solution Explorer, right-click the Models folder. From the context meny(menu), select Add, then select Class. Name the class "Product".
如果“解決方案資源管理器”此時尚不可見,點擊“視圖”菜單,並選擇“解決方案資源管理器”。在“解決方案資源管理器”中,右擊“Models”文件夾。從上下菜單中選擇“添加”,然後選擇“類”。將這個類命名為“Product”(如圖2-3所示)。

WebAPI2-3

圖2-3. 創建Product類

Add the following properties to the Product class.
將以下屬性添加到這個Product類。

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

Adding a Repository
添加存儲庫

We need to store a collection of products. It’s a good idea to separate the collection from our service implementation. That way, we can change the backing store without rewriting the service class. This type of design is called the repository pattern. Start by defining a generic interface for the repository.
我們需要存儲產品集合。將這個集合與我們的服務實現分開是一種好的思想。這樣,我們可以修改後台存儲而不必重寫服務類。這種設計類型稱為存儲庫模式。首先從定義存儲庫的泛型接口開始。

In Solution Explorer, right-click the Models folder. Select Add, then select New Item.
在“解決方案資源管理器”中,右擊“Models”文件夾。選擇“添加”,然後選擇“新項”(如圖2-4所示)。

WebAPI2-4

圖2-4. 創建新項

In the Templates pane, select Installed Templates and expand the C# node. Under C#, select Code. In the list of code templates, select Interface. Name the interface "IProductRepository".
在“模板”面板中,選擇“已安裝模板”,並展開“C#”節點,選擇“代碼”。在代碼模板列表中選擇“接口”。將此接口命名為“IProductRepository”(如圖2-5所示)。

WebAPI2-5

圖2-5. 創建接口

Add the following implementation:
添加以下實現:

namespace ProductStore.Models
{ 
    public interface IProductRepository 
    { 
        IEnumerable<Product> GetAll(); 
        Product Get(int id); 
        Product Add(Product item); 
        void Remove(int id); 
        bool Update(Product item); 
    } 
}

Now add another class to the Models folder, named "ProductRepository." This class will implement the IProductRespository interface. Add the following implementation:
現在,把另一個類添加到Models文件夾,名稱為“ProductRepository”。這個類將實現這個IProductRespository接口。添加以下實現:

namespace ProductStore.Models 
{ 
    public class ProductRepository : IProductRepository 
    { 
        private List<Product> products = new List<Product>(); 
        private int _nextId = 1; 
        public ProductRepository() 
        { 
            Add(new Product { Name = "Tomato soup", Category = "Groceries", Price = 1.39M }); 
            Add(new Product { Name = "Yo-yo", Category = "Toys", Price = 3.75M }); 
            Add(new Product { Name = "Hammer", Category = "Hardware", Price = 16.99M }); 
        } 
        public IEnumerable<Product> GetAll() 
        { 
            return products; 
        } 
        public Product Get(int id) 
        { 
            return products.Find(p => p.Id == id); 
        } 
        public Product Add(Product item) 
        { 
            if (item == null) 
            { 
                throw new ArgumentNullException("item"); 
            } 
            item.Id = _nextId++; 
            products.Add(item); 
            return item; 
        } 
        public void Remove(int id) 
        { 
            products.RemoveAll(p => p.Id == id); 
        } 
        public bool Update(Product item) 
        { 
            if (item == null) 
            { 
                throw new ArgumentNullException("item"); 
            } 
            int index = products.FindIndex(p => p.Id == item.Id); 
            if (index == -1) 
            { 
                return false; 
            } 
            products.RemoveAt(index); 
            products.Add(item); 
            return true; 
        } 
    } 
}

The repository keeps the list in local memory. This is OK for a tutorial, but in a real application, you would store the data externally, either a database or in cloud storage. The repository pattern will make it easier to change the implementation later.
該存儲庫在本地內存中保持了一個產品列表。對一個教程而言這就行了,但在一個真實應用程序中,你要在外部存儲這些數據,可以是一個數據庫,或是雲存儲庫。這種存儲庫模式會使今後對這個實現的修改很容易。

Adding a Web API Controller
添加Web API控制器

If you have worked with ASP.NET MVC, then you are already familiar with controllers. In ASP.NET Web API, a controller is a class that handles HTTP requests from the client. The New Project wizard created two controllers for you when it created the project. To see them, expand the Controllers folder in Solution Explorer.
如果你曾使用過ASP.NET MVC,對控制器是熟悉的。在ASP.NET Web API中,控制器是一種處理客戶端HTTP請求的類。“新項目”向導在創建項目時,為你創建了兩個控制器。要看到它們,可以在“解決方案資源管理器”中展開Controllers文件夾。

  • HomeController is a traditional ASP.NET MVC controller. It is responsible for serving HTML pages for the site, and is not directly related to our web API.
    HomeController一個傳統的ASP.NET MVC控制器。它負責對網站的HTML頁面進行服務,而與Web API無直接關系。
  • ValuesController is an example WebAPI controller.
    ValuesController是一個WebAPI控制器例子。

Go ahead and delete ValuesController, by right-clicking the file in Solution Explorer and selecting Delete. Now add a new controller, as follows:
繼續並刪除這個ValuesController,在“解決方案資源管理器”中右擊這個文件,並選擇“刪除”。現在,添加一個新控制器,操作如下:

In Solution Explorer, right-click the the Controllers folder. Select Add and then select Controller.
在“解決方案資源管理器”中,右擊Controllers文件夾。選擇“添加”,然後選擇“控制器”(如圖2-6所示)。

WebAPI2-6

圖2-6. 添加控制器

In the Add Controller wizard, name the controller "ProductsController". In the Template drop-down list, select Empty API Controller. Then click Add.
在“添加控制器”向導中,將此控制器命名為“ProductsController”。在“模板”下拉列表中選擇“空的API控制器”。然後點擊“添加”(如圖2-7所示)。

WebAPI2-7

圖2-7. 創建API控制器

It is not necessary to put your contollers into a folder named Controllers. The folder name is not important; it is simply a convenient way to organize your source files.
把控制器放在Controllers文件夾中不是必須的。文件夾名稱並不重要,這只是組織你資源文件的一種簡單的約定方式。

The Add Controller wizard will create a file named ProductsController.cs in the Controllers folder. If this file is not open already, double-click the file to open it. Add the following using statement:
“添加控制器”向導將在Controllers文件夾中創建一個名為ProductsController.cs的文件。如果這個文件尚未打開,雙擊此文件打開它。添加以下的using語句:

using ProductStore.Models;

Add a field that holds an IProductRepository instance.
添加一個保存IProductRepository實例的字段:

public class ProductsController : ApiController
{
    static readonly IProductRepository repository = new ProductRepository();
}

Calling new ProductRepository() in the controller is not the best design, because it ties the controller to a particular implementation of IProductRepository. For a better approach, see Using the Web API Dependency Resolver.
在控制器中調用new ProductRepository()不是最好的設計,因為它把控制器綁定到了IProductRepository的一個特定實現上了。更好的辦法參見“使用Web API依賴性解析器”。

Getting a Resource
獲取資源

The ProductStore API will expose several "read" operations as HTTP GET methods:
這個ProductStore API將把幾個“讀取”操作暴露成HTTP的GET方法(見表2-3):

表2-3. 幾個讀取產品的URI Action
動作 HTTP method
HTTP方法 Relative URI
相對URI Get a list of all products
獲取所有產品列表 GET /api/products Get a product by ID
根據ID獲得一個產品 GET /api/products/id Get a product by category
根據分類獲取產品 GET /api/products?category=category

Here is the method to get the list of all products:
以下是獲取所有產品列表的方法:

public IEnumerable<Product> GetAllProducts()
{
    return repository.GetAll();
}

The method name starts with "Get", so by convention it maps to GET requests. Also, because the method has no parameters, it maps to a URI that does not contain an "id" segment in the path.
該方法名以“Get”開頭,故根據約定,它用來映射GET請求。另外,因為該方法無參數,它映射到路徑中不含“id”片段的URI。

Here is the method to get a product by ID:
以下是根據ID獲取產品的方法:

public Product GetProduct(int id) 
{ 
    Product item = repository.Get(id); 
    if (item == null) 
    { 
        throw new HttpResponseException(HttpStatusCode.NotFound);  
    } 
    return item; 
}

This method name also starts with "Get", but the method has a parameter named id. This parameter is mapped to the "id" segment of the URI path. The ASP.NET Web API framework automatically converts the ID to the correct data type (int) for the parameter.
這個方法名也以“Get”開頭,但該方法有一個名為id的參數。該參數被映射成URI路徑的“id”片段。ASP.NET Web API框架自動地把這個ID轉換成用於參數的正確的數據類型(int)。

The GetProduct method throws an exception of type HttpResponseException if id is not valid. This exception will be translated by the framework into a 404 (Not Found) error.
如果id無效,GetProduct會拋出一個HttpResponseException類型的異常。這個異常被框架轉換成一個404(未找到)錯誤。

Finally, here is the method to find products by category:
最後,以下是根據分類查找產品的方法:

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

If the request URI has a query string, Web API tries to match the query parameters to parameters on the controller method. Therefore, a URI of the form "api/products?category=category" will map to this method.
如果請求URI有一個查詢字符串,Web API會試圖把這些查詢參數(查詢字符串中的參數 — 譯者注)匹配成該控制器方法的參數。因此,一個“api/products?category=category”形式的URI會映射給這個方法。

Creating a Resource
創建資源

To create a new product, the client sends an HTTP POST request, with the new product in the body of the request message.
為了創建一個新產品,客戶端要發送一個HTTP的POST請求,在該請求的消息體中含有這個新產品。

Here is a simple implementation of the method:
以下是此方法的一個簡單實現:

// Not the final implementation!
// 非最終實現!
public Product PostProduct(Product item)
{
    item = repository.Add(item);
    return item;
}

To handle POST requests, we define a method whose name starts with "Post...". The method takes a parameter of type Product. By default, parameters with complex types are deserialized from the request body. Therefore, we expect the client to send us a serialized representation of a product object, using either XML or JSON for the serialization.
為了處理POST請求,我們要定義以“Post…”開頭的方法。該方法采用一個Product類型的參數。默認地,復合類型的參數是通過請求體來解序列化的。因此,我們希望客戶端給我們發送的是產品對象的一種序列化的表達式,用XML或JSON進行這種序列化。

This implementation will work, but it is missing a couple of things.
這個實現會生效,但它缺少兩樣東西:

  • Response code: By default, the Web API framework sets the response status code to 200 (OK). But according to the HTTP/1.1 protocol, when a POST request results in the creation of a resource, the server should reply with status 201 (Created).
    響應碼(Response code):默認地,Web API框架把響應狀態碼設置為200(OK)。但根據HTTP/1.1協議,在POST請求形成資源創建時,服務器應當用狀態201(已創建)進行回答。
  • Location: When the server creates a resource, it should include the URI of the new resource in the Location header of the response.
    Location報頭:當服務器創建一個資源時,它應當在響應的Location報頭中包含新資源的URI。

ASP.NET Web API makes it easy to manipulate the HTTP response message. Here is the improved implementation:
ASP.NET Web API操縱HTTP響應消息是很容易的。以下是經改進的實現:

public HttpResponseMessage PostProduct(Product item) 
{ 
    item = repository.Add(item); 
    var response = Request.CreateResponse<Product>(HttpStatusCode.Created, item); 
    string uri = Url.Link("DefaultApi", new { id = item.Id }); 
    response.Headers.Location = new Uri(uri); 
    return response; 
}

Notice that the method return type is now HttpResponseMessage. By returning an HttpResponseMessage instead of a Product, we can control the details of the HTTP response message, including the status code and the Location header.
注意,方法的返回類型現在是HttpResponseMessage。通過返回一個HttpResponseMessage而不是Product,我們可以控制HTTP響應消息的細節,包括狀態碼和Location報頭。

The CreateResponse method creates an HttpResponseMessage and automatically writes a serialized representation of the Product object into the body fo of the response message.
這個CreateResponse方法創建一個HttpResponseMessage,並自動地把一個序列化的Product對象表達式寫入響應消息體。

This example does not validate the Product. For information about model validation, see Model Validation in ASP.NET Web API.
此例不驗證Product。關於模型驗證的信息,參閱“ASP.NET Web API中的模型驗證”。

Updating a Resource
更新資源

Updating a product with PUT is straightforward:
用PUT更新一個產品是很直觀的:

public void PutProduct(int id, Product product) 
{ 
    product.Id = id; 
    if (!repository.Update(product)) 
    { 
        throw new HttpResponseException(HttpStatusCode.NotFound); 
    } 
}

The method name starts with "Put...", so Web API matches it to PUT requests. The method takes two parameters, the product ID and the updated product. The id parameter is taken from the URI path, and the product parameter is deserialized from the request body. By default, the ASP.NET Web API framework takes simple parameter types from the route and complex types from the request body.
方法名以“Put…”開頭,因此,Web API把它與PUT請求進行匹配。此方法采用兩個參數,產品ID和被更新產品。Id參數取自URI路徑,而product參數通過請求解序列化。默認地,ASP.NET Web API框架通過路由獲取簡單參數,而通過請求體獲取復合類型。

Deleting a Resource
刪除資源

To delete a resourse, define a "Delete..." method.
為了刪除一個資源,要定義一個“Delete…”方法:

public HttpResponseMessage DeleteProduct(int id) 
{ 
    repository.Remove(id); 
    return new HttpResponseMessage(HttpStatusCode.NoContent); 
}

According to the HTTP specification, the DELETE method must be idempotent, meaning that several DELETE requests to the same URI must have the same effect as a single DELETE request. Therefore, the method should not return an error code if the product was already deleted.
根據HTTP規范,DELETE方法必須是冪等的,意即,對同一URI的幾個DELETE請求必須與一個單一的DELETE請求具有同樣的效果。因此,如果產品已被刪除,該方法不應該返回一個錯誤代碼。

If a DELETE request succeeds, it can return status 200 (OK) with an entity-body that describes the status, or status 202 (Accepted) if the deletion is still pending, or status 204 (No Content) with no entity body. In this example, the method returns status 204.
一個成功的DELETE請求,可以返回200(OK)狀態,並帶有一個描述該狀態的條目體;也可以在刪除未決的情況下返回202(Accepted)狀態;或者返回無條目體的204(No Content)狀態。在本例中,該方法返回204狀態。

作者簡介:

WebAPI2-1
By Mike Wasson, Mike Wasson is a programmer-writer at Microsoft.
Mike Wasson著,Mike Wasson是微軟的一位程序員著作人。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved