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

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.
  • Adicionar uma classe de modelo.Add a model class.
  • Criar o contexto de banco de dados.Create the database context.
  • Registrar o contexto de banco de dados.Register the 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/todoGET /api/todo Obter todos os itens de tarefas pendentesGet all to-do items NenhumNone Matriz de itens de tarefas pendentesArray of to-do items
GET /api/todo/{id}GET /api/todo/{id} Obter um item por IDGet an item by ID NenhumNone Item de tarefas pendentesTo-do item
POST /api/todoPOST /api/todo Adicionar um novo itemAdd a new item Item de tarefas pendentesTo-do item Item de tarefas pendentesTo-do item
PUT /api/todo/{id}PUT /api/todo/{id} Atualizar um item   existenteUpdate an existing item   Item de tarefas pendentesTo-do item NenhumNone
DELETE /api/todo/{id}    DELETE /api/todo/{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 e envia uma solicitação e recebe uma resposta do aplicativo, uma caixa desenhada à direita.

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.Select the ASP.NET Core Web Application template. Nomeie o projeto como TodoApi e clique em OK.Name the project TodoApi and click OK.
  • Na caixa de diálogo Novo aplicativo Web ASP.NET Core – TodoApi e escolha a versão do ASP.NET Core.In the New ASP.NET Core Web Application - TodoApi dialog, choose the ASP.NET Core version. Selecione o modelo API e clique em OK.Select the API template and click OK. Não selecione Habilitar Suporte ao Docker.Do not 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.
  • Decore 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 obter informações sobre comportamentos específicos habilitados pelo atributo, confira Anotação com o atributo ApiController.For information about specific behaviors that the attribute enables, see Annotation with ApiController attribute.
  • 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}

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 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.

  • 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:Add the following PostTodoItem method:

// 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ê receber um erro ao chamar PutTodoItem, chame GET para garantir que exista um item no banco de dados.If you get an error calling PutTodoItem, call GET to ensure there is a 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 is 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, mas quando o último item é excluído, um novo é criado pelo construtor de classe de modelo na próxima vez que a API é chamada.The sample app allows you to delete all the items, but 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.

Configure o aplicativo para fornecer arquivos estáticos e habilitar o mapeamento de arquivo padrão:Configure the app to serve static files and enable default file mapping:

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:

Próximas etapasNext steps

Neste tutorial, você aprendeu como:In this tutorial, you learned how to:

  • Criar um projeto de aplicativo API Web.Create a web api project.
  • Adicionar uma classe de modelo.Add a model class.
  • Criar o contexto de banco de dados.Create the database context.
  • Registrar o contexto de banco de dados.Register the 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.

Avance para o próximo tutorial para saber como gerar páginas de ajuda da API:Advance to the next tutorial to learn how to generate API help pages: