Merge pull request #4696 from aspnet/master

Update live with current master
pull/4758/head^2
Rick Anderson 2017-10-31 15:16:09 -10:00 committed by GitHub
commit af613fa516
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 69 additions and 57 deletions

View File

@ -1,14 +1,22 @@
## Implement the other CRUD operations
We'll add `Create`, `Update`, and `Delete` methods to the controller. These are variations on a theme, so I'll just show the code and highlight the main differences. Build the project after adding or changing code.
In the following sections, `Create`, `Update`, and `Delete` methods are added to the controller.
### Create
Add the following `Create` method.
[!code-csharp[Main](../../tutorials/first-web-api/sample/TodoApi/Controllers/TodoController.cs?name=snippet_Create)]
This is an HTTP POST method, indicated by the [`[HttpPost]`](/aspnet/core/api/microsoft.aspnetcore.mvc.httppostattribute) attribute. The [`[FromBody]`](/aspnet/core/api/microsoft.aspnetcore.mvc.frombodyattribute) attribute tells MVC to get the value of the to-do item from the body of the HTTP request.
The preceding code is an HTTP POST method, indicated by the [`[HttpPost]`](/aspnet/core/api/microsoft.aspnetcore.mvc.httppostattribute) attribute. The [`[FromBody]`](/aspnet/core/api/microsoft.aspnetcore.mvc.frombodyattribute) attribute tells MVC to get the value of the to-do item from the body of the HTTP request.
The `CreatedAtRoute` method returns a 201 response, which is the standard response for an HTTP POST method that creates a new resource on the server. `CreatedAtRoute` also adds a Location header to the response. The Location header specifies the URI of the newly created to-do item. See [10.2.2 201 Created](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html).
The `CreatedAtRoute` method:
* Returns a 201 response. HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
* Adds a Location header to the response. The Location header specifies the URI of the newly created to-do item. See [10.2.2 201 Created](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html).
* Uses the "GetTodo" named route to create the URL. The "GetTodo" named route is defined in `GetById`:
[!code-csharp[Main](../../tutorials/first-web-api/sample/TodoApi/Controllers/TodoController.cs?name=snippet_GetByID&highlight=1-2)]
### Use Postman to send a Create request
@ -18,7 +26,7 @@ The `CreatedAtRoute` method returns a 201 response, which is the standard respon
* Select the **Body** radio button
* Select the **raw** radio button
* Set the type to JSON
* In the key-value editor, enter a Todo item such as
* In the key-value editor, enter a Todo item such as
```json
{
@ -28,20 +36,16 @@ The `CreatedAtRoute` method returns a 201 response, which is the standard respon
```
* Select **Send**
* Select the Headers tab in the lower pane and copy the **Location** header:
![Headers tab of the Postman console](../../tutorials/first-web-api/_static/pmget.png)
You can use the Location header URI to access the resource you just created. Recall the `GetById` method created the `"GetTodo"` named route:
```csharp
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(long id)
```
The Location header URI can be used to access the new item.
### Update
Add the following `Update` method:
[!code-csharp[Main](../../tutorials/first-web-api/sample/TodoApi/Controllers/TodoController.cs?name=snippet_Update)]
`Update` is similar to `Create`, but uses HTTP PUT. The response is [204 (No Content)](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html). According to the HTTP spec, a PUT request requires the client to send the entire updated entity, not just the deltas. To support partial updates, use HTTP PATCH.
@ -50,8 +54,12 @@ public IActionResult GetById(long id)
### Delete
Add the following `Delete` method:
[!code-csharp[Main](../../tutorials/first-web-api/sample/TodoApi/Controllers/TodoController.cs?name=snippet_Delete)]
The response is [204 (No Content)](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html).
The `Delete` response is [204 (No Content)](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html).
Test `Delete`:
![Postman console showing 204 (No Content) response](../../tutorials/first-web-api/_static/pmd.png)

View File

