Tutorial: Criar uma API Web com o ASP.NET CoreTutorial: Create a web API with ASP.NET Core

Por Rick Anderson e Mike WassonBy Rick Anderson and Mike Wasson

Este tutorial ensina os conceitos básicos da criação de uma API Web com o ASP.NET Core.This tutorial teaches the basics of building a web API with ASP.NET Core.

Neste tutorial, você aprenderá como:In this tutorial, you learn how to:

  • Criar um projeto de API Web.Create a web API project.
  • Adicione uma classe de modelo e um contexto de banco de dados.Add a model class and a database context.
  • Faça scaffold de um controlador com métodos CRUD.Scaffold a controller with CRUD methods.
  • Configure o roteamento, os caminhos de URL e os valores retornados.Configure routing, URL paths, and return values.
  • Chamar a API Web com o Postman.Call the web API with Postman.

No final, você terá uma API Web que pode gerenciar itens de "tarefas pendentes" armazenados em um banco de dados.At the end, you have a web API that can manage "to-do" items stored in a database.

Visão geralOverview

Este tutorial cria a seguinte API:This tutorial creates the following API:

APIAPI DESCRIÇÃODescription Corpo da solicitaçãoRequest body Corpo da respostaResponse body
GET /api/TodoItemsGET /api/TodoItems Obter todos os itens de tarefas pendentesGet all to-do items NenhumNone Matriz de itens de tarefas pendentesArray of to-do items
GET /api/TodoItems/{id}GET /api/TodoItems/{id} Obter um item por IDGet an item by ID NenhumNone Item de tarefas pendentesTo-do item
POST /api/TodoItemsPOST /api/TodoItems Adicionar um novo itemAdd a new item Item de tarefas pendentesTo-do item Item de tarefas pendentesTo-do item
PUT /api/TodoItems/{id}PUT /api/TodoItems/{id} Atualizar um item   existenteUpdate an existing item   Item de tarefas pendentesTo-do item NenhumNone
DELETE /api/TodoItems/{id}    DELETE /api/TodoItems/{id}     Excluir um item    Delete an item     NenhumNone NenhumNone

O diagrama a seguir mostra o design do aplicativo.The following diagram shows the design of the app.

O cliente é representado por uma caixa à esquerda.

Pré-requisitosPrerequisites

Criar um projeto WebCreate a web project

  • No menu Arquivo, selecione Novo > Projeto.From the File menu, select New > Project.
  • Selecione o modelo Aplicativo Web ASP.NET Core e clique em Próximo.Select the ASP.NET Core Web Application template and click Next.
  • Nomeie o projeto como TodoApi e clique em Criar.Name the project TodoApi and click Create.
  • Na caixa de diálogo Criar um aplicativo Web ASP.NET Core, confirme se .NET Core e ASP.NET Core 3.0 estão selecionados.In the Create a new ASP.NET Core Web Application dialog, confirm that .NET Core and ASP.NET Core 3.0 are selected. Selecione o modelo API e clique em Criar.Select the API template and click Create. Não selecione Habilitar Suporte ao Docker.Don't select Enable Docker Support.

Caixa de diálogo Novo projeto do VS

Testar a APITest the API

O modelo de projeto cria uma API WeatherForecast.The project template creates a WeatherForecast API. Chame o método Get em um navegador para testar o aplicativo.Call the Get method from a browser to test the app.

Pressione CTRL+F5 para executar o aplicativo.Press Ctrl+F5 to run the app. O Visual Studio inicia um navegador e navega para https://localhost:<port>/WeatherForecast, em que <port> é um número de porta escolhido aleatoriamente.Visual Studio launches a browser and navigates to https://localhost:<port>/WeatherForecast, where <port> is a randomly chosen port number.

Se você receber uma caixa de diálogo perguntando se você deve confiar no certificado do IIS Express, selecione Sim.If you get a dialog box that asks if you should trust the IIS Express certificate, select Yes. Na caixa de diálogo Aviso de Segurança exibida em seguida, selecione Sim.In the Security Warning dialog that appears next, select Yes.

Um JSON semelhante ao seguinte será retornado:JSON similar to the following 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"
    }
]

Adicionar uma classe de modeloAdd a model class

Um modelo é um conjunto de classes que representam os dados gerenciados pelo aplicativo.A model is a set of classes that represent the data that the app manages. O modelo para esse aplicativo é uma única classe TodoItem.The model for this app is a single TodoItem class.

  • No Gerenciador de Soluções, clique com o botão direito do mouse no projeto.In Solution Explorer, right-click the project. Selecione Adicionar > Nova Pasta.Select Add > New Folder. Nomeie a pasta Models.Name the folder Models.

  • Clique com o botão direito do mouse na pasta Modelos e selecione Adicionar > Classe.Right-click the Models folder and select Add > Class. Dê à classe o nome TodoItem e selecione Adicionar.Name the class TodoItem and select Add.

  • Substitua o código do modelo pelo seguinte código:Replace the template code with the following code:

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

A propriedade Id funciona como a chave exclusiva em um banco de dados relacional.The Id property functions as the unique key in a relational database.

As classes de modelo podem ser colocadas em qualquer lugar no projeto, mas a pasta Models é usada por convenção.Model classes can go anywhere in the project, but the Models folder is used by convention.

Adicionar um contexto de banco de dadosAdd a database context

O contexto de banco de dados é a classe principal que coordena a funcionalidade do Entity Framework para um modelo de dados.The database context is the main class that coordinates Entity Framework functionality for a data model. Essa classe é criada derivando-a da classe Microsoft.EntityFrameworkCore.DbContext.This class is created by deriving from the Microsoft.EntityFrameworkCore.DbContext class.

Adicione Microsoft.EntityFrameworkCore.SqlServerAdd Microsoft.EntityFrameworkCore.SqlServer

  • No menu Ferramentas, selecione Gerenciador de Pacotes do NuGet > Gerenciar Pacotes do NuGet para a Solução.From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
  • Selecione a caixa de seleção Incluir Pré-lançamento.Select the Include prerelease checkbox.
  • Selecione a guia Procurar e, em seguida, insira Microsoft.EntityFrameworkCore.SqlServer na caixa de pesquisa.Select the Browse tab, and then enter Microsoft.EntityFrameworkCore.SqlServer in the search box.
  • Selecione Microsoft.EntityFrameworkCore.SqlServer V3.0.0-preview no painel esquerdo.Select Microsoft.EntityFrameworkCore.SqlServer V3.0.0-preview in the left pane.
  • Selecione a caixa de seleção Projeto no painel direito e, em seguida, selecione Instalar.Select the Project check box in the right pane and then select Install.
  • Use as instruções anteriores para adicionar o pacote do NuGet Microsoft.EntityFrameworkCore.InMemory.Use the preceding instructions to add the Microsoft.EntityFrameworkCore.InMemory NuGet package.

Gerenciador de pacotes do NuGet

Adicione o contexto de banco de dados TodoContextAdd the TodoContext database context

  • Clique com o botão direito do mouse na pasta Modelos e selecione Adicionar > Classe.Right-click the Models folder and select Add > Class. Nomeie a classe como TodoContext e clique em Adicionar.Name the class TodoContext and click Add.
  • Insira o seguinte código:Enter the following code:

    using Microsoft.EntityFrameworkCore;
    
    namespace TodoApi.Models
    {
        public class TodoContext : DbContext
        {
            public TodoContext(DbContextOptions<TodoContext> options)
                : base(options)
            {
            }
    
            public DbSet<TodoItem> TodoItems { get; set; }
        }
    }
    

Registrar o contexto de banco de dadosRegister the database context

No ASP.NET Core, serviços como o contexto de BD precisam ser registrados no contêiner de DI (injeção de dependência).In ASP.NET Core, services such as the DB context must be registered with the dependency injection (DI) container. O contêiner fornece o serviço aos controladores.The container provides the service to controllers.

Atualize Startup.cs com o seguinte código realçado:Update Startup.cs with the following highlighted code:

// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
               opt.UseInMemoryDatabase("TodoList"));
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

O código anterior:The preceding code:

  • Remove as declarações using não utilizadas.Removes unused using declarations.
  • Adiciona o contexto de banco de dados ao contêiner de DI.Adds the database context to the DI container.
  • Especifica que o contexto de banco de dados usará um banco de dados em memória.Specifies that the database context will use an in-memory database.

Faça scaffold de um controladorScaffold a controller

  • Clique com o botão direito do mouse na pasta Controllers.Right-click the Controllers folder.

  • Selecione Adicionar > Novo item com scaffold.Select Add > New Scaffolded Item.

  • Selecione Controlador de API com ações, usando o Entity Framework e, em seguida, selecione Adicionar.Select API Controller with actions, using Entity Framework, and then select Add.

  • Na caixa de diálogo Adicionar Controlador de API com ações, usando o Entity Framework:In the Add API Controller with actions, using Entity Framework dialog:

    • Selecione TodoItem (TodoAPI.Models) na classe Modelo.Select TodoItem (TodoAPI.Models) in the Model class.
    • Selecione TodoContext (TodoAPI.Models) na classe Contexto de Dados.Select TodoContext (TodoAPI.Models) in the Data context class.
    • Selecione AdicionarSelect Add

O código gerado:The generated code:

  • Define uma classe de controlador de API sem métodos.Defines an API controller class without methods.
  • Decora a classe com o atributo [ApiController].Decorates the class with the [ApiController] attribute. Esse atributo indica se o controlador responde às solicitações da API Web.This attribute indicates that the controller responds to web API requests. Para saber mais sobre comportamentos específicos habilitados pelo atributo, consulte Criar APIs Web com o ASP.NET Core.For information about specific behaviors that the attribute enables, see Criar APIs Web com o ASP.NET Core.
  • Usa a DI para injetar o contexto de banco de dados (TodoContext) no controlador.Uses DI to inject the database context (TodoContext) into the controller. O contexto de banco de dados é usado em cada um dos métodos CRUD no controlador.The database context is used in each of the CRUD methods in the controller.

Examine o método criar do PostTodoItemExamine the PostTodoItem create method

Substitua a instrução return no PostTodoItem para usar o operador nameof:Replace the return statement in the PostTodoItem to use the nameof operator:

// POST: api/TodoItems
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
    _context.TodoItems.Add(todoItem);
    await _context.SaveChangesAsync();

    //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
    return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}

O código anterior é um método HTTP POST, conforme indicado pelo atributo [HttpPost].The preceding code is an HTTP POST method, as indicated by the [HttpPost] attribute. O método obtém o valor do item pendente no corpo da solicitação HTTP.The method gets the value of the to-do item from the body of the HTTP request.

O método CreatedAtAction:The CreatedAtAction method:

  • retorna um código de status HTTP 201 em caso de êxito.Returns an HTTP 201 status code if successful. HTTP 201 é a resposta padrão para um método HTTP POST que cria um novo recurso no servidor.HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
  • Adiciona um cabeçalho de Local à resposta.Adds a Location header to the response. O cabeçalho Location especifica o URI do item de tarefas pendentes recém-criado.The Location header specifies the URI of the newly created to-do item. Para obter mais informações, confira 10.2.2 201 Criado.For more information, see 10.2.2 201 Created.
  • Faz referência à ação GetTodoItem para criar o URI de Location do cabeçalho.References the GetTodoItem action to create the Location header's URI. A palavra-chave nameof do C# é usada para evitar o hard-coding do nome da ação, na chamada CreatedAtAction.The C# nameof keyword is used to avoid hard-coding the action name in the CreatedAtAction call.

Instale o PostmanInstall Postman

Este tutorial usa o Postman para testar a API Web.This tutorial uses Postman to test the web API.

  • Instale o PostmanInstall Postman
  • Inicie o aplicativo Web.Start the web app.
  • Inicie o Postman.Start Postman.
  • Desabilite a Verificação do certificado SSLDisable SSL certificate verification
  • Em Arquivo > Configurações (guia *Geral), desabilite Verificação do certificado SSL.From File > Settings (*General tab), disable SSL certificate verification.

    Aviso

    Habilite novamente a verificação do certificado SSL depois de testar o controlador.Re-enable SSL certificate verification after testing the controller.

Teste o PostTodoItem com o PostmanTest PostTodoItem with Postman

  • Crie uma solicitação.Create a new request.

  • Defina o método HTTP como POST.Set the HTTP method to POST.

  • Selecione a guia Corpo.Select the Body tab.

  • Selecione o botão de opção bruto.Select the raw radio button.

  • Defina o tipo como JSON (aplicativo/json) .Set the type to JSON (application/json).

  • No corpo da solicitação, insira JSON para um item pendente:In the request body enter JSON for a to-do item:

    {
      "name":"walk dog",
      "isComplete":true
    }
    
  • Selecione Enviar.Select Send.

    Postman com a solicitação Create

Testar o URI do cabeçalho de localTest the location header URI

  • Selecione a guia Cabeçalhos no painel Resposta.Select the Headers tab in the Response pane.

  • Copie o valor do cabeçalho Local:Copy the Location header value:

    Guia Cabeçalhos do console do Postman

  • Defina o método como GET.Set the method to GET.

  • Cole o URI (por exemplo, https://localhost:5001/api/TodoItems/1)Paste the URI (for example, https://localhost:5001/api/TodoItems/1)

  • Selecione Enviar.Select Send.

Examine os métodos GETExamine the GET methods

Esses métodos implementam dois pontos de extremidade GET:These methods implement two GET endpoints:

  • GET /api/TodoItems
  • GET /api/TodoItems/{id}

Teste o aplicativo chamando os dois pontos de extremidade de um navegador ou do Postman.Test the app by calling the two endpoints from a browser or Postman. Por exemplo:For example:

Uma resposta semelhante à seguinte é produzida pela chamada a GetTodoItems:A response similar to the following is produced by the call to GetTodoItems:

[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

Teste o GET com o PostmanTest Get with Postman

  • Crie uma solicitação.Create a new request.
  • Defina o método HTTP como GET.Set the HTTP method to GET.
  • Defina a URL de solicitação como https://localhost:<port>/api/TodoItems.Set the request URL to https://localhost:<port>/api/TodoItems. Por exemplo, https://localhost:5001/api/TodoItems.For example, https://localhost:5001/api/TodoItems.
  • Defina Exibição de dois painéis no Postman.Set Two pane view in Postman.
  • Selecione Enviar.Select Send.

Este aplicativo usa um banco de dados em memória.This app uses an in-memory database. Se o aplicativo for interrompido e iniciado, a solicitação GET anterior não retornará nenhum dado.If the app is stopped and started, the preceding GET request will not return any data. Se nenhum dado for retornado, execute POST de dados no aplicativo.If no data is returned, POST data to the app.

Roteamento e caminhos de URLRouting and URL paths

O atributo [HttpGet] indica um método que responde a uma solicitação HTTP GET.The [HttpGet] attribute denotes a method that responds to an HTTP GET request. O caminho da URL de cada método é construído da seguinte maneira:The URL path for each method is constructed as follows:

  • Comece com a cadeia de caracteres de modelo no atributo Route do controlador:Start with the template string in the controller's Route attribute:

    [Route("api/[controller]")]
    [ApiController]
    public class TodoItemsController : ControllerBase
    {
        private readonly TodoContext _context;
    
        public TodoItemsController(TodoContext context)
        {
            _context = context;
        }
    
  • Substitua [controller] pelo nome do controlador, que é o nome de classe do controlador menos o sufixo "Controlador" por convenção.Replace [controller] with the name of the controller, which by convention is the controller class name minus the "Controller" suffix. Para esta amostra, o nome da classe do controlador é TodoItemsController. Portanto, o nome do controlador é "TodoItems".For this sample, the controller class name is TodoItemsController, so the controller name is "TodoItems". O roteamento do ASP.NET Core não diferencia maiúsculas de minúsculas.ASP.NET Core routing is case insensitive.

  • Se o atributo [HttpGet] tiver um modelo de rota (por exemplo, [HttpGet("products")]), acrescente isso ao caminho.If the [HttpGet] attribute has a route template (for example, [HttpGet("products")]), append that to the path. Esta amostra não usa um modelo.This sample doesn't use a template. Para obter mais informações, confira Roteamento de atributo com atributos Http[Verb].For more information, see Attribute routing with Http[Verb] attributes.

No método GetTodoItem a seguir, "{id}" é uma variável de espaço reservado para o identificador exclusivo do item pendente.In the following GetTodoItem method, "{id}" is a placeholder variable for the unique identifier of the to-do item. Quando GetTodoItem é invocado, o valor de "{id}" na URL é fornecido para o método no parâmetro id.When GetTodoItem is invoked, the value of "{id}" in the URL is provided to the method in itsid parameter.

// GET: api/TodoItems/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

Valores de retornoReturn values

O tipo de retorno dos métodos GetTodoItems e GetTodoItem é o tipo ActionResult<T>.The return type of the GetTodoItems and GetTodoItem methods is ActionResult<T> type. O ASP.NET Core serializa automaticamente o objeto em JSON e grava o JSON no corpo da mensagem de resposta.ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. O código de resposta para esse tipo de retorno é 200, supondo que não haja nenhuma exceção sem tratamento.The response code for this return type is 200, assuming there are no unhandled exceptions. As exceções sem tratamento são convertidas em erros 5xx.Unhandled exceptions are translated into 5xx errors.

Os tipos de retorno ActionResult podem representar uma ampla variedade de códigos de status HTTP.ActionResult return types can represent a wide range of HTTP status codes. Por exemplo, GetTodoItem pode retornar dois valores de status diferentes:For example, GetTodoItem can return two different status values:

  • Se nenhum item corresponder à ID solicitada, o método retornará um código de erro 404 NotFound.If no item matches the requested ID, the method returns a 404 NotFound error code.
  • Caso contrário, o método retornará 200 com um corpo de resposta JSON.Otherwise, the method returns 200 with a JSON response body. Retornar item resulta em uma resposta HTTP 200.Returning item results in an HTTP 200 response.

O método PutTodoItemThe PutTodoItem method

Examine o método PutTodoItem:Examine the PutTodoItem method:

// PUT: api/TodoItems/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
    if (id != todoItem.Id)
    {
        return BadRequest();
    }

    _context.Entry(todoItem).State = EntityState.Modified;

    try
    {
        await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!TodoItemExists(id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }

    return NoContent();
}

PutTodoItem é semelhante a PostTodoItem, exceto pelo uso de HTTP PUT.PutTodoItem is similar to PostTodoItem, except it uses HTTP PUT. A resposta é 204 (Sem conteúdo).The response is 204 (No Content). De acordo com a especificação de HTTP, uma solicitação PUT exige que o cliente envie a entidade inteira atualizada, não apenas as alterações.According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. Para dar suporte a atualizações parciais, use HTTP PATCH.To support partial updates, use HTTP PATCH.

Se você vir um erro ao chamar PutTodoItem, chame GET para garantir que existe um item no banco de dados.If you get an error calling PutTodoItem, call GET to ensure there's an item in the database.

Testar o método PutTodoItemTest the PutTodoItem method

Este exemplo usa um banco de dados em memória que deverá ser iniciado sempre que o aplicativo for iniciado.This sample uses an in-memory database that must be initialed each time the app is started. Deverá haver um item no banco de dados antes de você fazer uma chamada PUT.There must be an item in the database before you make a PUT call. Chame GET para garantir a existência de um item no banco de dados antes de fazer uma chamada PUT.Call GET to insure there's an item in the database before making a PUT call.

Atualize o item pendente que tem a ID = 1 e defina seu nome como "feed fish":Update the to-do item that has ID = 1 and set its name to "feed fish":

  {
    "ID":1,
    "name":"feed fish",
    "isComplete":true
  }

A seguinte imagem mostra a atualização do Postman:The following image shows the Postman update:

Console do Postman mostrando a resposta 204 (Sem conteúdo)

O método DeleteTodoItemThe DeleteTodoItem method

Examine o método DeleteTodoItem:Examine the DeleteTodoItem method:

// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<ActionResult<TodoItem>> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);
    if (todoItem == null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return todoItem;
}

A resposta DeleteTodoItem é 204 (Sem conteúdo).The DeleteTodoItem response is 204 (No Content).

Testar o método DeleteTodoItemTest the DeleteTodoItem method

Use o Postman para excluir um item pendente:Use Postman to delete a to-do item:

  • Defina o método como DELETE.Set the method to DELETE.
  • Defina o URI do objeto a ser excluído, por exemplo, https://localhost:5001/api/TodoItems/1Set the URI of the object to delete, for example https://localhost:5001/api/TodoItems/1
  • Selecione EnviarSelect Send

Chame a API por meio do jQueryCall the API from jQuery

Consulte Tutorial: Chamar uma API Web do ASP.NET Core com o jQuery.See Tutorial: Call an ASP.NET Core web API with jQuery.

Neste tutorial, você aprenderá como:In this tutorial, you learn how to:

  • Criar um projeto de API Web.Create a web API project.
  • Adicione uma classe de modelo e um contexto de banco de dados.Add a model class and a database context.
  • Adicionar um controlador.Add a controller.
  • Adicionar métodos CRUD.Add CRUD methods.
  • Configurar o roteamento e caminhos de URL.Configure routing and URL paths.
  • Especificar os valores retornados.Specify return values.
  • Chamar a API Web com o Postman.Call the web API with Postman.
  • Chamar a API Web com o jQuery.Call the web API with jQuery.

No final, você terá uma API Web que pode gerenciar itens de "tarefas pendentes" armazenados em um banco de dados relacional.At the end, you have a web API that can manage "to-do" items stored in a relational database.

Visão geralOverview

Este tutorial cria a seguinte API:This tutorial creates the following API:

APIAPI DESCRIÇÃODescription Corpo da solicitaçãoRequest body Corpo da respostaResponse body
GET /api/TodoItemsGET /api/TodoItems Obter todos os itens de tarefas pendentesGet all to-do items NenhumNone Matriz de itens de tarefas pendentesArray of to-do items
GET /api/TodoItems/{id}GET /api/TodoItems/{id} Obter um item por IDGet an item by ID NenhumNone Item de tarefas pendentesTo-do item
POST /api/TodoItemsPOST /api/TodoItems Adicionar um novo itemAdd a new item Item de tarefas pendentesTo-do item Item de tarefas pendentesTo-do item
PUT /api/TodoItems/{id}PUT /api/TodoItems/{id} Atualizar um item   existenteUpdate an existing item   Item de tarefas pendentesTo-do item NenhumNone
DELETE /api/TodoItems/{id}    DELETE /api/TodoItems/{id}     Excluir um item    Delete an item     NenhumNone NenhumNone

O diagrama a seguir mostra o design do aplicativo.The following diagram shows the design of the app.

O cliente é representado por uma caixa à esquerda.

Pré-requisitosPrerequisites

Aviso

Se você usar o Visual Studio 2017, confira problema de dotnet/sdk nº 3124 para obter informações sobre as versões do SDK do .NET Core que não funcionam com o Visual Studio.If you use Visual Studio 2017, see dotnet/sdk issue #3124 for information about .NET Core SDK versions that don't work with Visual Studio.

Criar um projeto WebCreate a web project

  • No menu Arquivo, selecione Novo > Projeto.From the File menu, select New > Project.
  • Selecione o modelo Aplicativo Web ASP.NET Core e clique em Próximo.Select the ASP.NET Core Web Application template and click Next.
  • Nomeie o projeto como TodoApi e clique em Criar.Name the project TodoApi and click Create.
  • Na caixa de diálogo Criar um aplicativo Web ASP.NET Core, confirme se .NET Core e ASP.NET Core 2.2 estão selecionados.In the Create a new ASP.NET Core Web Application dialog, confirm that .NET Core and ASP.NET Core 2.2 are selected. Selecione o modelo API e clique em Criar.Select the API template and click Create. Não selecione Habilitar Suporte ao Docker.Don't select Enable Docker Support.

Caixa de diálogo Novo projeto do VS

Testar a APITest the API

O modelo de projeto cria uma API values.The project template creates a values API. Chame o método Get em um navegador para testar o aplicativo.Call the Get method from a browser to test the app.

Pressione CTRL+F5 para executar o aplicativo.Press Ctrl+F5 to run the app. O Visual Studio inicia um navegador e navega para https://localhost:<port>/api/values, em que <port> é um número de porta escolhido aleatoriamente.Visual Studio launches a browser and navigates to https://localhost:<port>/api/values, where <port> is a randomly chosen port number.

Se você receber uma caixa de diálogo perguntando se você deve confiar no certificado do IIS Express, selecione Sim.If you get a dialog box that asks if you should trust the IIS Express certificate, select Yes. Na caixa de diálogo Aviso de Segurança exibida em seguida, selecione Sim.In the Security Warning dialog that appears next, select Yes.

O seguinte JSON é retornado:The following JSON is returned:

["value1","value2"]

Adicionar uma classe de modeloAdd a model class

Um modelo é um conjunto de classes que representam os dados gerenciados pelo aplicativo.A model is a set of classes that represent the data that the app manages. O modelo para esse aplicativo é uma única classe TodoItem.The model for this app is a single TodoItem class.

  • No Gerenciador de Soluções, clique com o botão direito do mouse no projeto.In Solution Explorer, right-click the project. Selecione Adicionar > Nova Pasta.Select Add > New Folder. Nomeie a pasta Models.Name the folder Models.

  • Clique com o botão direito do mouse na pasta Modelos e selecione Adicionar > Classe.Right-click the Models folder and select Add > Class. Dê à classe o nome TodoItem e selecione Adicionar.Name the class TodoItem and select Add.

  • Substitua o código do modelo pelo seguinte código:Replace the template code with the following code:

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

A propriedade Id funciona como a chave exclusiva em um banco de dados relacional.The Id property functions as the unique key in a relational database.

As classes de modelo podem ser colocadas em qualquer lugar no projeto, mas a pasta Models é usada por convenção.Model classes can go anywhere in the project, but the Models folder is used by convention.

Adicionar um contexto de banco de dadosAdd a database context

O contexto de banco de dados é a classe principal que coordena a funcionalidade do Entity Framework para um modelo de dados.The database context is the main class that coordinates Entity Framework functionality for a data model. Essa classe é criada derivando-a da classe Microsoft.EntityFrameworkCore.DbContext.This class is created by deriving from the Microsoft.EntityFrameworkCore.DbContext class.

  • Clique com o botão direito do mouse na pasta Modelos e selecione Adicionar > Classe.Right-click the Models folder and select Add > Class. Nomeie a classe como TodoContext e clique em Adicionar.Name the class TodoContext and click Add.
  • Substitua o código do modelo pelo seguinte código:Replace the template code with the following code:

    using Microsoft.EntityFrameworkCore;
    
    namespace TodoApi.Models
    {
        public class TodoContext : DbContext
        {
            public TodoContext(DbContextOptions<TodoContext> options)
                : base(options)
            {
            }
    
            public DbSet<TodoItem> TodoItems { get; set; }
        }
    }
    

Registrar o contexto de banco de dadosRegister the database context

No ASP.NET Core, serviços como o contexto de BD precisam ser registrados no contêiner de DI (injeção de dependência).In ASP.NET Core, services such as the DB context must be registered with the dependency injection (DI) container. O contêiner fornece o serviço aos controladores.The container provides the service to controllers.

Atualize Startup.cs com o seguinte código realçado:Update Startup.cs with the following highlighted code:

// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the 
        //container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
                opt.UseInMemoryDatabase("TodoList"));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP 
        //request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for 
                // production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}

O código anterior:The preceding code:

  • Remove as declarações using não utilizadas.Removes unused using declarations.
  • Adiciona o contexto de banco de dados ao contêiner de DI.Adds the database context to the DI container.
  • Especifica que o contexto de banco de dados usará um banco de dados em memória.Specifies that the database context will use an in-memory database.

Adicionar um controladorAdd a controller

  • Clique com o botão direito do mouse na pasta Controllers.Right-click the Controllers folder.

  • Selecione Adicionar > Novo Item.Select Add > New Item.

  • Na caixa de diálogo Adicionar Novo Item, selecione o modelo Classe do Controlador de API.In the Add New Item dialog, select the API Controller Class template.

  • Dê à classe o nome TodoController e selecione Adicionar.Name the class TodoController, and select Add.

    Caixa de diálogo Adicionar Novo Item com o controlador na caixa de pesquisa e o controlador da API Web selecionados

  • Substitua o código do modelo pelo seguinte código:Replace the template code with the following code:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using TodoApi.Models;
    
    namespace TodoApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class TodoController : ControllerBase
        {
            private readonly TodoContext _context;
    
            public TodoController(TodoContext context)
            {
                _context = context;
    
                if (_context.TodoItems.Count() == 0)
                {
                    // Create a new TodoItem if collection is empty,
                    // which means you can't delete all TodoItems.
                    _context.TodoItems.Add(new TodoItem { Name = "Item1" });
                    _context.SaveChanges();
                }
            }
        }
    }
    

O código anterior:The preceding code:

  • Define uma classe de controlador de API sem métodos.Defines an API controller class without methods.
  • Decora a classe com o atributo [ApiController].Decorates the class with the [ApiController] attribute. Esse atributo indica se o controlador responde às solicitações da API Web.This attribute indicates that the controller responds to web API requests. Para saber mais sobre comportamentos específicos habilitados pelo atributo, consulte Criar APIs Web com o ASP.NET Core.For information about specific behaviors that the attribute enables, see Criar APIs Web com o ASP.NET Core.
  • Usa a DI para injetar o contexto de banco de dados (TodoContext) no controlador.Uses DI to inject the database context (TodoContext) into the controller. O contexto de banco de dados é usado em cada um dos métodos CRUD no controlador.The database context is used in each of the CRUD methods in the controller.
  • Adiciona um item chamado Item1 ao banco de dados se o banco de dados está vazio.Adds an item named Item1 to the database if the database is empty. Esse código está no construtor, de modo que ele seja executado sempre que há uma nova solicitação HTTP.This code is in the constructor, so it runs every time there's a new HTTP request. Se você excluir todos os itens, o construtor criará Item1 novamente na próxima vez que um método de API for chamado.If you delete all items, the constructor creates Item1 again the next time an API method is called. Portanto, pode parecer que a exclusão não funcionou quando ela realmente funcionou.So it may look like the deletion didn't work when it actually did work.

Adicionar métodos GetAdd Get methods

Para fornecer uma API que recupera itens pendentes, adicione os seguintes métodos à classe TodoController:To provide an API that retrieves to-do items, add the following methods to the TodoController class:

// GET: api/Todo
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
{
    return await _context.TodoItems.ToListAsync();
}

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

Esses métodos implementam dois pontos de extremidade GET:These methods implement two GET endpoints:

  • GET /api/todo
  • GET /api/todo/{id}

Interrompa o aplicativo se ele ainda estiver em execução.Stop the app if it's still running. Em seguida, execute-o novamente para incluir as alterações mais recentes.Then run it again to include the latest changes.

Teste o aplicativo chamando os dois pontos de extremidade em um navegador.Test the app by calling the two endpoints from a browser. Por exemplo:For example:

  • https://localhost:<port>/api/todo
  • https://localhost:<port>/api/todo/1

A seguinte resposta HTTP é produzida pela chamada a GetTodoItems:The following HTTP response is produced by the call to GetTodoItems:

[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

Roteamento e caminhos de URLRouting and URL paths

O atributo [HttpGet] indica um método que responde a uma solicitação HTTP GET.The [HttpGet] attribute denotes a method that responds to an HTTP GET request. O caminho da URL de cada método é construído da seguinte maneira:The URL path for each method is constructed as follows:

  • Comece com a cadeia de caracteres de modelo no atributo Route do controlador:Start with the template string in the controller's Route attribute:

    namespace TodoApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class TodoController : ControllerBase
        {
            private readonly TodoContext _context;
    
  • Substitua [controller] pelo nome do controlador, que é o nome de classe do controlador menos o sufixo "Controlador" por convenção.Replace [controller] with the name of the controller, which by convention is the controller class name minus the "Controller" suffix. Para esta amostra, o nome da classe do controlador é TodoController e, portanto, o nome do controlador é "todo".For this sample, the controller class name is TodoController, so the controller name is "todo". O roteamento do ASP.NET Core não diferencia maiúsculas de minúsculas.ASP.NET Core routing is case insensitive.

  • Se o atributo [HttpGet] tiver um modelo de rota (por exemplo, [HttpGet("products")]), acrescente isso ao caminho.If the [HttpGet] attribute has a route template (for example, [HttpGet("products")]), append that to the path. Esta amostra não usa um modelo.This sample doesn't use a template. Para obter mais informações, confira Roteamento de atributo com atributos Http[Verb].For more information, see Attribute routing with Http[Verb] attributes.

No método GetTodoItem a seguir, "{id}" é uma variável de espaço reservado para o identificador exclusivo do item pendente.In the following GetTodoItem method, "{id}" is a placeholder variable for the unique identifier of the to-do item. Quando GetTodoItem é invocado, o valor de "{id}" na URL é fornecido para o método no parâmetro id.When GetTodoItem is invoked, the value of "{id}" in the URL is provided to the method in itsid parameter.

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

Valores de retornoReturn values

O tipo de retorno dos métodos GetTodoItems e GetTodoItem é o tipo ActionResult<T>.The return type of the GetTodoItems and GetTodoItem methods is ActionResult<T> type. O ASP.NET Core serializa automaticamente o objeto em JSON e grava o JSON no corpo da mensagem de resposta.ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. O código de resposta para esse tipo de retorno é 200, supondo que não haja nenhuma exceção sem tratamento.The response code for this return type is 200, assuming there are no unhandled exceptions. As exceções sem tratamento são convertidas em erros 5xx.Unhandled exceptions are translated into 5xx errors.

Os tipos de retorno ActionResult podem representar uma ampla variedade de códigos de status HTTP.ActionResult return types can represent a wide range of HTTP status codes. Por exemplo, GetTodoItem pode retornar dois valores de status diferentes:For example, GetTodoItem can return two different status values:

  • Se nenhum item corresponder à ID solicitada, o método retornará um código de erro 404 NotFound.If no item matches the requested ID, the method returns a 404 NotFound error code.
  • Caso contrário, o método retornará 200 com um corpo de resposta JSON.Otherwise, the method returns 200 with a JSON response body. Retornar item resulta em uma resposta HTTP 200.Returning item results in an HTTP 200 response.

Testar o método GetTodoItemsTest the GetTodoItems method

Este tutorial usa o Postman para testar a API Web.This tutorial uses Postman to test the web API.

  • Instale o PostmanInstall Postman
  • Inicie o aplicativo Web.Start the web app.
  • Inicie o Postman.Start Postman.
  • Desabilite a Verificação do certificado SSLDisable SSL certificate verification
  • Em Arquivo > Configurações (guia Geral), desabilite Verificação de certificado SSL.From File > Settings (General tab), disable SSL certificate verification.

Aviso

Habilite novamente a verificação do certificado SSL depois de testar o controlador.Re-enable SSL certificate verification after testing the controller.

  • Crie uma solicitação.Create a new request.
    • Defina o método HTTP como GET.Set the HTTP method to GET.
    • Defina a URL de solicitação como https://localhost:<port>/api/todo.Set the request URL to https://localhost:<port>/api/todo. Por exemplo, https://localhost:5001/api/todo.For example, https://localhost:5001/api/todo.
  • Defina Exibição de dois painéis no Postman.Set Two pane view in Postman.
  • Selecione Enviar.Select Send.

Postman com solicitação GET

Adicionar um método CreateAdd a Create method

Adicione o seguinte método PostTodoItem dentro de Controllers/TodoController.cs:Add the following PostTodoItem method inside of Controllers/TodoController.cs:

// POST: api/Todo
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item)
{
    _context.TodoItems.Add(item);
    await _context.SaveChangesAsync();

    return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item);
}

O código anterior é um método HTTP POST, conforme indicado pelo atributo [HttpPost].The preceding code is an HTTP POST method, as indicated by the [HttpPost] attribute. O método obtém o valor do item pendente no corpo da solicitação HTTP.The method gets the value of the to-do item from the body of the HTTP request.

O método CreatedAtAction:The CreatedAtAction method:

  • retorna um código de status HTTP 201 em caso de êxito.Returns an HTTP 201 status code, if successful. HTTP 201 é a resposta padrão para um método HTTP POST que cria um novo recurso no servidor.HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.

  • Adiciona um cabeçalho Location à resposta.Adds a Location header to the response. O cabeçalho Location especifica o URI do item de tarefas pendentes recém-criado.The Location header specifies the URI of the newly created to-do item. Para obter mais informações, confira 10.2.2 201 Criado.For more information, see 10.2.2 201 Created.

  • Faz referência à ação GetTodoItem para criar o URI de Location do cabeçalho.References the GetTodoItem action to create the Location header's URI. A palavra-chave nameof do C# é usada para evitar o hard-coding do nome da ação, na chamada CreatedAtAction.The C# nameof keyword is used to avoid hard-coding the action name in the CreatedAtAction call.

    // GET: api/Todo/5
    [HttpGet("{id}")]
    public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
    {
        var todoItem = await _context.TodoItems.FindAsync(id);
    
        if (todoItem == null)
        {
            return NotFound();
        }
    
        return todoItem;
    }
    

Testar o método PostTodoItemTest the PostTodoItem method

  • Compile o projeto.Build the project.

  • No Postman, defina o método HTTP como POST.In Postman, set the HTTP method to POST.

  • Selecione a guia Corpo.Select the Body tab.

  • Selecione o botão de opção bruto.Select the raw radio button.

  • Defina o tipo como JSON (aplicativo/json) .Set the type to JSON (application/json).

  • No corpo da solicitação, insira JSON para um item pendente:In the request body enter JSON for a to-do item:

    {
      "name":"walk dog",
      "isComplete":true
    }
    
  • Selecione Enviar.Select Send.

    Postman com a solicitação Create

    Se você receber um erro 405 Método Não Permitido, provavelmente, esse será o resultado da não compilação do projeto após a adição do método PostTodoItem.If you get a 405 Method Not Allowed error, it's probably the result of not compiling the project after adding the PostTodoItem method.

Testar o URI do cabeçalho de localTest the location header URI

  • Selecione a guia Cabeçalhos no painel Resposta.Select the Headers tab in the Response pane.

  • Copie o valor do cabeçalho Local:Copy the Location header value:

    Guia Cabeçalhos do console do Postman

  • Defina o método como GET.Set the method to GET.

  • Cole o URI (por exemplo, https://localhost:5001/api/Todo/2)Paste the URI (for example, https://localhost:5001/api/Todo/2)

  • Selecione Enviar.Select Send.

Adicionar um método PutTodoItemAdd a PutTodoItem method

Adicione o seguinte método PutTodoItem:Add the following PutTodoItem method:

// PUT: api/Todo/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem item)
{
    if (id != item.Id)
    {
        return BadRequest();
    }

    _context.Entry(item).State = EntityState.Modified;
    await _context.SaveChangesAsync();

    return NoContent();
}

PutTodoItem é semelhante a PostTodoItem, exceto pelo uso de HTTP PUT.PutTodoItem is similar to PostTodoItem, except it uses HTTP PUT. A resposta é 204 (Sem conteúdo).The response is 204 (No Content). De acordo com a especificação de HTTP, uma solicitação PUT exige que o cliente envie a entidade inteira atualizada, não apenas as alterações.According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. Para dar suporte a atualizações parciais, use HTTP PATCH.To support partial updates, use HTTP PATCH.

Se você vir um erro ao chamar PutTodoItem, chame GET para garantir que existe um item no banco de dados.If you get an error calling PutTodoItem, call GET to ensure there's an item in the database.

Testar o método PutTodoItemTest the PutTodoItem method

Este exemplo usa um banco de dados em memória que deverá ser iniciado sempre que o aplicativo for iniciado.This sample uses an in-memory database that must be initialed each time the app is started. Deverá haver um item no banco de dados antes de você fazer uma chamada PUT.There must be an item in the database before you make a PUT call. Chame GET para garantir a existência de um item no banco de dados antes de fazer uma chamada PUT.Call GET to insure there's an item in the database before making a PUT call.

Atualize o item pendente que tem a ID = 1 e defina seu nome como "feed fish":Update the to-do item that has id = 1 and set its name to "feed fish":

  {
    "ID":1,
    "name":"feed fish",
    "isComplete":true
  }

A seguinte imagem mostra a atualização do Postman:The following image shows the Postman update:

Console do Postman mostrando a resposta 204 (Sem conteúdo)

Adicionar um método DeleteTodoItemAdd a DeleteTodoItem method

Adicione o seguinte método DeleteTodoItem:Add the following DeleteTodoItem method:

// DELETE: api/Todo/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return NoContent();
}

A resposta DeleteTodoItem é 204 (Sem conteúdo).The DeleteTodoItem response is 204 (No Content).

Testar o método DeleteTodoItemTest the DeleteTodoItem method

Use o Postman para excluir um item pendente:Use Postman to delete a to-do item:

  • Defina o método como DELETE.Set the method to DELETE.
  • Defina o URI do objeto a ser excluído, por exemplo, https://localhost:5001/api/todo/1Set the URI of the object to delete, for example https://localhost:5001/api/todo/1
  • Selecione EnviarSelect Send

O aplicativo de exemplo permite que você exclua todos os itens.The sample app allows you to delete all the items. No entanto, quando o último item é excluído, um novo é criado pelo construtor de classe de modelo na próxima vez que a API for chamada.However, when the last item is deleted, a new one is created by the model class constructor the next time the API is called.

Chamar a API com o jQueryCall the API with jQuery

Nesta seção, uma página HTML que usa o jQuery para chamar a API Web é adicionada.In this section, an HTML page is added that uses jQuery to call the web api. O jQuery inicia a solicitação e atualiza a página com os detalhes da resposta da API.jQuery initiates the request and updates the page with the details from the API's response.

Configurar o aplicativo para servir arquivos estáticos e habilitar o mapeamento de arquivo padrão atualizando Startup.cs com o código realçado a seguir:Configure the app to serve static files and enable default file mapping by updating Startup.cs with the following highlighted code:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        // The default HSTS value is 30 days. You may want to change this for 
        // production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }

    app.UseDefaultFiles();
    app.UseStaticFiles();
    app.UseHttpsRedirection();
    app.UseMvc();
}

