aspnetcore/tutorials/first-web-api/includes/first-web-api7.md
:::moniker range="= aspnetcore-7.0"
This tutorial teaches the basics of building a controller-based web API that uses a database. Another approach to creating APIs in ASP.NET Core is to create Minimal APIs. For help with choosing between Minimal APIs and controller-based APIs, see xref:fundamentals/apis. For a tutorial on creating a Minimal API, see xref:tutorials/min-web-api.
This tutorial creates the following API:
| API | Description | Request body | Response body |
|---|---|---|---|
GET /api/todoitems | Get all to-do items | None | Array of to-do items |
GET /api/todoitems/{id} | Get an item by ID | None | To-do item |
POST /api/todoitems | Add a new item | To-do item | To-do item |
PUT /api/todoitems/{id} | Update an existing item | To-do item | None |
DELETE /api/todoitems/{id} | Delete an item | None | None |
The following diagram shows the design of the app.
A NuGet package must be added to support the database used in this tutorial.
Microsoft.EntityFrameworkCore.InMemory.Open the integrated terminal.
Change directories (cd) to the folder that will contain the project folder.
Run the following commands:
dotnet new webapi --use-controllers -o TodoApi
cd TodoApi
dotnet add package Microsoft.EntityFrameworkCore.InMemory
code -r ../TodoApi
These commands:
In Visual Studio for Mac 2022, select File > New Project....
In the Choose a template for your new project dialog:
In the Configure your new API dialog, make the following selections:
Enter the following:
Microsoft.EntityFrameworkCore.InMemory.The project template creates a WeatherForecast API with support for Swagger.
Press Ctrl+F5 to run without the debugger.
Visual Studio launches the default browser and navigates to https://localhost:<port>/swagger/index.html, where <port> is a randomly chosen port number set at the project creation.
Run the app:
Run the following command to start the app on the https profile:
dotnet run --launch-profile https
The output shows messages similar to the following, indicating that the app is running and awaiting requests:
...
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:{port}
...
<kbd>Ctrl</kbd>+click the HTTPS URL in the output to test the web app in a browser.
The default browser is launched to https://localhost:<port>/swagger/index.html, where <port> is the randomly chosen port number displayed in the output. There's no endpoint at https://localhost:<port>, so the browser returns HTTP 404 Not Found. Append /swagger to the URL, https://localhost:<port>/swagger.
After testing the web app in the following instruction, press <kbd>Ctrl</kbd>+<kbd>C</kbd> in the integrated terminal to shut it down.
Select Debug > Start Debugging to launch the app. Visual Studio for Mac launches a browser and navigates to https://localhost:<port>/swagger/index.html, where <port> is a randomly chosen port number set at the project creation.
The Swagger page /swagger/index.html is displayed. Select GET > Try it out > Execute. The page displays:
If the Swagger page doesn't appear, see this GitHub issue.
Swagger is used to generate useful documentation and help pages for web APIs. This tutorial uses Swagger to test the app. For more information on Swagger, see xref:tutorials/web-api-help-pages-using-swagger.
Copy and paste the Request URL in the browser: https://localhost:<port>/weatherforecast
JSON similar to the following example is returned:
[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]
A model is a set of classes that represent the data that the app manages. The model for this app is the TodoItem class.
Models.Models folder and select Add > Class. Name the class TodoItem and select Add.Models.TodoItem.cs file to the Models folder with the following code:Control-click the TodoAPI project and select Add > New Folder. Name the folder Models.
Control-click the Models folder, and select Add > New Class... > General > Empty Class.
Name the class TodoItem, and then select Create.
Replace the template code with the following:
The Id property functions as the unique key in a relational database.
Model classes can go anywhere in the project, but the Models folder is used by convention.
The database context is the main class that coordinates Entity Framework functionality for a data model. This class is created by deriving from the xref:Microsoft.EntityFrameworkCore.DbContext?displayProperty=fullName class.
Models folder and select Add > Class. Name the class TodoContext and click Add.TodoContext.cs file to the Models folder.In ASP.NET Core, services such as the DB context must be registered with the dependency injection (DI) container. The container provides the service to controllers.
Update Program.cs with the following highlighted code:
The preceding code:
using directives.Right-click the Controllers folder.
Select Add > :::no-loc text="New Scaffolded Item":::.
Select API Controller with actions, using Entity Framework, and then select Add.
In the Add API Controller with actions, using Entity Framework dialog:
If the scaffolding operation fails, select Add to try scaffolding a second time.
Make sure that all of your changes so far are saved.
TodoAPI project folder.
Run the following commands:dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet tool uninstall -g dotnet-aspnet-codegenerator
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet tool update -g dotnet-aspnet-codegenerator
The preceding commands:
dotnet-aspnet-codegenerator) after uninstalling any possible previous version.For Linux, add the .NET tools directory to the system path with the following command:
echo 'export PATH=$HOME/.dotnet/tools:$PATH' >> ~/.bashrc
source ~/.bashrc
Build the project.
Run the following command:
dotnet aspnet-codegenerator controller -name TodoItemsController -async -api -m TodoItem -dc TodoContext -outDir Controllers
The preceding command scaffolds the TodoItemsController.
The generated code:
[ApiController] attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see xref:web-api/index.TodoContext) into the controller. The database context is used in each of the CRUD methods in the controller.The ASP.NET Core templates for:
[action] in the route template.[action] in the route template.When the [action] token isn't in the route template, the action name (method name) isn't included in the endpoint. That is, the action's associated method name isn't used in the matching route.
Update the return statement in the PostTodoItem to use the nameof operator:
The preceding code is an HTTP POST method, as indicated by the [HttpPost] attribute. The method gets the value of the TodoItem from the body of the HTTP request.
For more information, see Attribute routing with Http[Verb] attributes.
The xref:Microsoft.AspNetCore.Mvc.ControllerBase.CreatedAtAction%2A method:
HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.Location header specifies the URI of the newly created to-do item. For more information, see 10.2.2 201 Created.GetTodoItem action to create the Location header's URI. The C# nameof keyword is used to avoid hard-coding the action name in the CreatedAtAction call.<a name="post7"></a>
Press Ctrl+F5 to run the app.
In the Swagger browser window, select POST /api/TodoItems, and then select Try it out.
In the Request body input window, update the JSON. For example,
{
"name": "walk dog",
"isComplete": true
}
Select Execute
In the preceding POST, the Swagger UI shows the location header under Response headers. For example, location: https://localhost:7260/api/TodoItems/1. The location header shows the URI to the created resource.
To test the location header:
In the Swagger browser window, select GET /api/TodoItems/{id}, and then select Try it out.
Enter 1 in the id input box, and then select Execute.
Two GET endpoints are implemented:
GET /api/todoitemsGET /api/todoitems/{id}The previous section showed an example of the /api/todoitems/{id} route.
Follow the POST instructions to add another todo item, and then test the /api/todoitems route using Swagger.
This app uses an in-memory database. If the app is stopped and started, the preceding GET request doesn't return any data. If no data is returned, POST data to the app.
The [HttpGet] attribute denotes a method that responds to an HTTP GET request. The URL path for each method is constructed as follows:
Start with the template string in the controller's Route attribute:
Replace [controller] with the name of the controller, which by convention is the controller class name minus the "Controller" suffix. For this sample, the controller class name is TodoItemsController, so the controller name is "TodoItems". ASP.NET Core routing is case insensitive.
If the [HttpGet] attribute has a route template (for example, [HttpGet("products")]), append that to the path. This sample doesn't use a template. For more information, see Attribute routing with Http[Verb] attributes.
In the following GetTodoItem method, "{id}" is a placeholder variable for the unique identifier of the to-do item. When GetTodoItem is invoked, the value of "{id}" in the URL is provided to the method in its id parameter.
The return type of the GetTodoItems and GetTodoItem methods is ActionResult<T> type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200 OK, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.
ActionResult return types can represent a wide range of HTTP status codes. For example, GetTodoItem can return two different status values:
item results in an HTTP 200 response.Examine the PutTodoItem method:
PutTodoItem is similar to PostTodoItem, except it uses HTTP PUT. The response is 204 (No Content). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.
This sample uses an in-memory database that must be initialized each time the app is started. There must be an item in the database before you make a PUT call. Call GET to ensure there's an item in the database before making a PUT call.
Using the Swagger UI, use the PUT button to update the TodoItem that has Id = 1 and set its name to "feed fish". Note the response is HTTP 204 No Content.
Examine the DeleteTodoItem method:
Use the Swagger UI to delete the TodoItem that has Id = 1. Note the response is HTTP 204 No Content.
There are many other tools that can be used to test web APIs, for example:
curl and shows the curl commands it submits.For more information, see:
<!-- Verify https://go.microsoft.com/fwlink/?linkid=2123754 goes to this H2. Verify the latest released version is on top so this anchor works --><a name="over-post"></a>
Currently the sample app exposes the entire TodoItem object. Production apps typically limit the data that's input and returned using a subset of the model. There are multiple reasons behind this, and security is a major one. The subset of a model is usually referred to as a Data Transfer Object (DTO), input model, or view model. DTO is used in this tutorial.
A DTO may be used to:
To demonstrate the DTO approach, update the TodoItem class to include a secret field:
The secret field needs to be hidden from this app, but an administrative app could choose to expose it.
Verify you can post and get the secret field.
Create a DTO model:
Update the TodoItemsController to use TodoItemDTO:
Verify you can't post or get the secret field.
See Tutorial: Call an ASP.NET Core web API with JavaScript.
See Video: Beginner's Series to: Web APIs.
<a name="auth"></a>
For information on deploying to Azure, see Quickstart: Deploy an ASP.NET web app.
View or download sample code for this tutorial. See how to download.
For more information, see the following resources:
:::moniker-end