@ -2,7 +2,7 @@
The preceding code:
* Defines an empty controller class. In the next sections, we'll add methods to implement the API.
* Defines an empty controller class. In the next sections, methods are added to implement the API.
* The constructor uses [Dependency Injection](xref:fundamentals/dependency-injection) to inject the database context (`TodoContext `) into the controller. The database context is used in each of the [CRUD](https://wikipedia.org/wiki/Create,_read,_update_and_delete) methods in the controller.
* The constructor adds an item to the in-memory database if one doesn't exist.
@ -20,22 +20,22 @@ These methods implement the two GET methods:
Here is an example HTTP response for the `GetAll` method:
```
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/10.0
Date: Thu, 18 Jun 2015 20:51:10 GMT
Content-Length: 82
[{"Key":"1", "Name":"Item1","IsComplete":false}]
[
{
"id": 1,
"name": "Item1",
"isComplete": false
}
]
```
Later in the tutorial I'll show how you can view the HTTP response using [Postman](https://www.getpostman.com/) or [curl](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/curl.1.html).
Later in the tutorial I'll show how the HTTP response can be viewed with [Postman](https://www.getpostman.com/) or [curl](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/curl.1.html).
### Routing and URL paths
The `[HttpGet]` attribute specifies an HTTP GET method. The URL path for each method is constructed as follows:
* Take the template string in the controllers route attribute:
* Take the template string in the controllers `Route` attribute:
[!code-csharp[Main](../../tutorials/first-web-api/sample/TodoApi/Controllers/TodoController.cs?name=TodoController&highlight=3)]
@ -44,14 +44,14 @@ The `[HttpGet]` attribute specifies an HTTP GET method. The URL path for each me
In the `GetById` method:
```csharp
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(long id)
```
[!code-csharp[Main](../../tutorials/first-web-api/sample/TodoApi/Controllers/TodoController.cs?name=snippet_GetByID&highlight=1-2)]
`"{id}"` is a placeholder variable for the ID of the `todo` item. When `GetById` is invoked, it assigns the value of "{id}" in the URL to the method's `id` parameter.
`Name = "GetTodo"` creates a named route and allows you to link to this route in an HTTP Response. I'll explain it with an example later. See [Routing to Controller Actions](xref:mvc/controllers/routing) for detailed information.
`Name = "GetTodo"` creates a named route. Named routes:
* Enable the app to create an HTTP link using the route name.
* Are explained later in the tutorial.
### Return values
@ -59,6 +59,6 @@ The `GetAll` method returns an `IEnumerable`. MVC automatically serializes the o
In contrast, the `GetById` method returns the more general `IActionResult` type, which represents a wide range of return types. `GetById` has two different return types:
* If no item matches the requested ID, the method returns a 404 error. This is done by returning `NotFound`.
* If no item matches the requested ID, the method returns a 404 error. Returning `NotFound` returns an HTTP 404 response.
* Otherwise, the method returns 200 with a JSON response body. This is done by returning an `ObjectResult`
* Otherwise, the method returns 200 with a JSON response body. Returning `ObjectResult` returns an HTTP 200 response.

View File

@ -1,14 +1,14 @@
## Overview
Here is the API that youll create:
This tutorial creates the following API:
|API | Description | Request body | Response body |
|API | Description | Request body | Response body |
|--- | ---- | ---- | ---- |
|GET /api/todo | Get all to-do items | None | Array of to-do items|
|GET /api/todo/{id} | Get an item by ID | None | To-do item|
|POST /api/todo | Add a new item | To-do item | To-do item |
|PUT /api/todo/{id} | Update an existing item   | To-do item | None |
|DELETE /api/todo/{id}     | Delete an item     | None | None|
|GET /api/todo | Get all to-do items | None | Array of to-do items|
|GET /api/todo/{id} | Get an item by ID | None | To-do item|
|POST /api/todo | Add a new item | To-do item | To-do item |
|PUT /api/todo/{id} | Update an existing item   | To-do item | None |
|DELETE /api/todo/{id}     | Delete an item     | None | None|
<br>
@ -16,10 +16,10 @@ The following diagram shows the basic design of the app.
![The client is represented by a box on the left and submits a request and receives a response from the application, a box drawn on the right. Within the application box, three boxes represent the controller, the model, and the data access layer. The request comes into the application's controller, and read/write operations occur between the controller and the data access layer. The model is serialized and returned to the client in the response.](../../tutorials/first-web-api/_static/architecture.png)
* The client is whatever consumes the web API (mobile app, browser, etc). We arent writing a client in this tutorial. We'll use [Postman](https://www.getpostman.com/) or [curl](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/curl.1.html) to test the app.
* The client is whatever consumes the web API (mobile app, browser, etc.). This tutorial doesn't create a client. [Postman](https://www.getpostman.com/) or [curl](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/curl.1.html) is used as the client to test the app.
* A *model* is an object that represents the data in your application. In this case, the only model is a to-do item. Models are represented as C# classes, also know as **P**lain **O**ld **C**# **O**bject (POCOs).
* A *model* is an object that represents the data in the app. In this case, the only model is a to-do item. Models are represented as C# classes, also know as **P**lain **O**ld **C**# **O**bject (POCOs).
* A *controller* is an object that handles HTTP requests and creates the HTTP response. This app will have a single controller.
* A *controller* is an object that handles HTTP requests and creates the HTTP response. This app has a single controller.
* To keep the tutorial simple, the app doesnt use a persistent database. The sample app stores to-do items in an in-memory database.

View File

@ -2,6 +2,6 @@
* [ASP.NET Core Web API Help Pages using Swagger](xref:tutorials/web-api-help-pages-using-swagger)
* [Routing to Controller Actions](xref:mvc/controllers/routing)
* For information about deploying your API, see [Publishing and Deployment](xref:publishing/index).
* For information about deploying an API, see [Publishing and Deployment](xref:publishing/index).
* [View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/tutorials/first-web-api/sample). See [how to download](xref:tutorials/index#how-to-download-a-sample).
* [Postman](https://www.getpostman.com/)

View File

@ -1,10 +1,12 @@
## Register the database context
In order to inject the database context into the controller, we need to register it with the [dependency injection](xref:fundamentals/dependency-injection) container. Register the database context with the service container using the built-in support for [dependency injection](xref:fundamentals/dependency-injection). Replace the contents of the *Startup.cs* file with the following:
In this step, the database context is registered with the [dependency injection](xref:fundamentals/dependency-injection) container. Services (such as the DB context) that are registered with the dependency injection (DI) container are available to the controllers.
Register the DB context with the service container using the built-in support for [dependency injection](xref:fundamentals/dependency-injection). Replace the contents of the *Startup.cs* file with the following code:
[!code-csharp[Main](../../tutorials/first-web-api/sample/TodoApi/Startup.cs?highlight=2,4,12)]
The preceding code:
* Removes the code we're not using.
* Specifies an in-memory database is injected into the service container.
* Removes the code that is not used.
* Specifies an in-memory database is injected into the service container.

View File

@ -157,7 +157,7 @@ Think of AlgorithmConfiguration as the top-level factory. The configuration serv
When CreateNewDescriptor is called, fresh key material is created solely for this call, and a new IAuthenticatedEncryptorDescriptor is produced which wraps this key material and the algorithmic information required to consume the material. The key material could be created in software (and held in memory), it could be created and held within an HSM, and so on. The crucial point is that any two calls to CreateNewDescriptor should never create equivalent IAuthenticatedEncryptorDescriptor instances.
The AlgorithmConfiguration type serves as the entry point for key creation routines such as [automatic key rolling](../implementation/key-management.md#data-protection-implementation-key-management). To change the implementation for all future keys, set the AuthenticatedEncryptorConfiguration property in KeyManagementOptions.
The AlgorithmConfiguration type serves as the entry point for key creation routines such as [automatic key rolling](../implementation/key-management.md#key-expiration-and-rolling). To change the implementation for all future keys, set the AuthenticatedEncryptorConfiguration property in KeyManagementOptions.
# [ASP.NET Core 1.x](#tab/aspnetcore1x)
@ -169,6 +169,6 @@ Think of IAuthenticatedEncryptorConfiguration as the top-level factory. The conf
When CreateNewDescriptor is called, fresh key material is created solely for this call, and a new IAuthenticatedEncryptorDescriptor is produced which wraps this key material and the algorithmic information required to consume the material. The key material could be created in software (and held in memory), it could be created and held within an HSM, and so on. The crucial point is that any two calls to CreateNewDescriptor should never create equivalent IAuthenticatedEncryptorDescriptor instances.
The IAuthenticatedEncryptorConfiguration type serves as the entry point for key creation routines such as [automatic key rolling](../implementation/key-management.md#data-protection-implementation-key-management). To change the implementation for all future keys, register a singleton IAuthenticatedEncryptorConfiguration in the service container.
The IAuthenticatedEncryptorConfiguration type serves as the entry point for key creation routines such as [automatic key rolling](../implementation/key-management.md#key-expiration-and-rolling). To change the implementation for all future keys, register a singleton IAuthenticatedEncryptorConfiguration in the service container.
---

View File

@ -16,7 +16,7 @@ uid: tutorials/first-web-api
By [Rick Anderson](https://twitter.com/RickAndMSFT) and [Mike Wasson](https://github.com/mikewasson)
In this tutorial, youll build a web API for managing a list of "to-do" items. You wont build a UI.
This tutorial builds a web API for managing a list of "to-do" items. A user interface (UI) is not created.
There are 3 versions of this tutorial:
@ -48,23 +48,23 @@ In the **New ASP.NET Core Web Application - TodoApi** dialog, select the **Web A
### Launch the app
In Visual Studio, press CTRL+F5 to launch the app. Visual Studio launches a browser and navigates to `http://localhost:port/api/values`, where *port* is a randomly-chosen port number. Chrome, Edge, and Firefox display the following:
In Visual Studio, press CTRL+F5 to launch the app. Visual Studio launches a browser and navigates to `http://localhost:port/api/values`, where *port* is a randomly chosen port number. Chrome, Microsoft Edge, and Firefox display the following output:
```
["value1","value2"]
```
```
### Add a model class
A model is an object that represents the data in your application. In this case, the only model is a to-do item.
A model is an object that represents the data in the app. In this case, the only model is a to-do item.
Add a folder named "Models". In Solution Explorer, right-click the project. Select **Add** > **New Folder**. Name the folder *Models*.
Note: The model classes go anywhere in your project, but the *Models* folder is used by convention.
Note: The model classes go anywhere in in the project. The *Models* folder is used by convention for model classes.
Add a `TodoItem` class. Right-click the *Models* folder and select **Add** > **Class**. Name the class `TodoItem` and select **Add**.
Replace the generated code with the following:
Update the `TodoItem` class with the following code:
[!code-csharp[Main](first-web-api/sample/TodoApi/Models/TodoItem.cs)]
@ -76,7 +76,7 @@ The *database context* is the main class that coordinates Entity Framework funct
Add a `TodoContext` class. Right-click the *Models* folder and select **Add** > **Class**. Name the class `TodoContext` and select **Add**.
Replace the generated code with the following:
Replace the class with the following code:
[!code-csharp[Main](first-web-api/sample/TodoApi/Models/TodoContext.cs)]
@ -84,17 +84,17 @@ Replace the generated code with the following:
### Add a controller
In Solution Explorer, right-click the *Controllers* folder. Select **Add** > **New Item**. In the **Add New Item** dialog, select the **Web API Controller Class** template. Name the class `TodoController`.
In Solution Explorer, right-click the *Controllers* folder. Select **Add** > **New Item**. In the **Add New Item** dialog, select the **Web API Controller Class** template. Name the class `TodoController`.
![Add new Item dialog with controller in search box and web API controller selected](first-web-api/_static/new_controller.png)
Replace the generated code with the following:
Replace the class with the following code:
[!INCLUDE[code and get todo items](../includes/webApi/getTodoItems.md)]
### Launch the app
In Visual Studio, press CTRL+F5 to launch the app. Visual Studio launches a browser and navigates to `http://localhost:port/api/values`, where *port* is a randomly chosen port number. If you're using Chrome, Edge or Firefox, the data will be displayed. If you're using IE, IE will prompt to you open or save the *values.json* file. Navigate to the `Todo` controller we just created `http://localhost:port/api/todo`.
In Visual Studio, press CTRL+F5 to launch the app. Visual Studio launches a browser and navigates to `http://localhost:port/api/values`, where *port* is a randomly chosen port number. Navigate to the `Todo` controller at `http://localhost:port/api/todo`.
[!INCLUDE[last part of web API](../includes/webApi/end.md)]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -10,7 +10,7 @@ namespace TodoApi.Controllers
public class TodoController : Controller
{
private readonly TodoContext _context;
#endregion
#endregion
public TodoController(TodoContext context)
{
@ -30,6 +30,7 @@ namespace TodoApi.Controllers
return _context.TodoItems.ToList();
}
#region snippet_GetByID
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(long id)
{
@ -41,6 +42,7 @@ namespace TodoApi.Controllers
return new ObjectResult(item);
}
#endregion
#endregion
#region snippet_Create
[HttpPost]
public IActionResult Create([FromBody] TodoItem item)