Crie uma pasta wwwroot no diretório do projeto.Create a wwwroot folder in the project directory.

Adicione um arquivo HTML chamado index.html ao diretório wwwroot.Add an HTML file named index.html to the wwwroot directory. Substitua seu conteúdo pela seguinte marcação:Replace its contents with the following markup:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>To-do CRUD</title>
    <style>
        input[type='submit'], button, [aria-label] {
            cursor: pointer;
        }

        #spoiler {
            display: none;
        }

        table {
            font-family: Arial, sans-serif;
            border: 1px solid;
            border-collapse: collapse;
        }

        th {
            background-color: #0066CC;
            color: white;
        }

        td {
            border: 1px solid;
            padding: 5px;
        }
    </style>
</head>
<body>
    <h1>To-do CRUD</h1>
    <h3>Add</h3>
    <form action="javascript:void(0);" method="POST" onsubmit="addItem()">
        <input type="text" id="add-name" placeholder="New to-do">
        <input type="submit" value="Add">
    </form>

    <div id="spoiler">
        <h3>Edit</h3>
        <form class="my-form">
            <input type="hidden" id="edit-id">
            <input type="checkbox" id="edit-isComplete">
            <input type="text" id="edit-name">
            <input type="submit" value="Save">
            <a onclick="closeInput()" aria-label="Close">&#10006;</a>
        </form>
    </div>

    <p id="counter"></p>

    <table>
        <tr>
            <th>Is Complete</th>
            <th>Name</th>
            <th></th>
            <th></th>
        </tr>
        <tbody id="todos"></tbody>
    </table>

    <script src="https://code.jquery.com/jquery-3.3.1.min.js"
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
            crossorigin="anonymous"></script>
    <script src="site.js"></script>
</body>
</html>

Adicione um arquivo JavaScript chamado site.js ao diretório wwwroot.Add a JavaScript file named site.js to the wwwroot directory. Substitua seu conteúdo pelo código a seguir:Replace its contents with the following code:

const uri = "api/todo";
let todos = null;
function getCount(data) {
  const el = $("#counter");
  let name = "to-do";
  if (data) {
    if (data > 1) {
      name = "to-dos";
    }
    el.text(data + " " + name);
  } else {
    el.text("No " + name);
  }
}

$(document).ready(function() {
  getData();
});

function getData() {
  $.ajax({
    type: "GET",
    url: uri,
    cache: false,
    success: function(data) {
      const tBody = $("#todos");

      $(tBody).empty();

      getCount(data.length);

      $.each(data, function(key, item) {
        const tr = $("<tr></tr>")
          .append(
            $("<td></td>").append(
              $("<input/>", {
                type: "checkbox",
                disabled: true,
                checked: item.isComplete
              })
            )
          )
          .append($("<td></td>").text(item.name))
          .append(
            $("<td></td>").append(
              $("<button>Edit</button>").on("click", function() {
                editItem(item.id);
              })
            )
          )
          .append(
            $("<td></td>").append(
              $("<button>Delete</button>").on("click", function() {
                deleteItem(item.id);
              })
            )
          );

        tr.appendTo(tBody);
      });

      todos = data;
    }
  });
}

function addItem() {
  const item = {
    name: $("#add-name").val(),
    isComplete: false
  };

  $.ajax({
    type: "POST",
    accepts: "application/json",
    url: uri,
    contentType: "application/json",
    data: JSON.stringify(item),
    error: function(jqXHR, textStatus, errorThrown) {
      alert("Something went wrong!");
    },
    success: function(result) {
      getData();
      $("#add-name").val("");
    }
  });
}

function deleteItem(id) {
  $.ajax({
    url: uri + "/" + id,
    type: "DELETE",
    success: function(result) {
      getData();
    }
  });
}

function editItem(id) {
  $.each(todos, function(key, item) {
    if (item.id === id) {
      $("#edit-name").val(item.name);
      $("#edit-id").val(item.id);
      $("#edit-isComplete")[0].checked = item.isComplete;
    }
  });
  $("#spoiler").css({ display: "block" });
}

$(".my-form").on("submit", function() {
  const item = {
    name: $("#edit-name").val(),
    isComplete: $("#edit-isComplete").is(":checked"),
    id: $("#edit-id").val()
  };

  $.ajax({
    url: uri + "/" + $("#edit-id").val(),
    type: "PUT",
    accepts: "application/json",
    contentType: "application/json",
    data: JSON.stringify(item),
    success: function(result) {
      getData();
    }
  });

  closeInput();
  return false;
});

function closeInput() {
  $("#spoiler").css({ display: "none" });
}

Uma alteração nas configurações de inicialização do projeto ASP.NET Core pode ser necessária para testar a página HTML localmente:A change to the ASP.NET Core project's launch settings may be required to test the HTML page locally:

  • Abra Properties\launchSettings.json.Open Properties\launchSettings.json.
  • Remova a propriedade launchUrl para forçar o aplicativo a ser aberto em index.html, o arquivo padrão do projeto.Remove the launchUrl property to force the app to open at index.html—the project's default file.

Há várias maneiras de obter o jQuery.There are several ways to get jQuery. No snippet anterior, a biblioteca é carregada de uma CDN.In the preceding snippet, the library is loaded from a CDN.

Esta amostra chama todos os métodos CRUD da API.This sample calls all of the CRUD methods of the API. Veja a seguir explicações das chamadas à API.Following are explanations of the calls to the API.

Obter uma lista de itens pendentesGet a list of to-do items

A função ajax do jQuery envia uma solicitação GET para a API, que retorna o JSON que representa uma matriz de itens pendentes.The jQuery ajax function sends a GET request to the API, which returns JSON representing an array of to-do items. A função de retorno de chamada success será invocada se a solicitação for bem-sucedida.The success callback function is invoked if the request succeeds. No retorno de chamada, o DOM é atualizado com as informações do item pendente.In the callback, the DOM is updated with the to-do information.

$(document).ready(function() {
  getData();
});

function getData() {
  $.ajax({
    type: "GET",
    url: uri,
    cache: false,
    success: function(data) {
      const tBody = $("#todos");

      $(tBody).empty();

      getCount(data.length);

      $.each(data, function(key, item) {
        const tr = $("<tr></tr>")
          .append(
            $("<td></td>").append(
              $("<input/>", {
                type: "checkbox",
                disabled: true,
                checked: item.isComplete
              })
            )
          )
          .append($("<td></td>").text(item.name))
          .append(
            $("<td></td>").append(
              $("<button>Edit</button>").on("click", function() {
                editItem(item.id);
              })
            )
          )
          .append(
            $("<td></td>").append(
              $("<button>Delete</button>").on("click", function() {
                deleteItem(item.id);
              })
            )
          );

        tr.appendTo(tBody);
      });

      todos = data;
    }
  });
}

Adicionar um item pendenteAdd a to-do item

A função ajax envia uma solicitação POST com o item pendente no corpo da solicitação.The ajax function sends a POST request with the to-do item in the request body. As opções accepts e contentType são definidas como application/json para especificar o tipo de mídia que está sendo recebido e enviado.The accepts and contentType options are set to application/json to specify the media type being received and sent. O item pendente é convertido em JSON usando JSON.stringify.The to-do item is converted to JSON by using JSON.stringify. Quando a API retorna um código de status de êxito, a função getData é invocada para atualizar a tabela HTML.When the API returns a successful status code, the getData function is invoked to update the HTML table.

function addItem() {
  const item = {
    name: $("#add-name").val(),
    isComplete: false
  };

  $.ajax({
    type: "POST",
    accepts: "application/json",
    url: uri,
    contentType: "application/json",
    data: JSON.stringify(item),
    error: function(jqXHR, textStatus, errorThrown) {
      alert("Something went wrong!");
    },
    success: function(result) {
      getData();
      $("#add-name").val("");
    }
  });
}

Atualizar um item pendenteUpdate a to-do item

A atualização de um item pendente é semelhante à adição de um.Updating a to-do item is similar to adding one. A url é alterada para adicionar o identificador exclusivo do item, e o type é PUT.The url changes to add the unique identifier of the item, and the type is PUT.

$.ajax({
  url: uri + "/" + $("#edit-id").val(),
  type: "PUT",
  accepts: "application/json",
  contentType: "application/json",
  data: JSON.stringify(item),
  success: function(result) {
    getData();
  }
});

Excluir um item pendenteDelete a to-do item

A exclusão de um item pendente é feita definindo o type na chamada do AJAX como DELETE e especificando o identificador exclusivo do item na URL.Deleting a to-do item is accomplished by setting the type on the AJAX call to DELETE and specifying the item's unique identifier in the URL.

$.ajax({
  url: uri + "/" + id,
  type: "DELETE",
  success: function(result) {
    getData();
  }
});

Recursos adicionaisAdditional resources

Exibir ou baixar o código de exemplo para este tutorial.View or download sample code for this tutorial. Consulte como baixar.See how to download.

Para obter mais informações, consulte os seguintes recursos:For more information, see the following resources: