Implementação da APIAPI implementation

Uma API de web RESTful cuidadosamente estruturada define os recursos, relações e esquemas de navegação que podem ser acedidas por aplicações cliente.A carefully designed RESTful web API defines the resources, relationships, and navigation schemes that are accessible to client applications. Quando implementa e executa uma API Web, deve considerar os requisitos físicos do ambiente a alojar a API Web e a forma como esta é construída em vez da estrutura lógica dos dados.When you implement and deploy a web API, you should consider the physical requirements of the environment hosting the web API and the way in which the web API is constructed rather than the logical structure of the data. Esta orientação concentra-se nas melhores práticas para implementar uma API web e publicar para que fique disponível para aplicativos cliente.This guidance focuses on best practices for implementing a web API and publishing it to make it available to client applications. Para obter informações detalhadas sobre a estrutura da web API, consulte documentação de orientação de design de API.For detailed information about web API design, see API design guidance.

Processamento de pedidosProcessing requests

Considere os seguintes pontos ao implementar o código para processar pedidos.Consider the following points when you implement the code to handle requests.

As ações GET, PUT, DELETE, HEAD e PATCH devem ser idempotentesGET, PUT, DELETE, HEAD, and PATCH actions should be idempotent

O código que implementa estes pedidos não deve impor quaisquer efeitos secundários.The code that implements these requests should not impose any side-effects. O mesmo pedido repetido sobre o mesmo recurso deve produzir o mesmo estado.The same request repeated over the same resource should result in the same state. Por exemplo, o envio de vários pedidos DELETE para o mesmo URI deve ter o mesmo efeito, embora o código de estado HTTP nas mensagens de resposta possa ser diferente.For example, sending multiple DELETE requests to the same URI should have the same effect, although the HTTP status code in the response messages may be different. O primeiro pedido DELETE pode devolver o código de estado 204 (Sem Conteúdo), enquanto um pedido DELETE subsequente pode devolver o código de estado 404 (Não Encontrado).The first DELETE request might return status code 204 (No Content), while a subsequent DELETE request might return status code 404 (Not Found).

Nota

O artigo Idempotency Patterns (Padrões de Idempotência) no blogue de Jonathan Oliver fornece uma descrição geral da idempotência e como esta se relaciona com operações de gestão de dados.The article Idempotency Patterns on Jonathan Oliver’s blog provides an overview of idempotency and how it relates to data management operations.

As ações POST que criam novos recursos não devem ter efeitos secundários não relacionadosPOST actions that create new resources should not have unrelated side-effects

Se um pedido POST destina-se para criar um novo recurso, os efeitos do pedido devem ser limitados para o novo recurso (e possivelmente todos diretamente os recursos relacionados se existir algum tipo de ligação envolvido) por exemplo, num sistema de comércio eletrônico, uma POSTAGEM solicitar que cria uma nova encomenda para um cliente também pode corrigir os níveis de estoque e gerar informações de faturação, mas não deve modificar informações não diretamente relacionadas com a ordem ou ter quaisquer outros efeitos colaterais sobre o estado geral do sistema.If a POST request is intended to create a new resource, the effects of the request should be limited to the new resource (and possibly any directly related resources if there is some sort of linkage involved) For example, in an e-commerce system, a POST request that creates a new order for a customer might also amend inventory levels and generate billing information, but it should not modify information not directly related to the order or have any other side-effects on the overall state of the system.

Evitar implementar operações POST, PUT e DELETE conversadorasAvoid implementing chatty POST, PUT, and DELETE operations

Suporte os pedidos POST, PUT e DELETE nas coleções de recursos.Support POST, PUT and DELETE requests over resource collections. Um pedido POST pode conter os detalhes para vários novos recursos e adicioná-los à mesma coleção, um pedido PUT pode substituir todo o conjunto de recursos numa coleção e um pedido DELETE pode remover uma coleção completa.A POST request can contain the details for multiple new resources and add them all to the same collection, a PUT request can replace the entire set of resources in a collection, and a DELETE request can remove an entire collection.

O suporte de OData incluído na API Web 2 da ASP.NET fornece a capacidade de pedidos de lote.The OData support included in ASP.NET Web API 2 provides the ability to batch requests. Uma aplicação cliente pode empacotar vários pedidos da API Web e enviá-los para o servidor num único pedido HTTP e receber uma única resposta HTTP que contém as respostas para cada pedido.A client application can package up several web API requests and send them to the server in a single HTTP request, and receive a single HTTP response that contains the replies to each request. Para obter mais informações, introdução ao suporte de lote na Web API e Web API OData.For more information, Introducing batch support in Web API and Web API OData.

Siga a especificação HTTP ao enviar uma respostaFollow the HTTP specification when sending a response

Uma API Web tem de devolver mensagens que contêm o código de estado HTTP correto para permitir ao cliente determinar como processar o resultado, os cabeçalhos HTTP adequados para que o cliente compreenda a natureza do resultado e um corpo corretamente formatado para permitir ao cliente analisar o resultado.A web API must return messages that contain the correct HTTP status code to enable the client to determine how to handle the result, the appropriate HTTP headers so that the client understands the nature of the result, and a suitably formatted body to enable the client to parse the result.

Por exemplo, uma operação POST deve devolver o código de estado 201 (Criado) e a mensagem de resposta deve incluir o URI do recurso recém-criado no cabeçalho Location da mensagem de resposta.For example, a POST operation should return status code 201 (Created) and the response message should include the URI of the newly created resource in the Location header of the response message.

Suporte a negociação do conteúdoSupport content negotiation

O corpo de uma mensagem de resposta pode conter dados numa variedade de formatos.The body of a response message may contain data in a variety of formats. Por exemplo, um pedido HTTP GET pode devolver os dados num formato JSON ou XML.For example, an HTTP GET request could return data in JSON, or XML format. Quando o cliente envia um pedido, este pode incluir um cabeçalho Accept que especifica os formatos de dados que pode processar.When the client submits a request, it can include an Accept header that specifies the data formats that it can handle. Estes formatos são especificados como tipos de suporte.These formats are specified as media types. Por exemplo, um cliente que emite um pedido GET para obter uma imagem pode especificar um cabeçalho Accept que lista os tipos de suportes de dados que o cliente pode processar, tais como image/jpeg, image/gif, image/png.For example, a client that issues a GET request that retrieves an image can specify an Accept header that lists the media types that the client can handle, such as image/jpeg, image/gif, image/png. Quando a API Web devolve o resultado, deve formatar os dados com um destes tipos de suporte e especificar o formato no cabeçalho Content-Type da resposta.When the web API returns the result, it should format the data by using one of these media types and specify the format in the Content-Type header of the response.

Se o cliente não especificar um cabeçalho Accept, utilize um formato sensível predefinido para o corpo da resposta.If the client does not specify an Accept header, then use a sensible default format for the response body. Por exemplo, a estrutura da API Web da ASP.NET está predefinida como JSON para os dados de texto.As an example, the ASP.NET Web API framework defaults to JSON for text-based data.

A abordagem HATEOAS permite que um cliente navegue e detete recursos a partir de um ponto de partida inicial.The HATEOAS approach enables a client to navigate and discover resources from an initial starting point. Tal é conseguido através de ligações que contém URIs. Quando um cliente emite um pedido HTTP GET para obter um recurso, a resposta deve conter os URIs que permitem que uma aplicação cliente localize rapidamente quaisquer recursos diretamente relacionados.This is achieved by using links containing URIs; when a client issues an HTTP GET request to obtain a resource, the response should contain URIs that enable a client application to quickly locate any directly related resources. Por exemplo, numa API Web que suporta uma solução de comércio eletrónico, um cliente pode ter realizado muitas encomendas.For example, in a web API that supports an e-commerce solution, a customer may have placed many orders. Quando uma aplicação cliente obtém os detalhes de um cliente, a resposta deve incluir ligações que permitem que a aplicação cliente envie pedidos HTTP GET que podem obter estas encomendas.When a client application retrieves the details for a customer, the response should include links that enable the client application to send HTTP GET requests that can retrieve these orders. Além disso, as ligações de estilo HATEOAS devem descrever as outras operações (POST, PUT, DELETE, entre outras) que cada recurso ligado suporta, juntamente com o URI correspondente para realizar cada pedido.Additionally, HATEOAS-style links should describe the other operations (POST, PUT, DELETE, and so on) that each linked resource supports together with the corresponding URI to perform each request. Esta abordagem é descrita mais detalhadamente nas design de API.This approach is described in more detail in API design.

Atualmente, não existe nenhuma norma que regule a implementação de HATEOAS, mas o exemplo a seguir ilustra uma abordagem possível.Currently there are no standards that govern the implementation of HATEOAS, but the following example illustrates one possible approach. Neste exemplo, um pedido HTTP GET que localiza os detalhes de um cliente devolve uma resposta que inclui ligações HATEOAS que referenciam as encomendas do cliente:In this example, an HTTP GET request that finds the details for a customer returns a response that includes HATEOAS links that reference the orders for that customer:

GET https://adventure-works.com/customers/2 HTTP/1.1
Accept: text/json
...
HTTP/1.1 200 OK
...
Content-Type: application/json; charset=utf-8
...
Content-Length: ...
{"CustomerID":2,"CustomerName":"Bert","Links":[
    {"rel":"self",
    "href":"https://adventure-works.com/customers/2",
    "action":"GET",
    "types":["text/xml","application/json"]},
    {"rel":"self",
    "href":"https://adventure-works.com/customers/2",
    "action":"PUT",
    "types":["application/x-www-form-urlencoded"]},
    {"rel":"self",
    "href":"https://adventure-works.com/customers/2",
    "action":"DELETE",
    "types":[]},
    {"rel":"orders",
    "href":"https://adventure-works.com/customers/2/orders",
    "action":"GET",
    "types":["text/xml","application/json"]},
    {"rel":"orders",
    "href":"https://adventure-works.com/customers/2/orders",
    "action":"POST",
    "types":["application/x-www-form-urlencoded"]}
]}

Neste exemplo, os dados do cliente são representados pela classe Customer, mostrada no fragmento de código seguinte.In this example, the customer data is represented by the Customer class shown in the following code snippet. As ligações HATEOAS são guardadas na propriedade da coleção Links:The HATEOAS links are held in the Links collection property:

public class Customer
{
    public int CustomerID { get; set; }
    public string CustomerName { get; set; }
    public List<Link> Links { get; set; }
    ...
}

public class Link
{
    public string Rel { get; set; }
    public string Href { get; set; }
    public string Action { get; set; }
    public string [] Types { get; set; }
}

A operação HTTP GET obtém os dados dos clientes do armazenamento e constrói um objeto Customer e, em seguida, preenche a coleção Links.The HTTP GET operation retrieves the customer data from storage and constructs a Customer object, and then populates the Links collection. O resultado é formatado como uma mensagem de resposta JSON.The result is formatted as a JSON response message. Cada ligação inclui os seguintes campos:Each link comprises the following fields:

  • A relação entre o objeto a ser devolvido e o objeto descrito através da ligação.The relationship between the object being returned and the object described by the link. Neste caso self indica que a ligação é uma referência ao próprio objeto (semelhante a uma this ponteiro em vários idiomas orientados a objeto), e orders é o nome de uma coleção que contém as informações relativas às encomendas.In this case self indicates that the link is a reference back to the object itself (similar to a this pointer in many object-oriented languages), and orders is the name of a collection containing the related order information.
  • A hiperligação (Href) do objeto que está a ser descrito pela ligação sob a forma de um URI.The hyperlink (Href) for the object being described by the link in the form of a URI.
  • O tipo de pedido HTTP (Action) que pode ser enviado para este URI.The type of HTTP request (Action) that can be sent to this URI.
  • O formato de quaisquer dados (Types) que devem ser fornecidos no pedido HTTP ou que podem ser devolvidos na resposta, depende do tipo de pedido.The format of any data (Types) that should be provided in the HTTP request or that can be returned in the response, depending on the type of the request.

As ligações HATEOAS mostradas na resposta HTTP de exemplo indicam que uma aplicação cliente pode realizar as seguintes operações:The HATEOAS links shown in the example HTTP response indicate that a client application can perform the following operations:

  • Um pedido HTTP GET enviado ao URI https://adventure-works.com/customers/2 para obter os detalhes do cliente (novamente).An HTTP GET request to the URI https://adventure-works.com/customers/2 to fetch the details of the customer (again). Os dados podem ser devolvidos como XML ou JSON.The data can be returned as XML or JSON.
  • Um pedido HTTP PUT enviado ao URI https://adventure-works.com/customers/2 para modificar os detalhes do cliente.An HTTP PUT request to the URI https://adventure-works.com/customers/2 to modify the details of the customer. Os novos dados devem ser fornecidos na mensagem do pedido no formato x-www-form-urlencoded.The new data must be provided in the request message in x-www-form-urlencoded format.
  • Um pedido HTTP DELETE enviado ao URI https://adventure-works.com/customers/2 para eliminar o cliente.An HTTP DELETE request to the URI https://adventure-works.com/customers/2 to delete the customer. O pedido não espera receber quaisquer informações adicionais nem dados devolvidos no corpo da mensagem de resposta.The request does not expect any additional information or return data in the response message body.
  • Um pedido HTTP GET enviado ao URI https://adventure-works.com/customers/2/orders para localizar todas as encomendas do cliente.An HTTP GET request to the URI https://adventure-works.com/customers/2/orders to find all the orders for the customer. Os dados podem ser devolvidos como XML ou JSON.The data can be returned as XML or JSON.
  • Um pedido HTTP PUT enviado ao URI https://adventure-works.com/customers/2/orders para criar uma nova encomenda para este cliente.An HTTP PUT request to the URI https://adventure-works.com/customers/2/orders to create a new order for this customer. Os dados devem ser fornecidos na mensagem do pedido no formato x-www-form-urlencoded.The data must be provided in the request message in x-www-form-urlencoded format.

Processamento de exceçõesHandling exceptions

Considere os seguintes pontos se uma operação emitir uma exceção não identificada.Consider the following points if an operation throws an uncaught exception.

Recolher exceções e devolver uma resposta significativa aos clientesCapture exceptions and return a meaningful response to clients

O código que implementa uma operação HTTP deve fornecer um processamento de exceção abrangente ao invés de permitir que exceções não identificadas se propaguem para a estrutura.The code that implements an HTTP operation should provide comprehensive exception handling rather than letting uncaught exceptions propagate to the framework. Se uma exceção tornar impossível concluir a operação com sucesso, a exceção poderá ser transmitida de volta na mensagem de resposta, mas deve incluir uma descrição significativa do erro que provocou a exceção.If an exception makes it impossible to complete the operation successfully, the exception can be passed back in the response message, but it should include a meaningful description of the error that caused the exception. A exceção também deve incluir o código de estado HTTP adequado ao invés de devolver simplesmente um código de estado 500 para cada situação.The exception should also include the appropriate HTTP status code rather than simply returning status code 500 for every situation. Por exemplo, se um pedido de utilizador der origem a uma atualização da base de dados que viola uma restrição (por exemplo, tentar eliminar um cliente com encomendas pendentes), deverá devolver o código de estado 409 (Conflito) e um corpo de mensagem que indica o motivo do conflito.For example, if a user request causes a database update that violates a constraint (such as attempting to delete a customer that has outstanding orders), you should return status code 409 (Conflict) and a message body indicating the reason for the conflict. Se alguma outra condição tornar o pedido irrealizável, poderá devolver o código de estado 400 (Pedido Incorreto).If some other condition renders the request unachievable, you can return status code 400 (Bad Request). Encontrará uma lista completa dos códigos de estado HTTP a definições de código de estado página no site da W3C.You can find a full list of HTTP status codes on the Status code definitions page on the W3C website.

O exemplo de código interceta condições diferentes e devolve uma resposta adequada.The code example traps different conditions and returns an appropriate response.

[HttpDelete]
[Route("customers/{id:int}")]
public IHttpActionResult DeleteCustomer(int id)
{
    try
    {
        // Find the customer to be deleted in the repository
        var customerToDelete = repository.GetCustomer(id);

        // If there is no such customer, return an error response
        // with status code 404 (Not Found)
        if (customerToDelete == null)
        {
                return NotFound();
        }

        // Remove the customer from the repository
        // The DeleteCustomer method returns true if the customer
        // was successfully deleted
        if (repository.DeleteCustomer(id))
        {
            // Return a response message with status code 204 (No Content)
            // To indicate that the operation was successful
            return StatusCode(HttpStatusCode.NoContent);
        }
        else
        {
            // Otherwise return a 400 (Bad Request) error response
            return BadRequest(Strings.CustomerNotDeleted);
        }
    }
    catch
    {
        // If an uncaught exception occurs, return an error response
        // with status code 500 (Internal Server Error)
        return InternalServerError();
    }
}

Dica

Não inclua informações que podem ser úteis para um atacante a tentar entrar na sua API.Do not include information that could be useful to an attacker attempting to penetrate your API.

Muitos servidores Web intercetam pessoalmente condições de erro antes de atingirem a API Web.Many web servers trap error conditions themselves before they reach the web API. Por exemplo, se configurar uma autenticação para um site e o utilizador não conseguir fornecer as informações de autenticação corretas, o servidor Web deverá responder com o código de estado 401 (Não Autorizado).For example, if you configure authentication for a web site and the user fails to provide the correct authentication information, the web server should respond with status code 401 (Unauthorized). Assim que o cliente tenha sido autenticado, o código pode executar as suas próprias verificações para confirmar que o cliente é capaz de aceder ao recurso pedido.Once a client has been authenticated, your code can perform its own checks to verify that the client should be able access the requested resource. Se esta autorização falhar, o código de estado 403 (Proibido) deverá ser devolvido.If this authorization fails, you should return status code 403 (Forbidden).

Processar exceções de forma consistente e registar informações sobre errosHandle exceptions consistently and log information about errors

Para resolver exceções de uma forma consistente, pondere implementar uma estratégia de processamento de erros em toda a API Web.To handle exceptions in a consistent manner, consider implementing a global error handling strategy across the entire web API. Também deve incorporar o registo de erros que recolhem todos os detalhes de cada exceção. Este registo de erros pode conter informações detalhadas, desde que não esteja acessível aos clientes através da Web.You should also incorporate error logging which captures the full details of each exception; this error log can contain detailed information as long as it is not made accessible over the web to clients.

Distinguir entre erros do lado do cliente e erros do lado do servidorDistinguish between client-side errors and server-side errors

O protocolo HTTP distingue entre os erros que ocorrem devido a uma aplicação cliente (os códigos de estado HTTP 4xx) e os erros provocados por um erro no servidor (os códigos de estado HTTP 5xx).The HTTP protocol distinguishes between errors that occur due to the client application (the HTTP 4xx status codes), and errors that are caused by a mishap on the server (the HTTP 5xx status codes). Confirme que respeitou esta convenção em todas as mensagens de resposta de erro.Make sure that you respect this convention in any error response messages.

Otimizar o acesso a dados do lado do clienteOptimizing client-side data access

Num ambiente distribuído, tal como o servidor Web e as aplicações cliente envolventes, uma das principais fontes de preocupação é a rede,In a distributed environment such as that involving a web server and client applications, one of the primary sources of concern is the network. que pode agir como um estrangulamento considerável, especialmente se uma aplicação cliente enviar pedidos ou receber dados frequentemente.This can act as a considerable bottleneck, especially if a client application is frequently sending requests or receiving data. Portanto, deve procurar minimizar a quantidade de tráfego que passa pela rede.Therefore you should aim to minimize the amount of traffic that flows across the network. Considere os seguintes pontos ao implementar o código para obter e manter dados dos pedidos:Consider the following points when you implement the code to retrieve and maintain data:

Suporte de colocação em cache do lado do clienteSupport client-side caching

O protocolo HTTP 1.1 suporta a colocação em cache de clientes e servidores intermédios através do qual um pedido é encaminhado pela utilização do cabeçalho Cache-Control.The HTTP 1.1 protocol supports caching in clients and intermediate servers through which a request is routed by the use of the Cache-Control header. Quando uma aplicação cliente envia um pedido HTTP GET para a API Web, a resposta pode incluir um cabeçalho Cache-Control que indica se os dados no corpo da resposta podem ser colocados em cache de forma segura pelo cliente ou por um servidor intermédio, através do qual o pedido foi encaminhado, e o período de tempo até expirar e ser considerado desatualizado.When a client application sends an HTTP GET request to the web API, the response can include a Cache-Control header that indicates whether the data in the body of the response can be safely cached by the client or an intermediate server through which the request has been routed, and for how long before it should expire and be considered out-of-date. O exemplo seguinte mostra um pedido HTTP GET e a resposta correspondente que inclui um cabeçalho Cache-Control:The following example shows an HTTP GET request and the corresponding response that includes a Cache-Control header:

GET https://adventure-works.com/orders/2 HTTP/1.1
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: text/json; charset=utf-8
Content-Length: ...
{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}

Neste exemplo, o cabeçalho Cache-Control especifica que os dados devolvidos devem expirar após 600 segundos, sendo apenas adequado para um único cliente, e não devem ser armazenados numa cache partilhada utilizada por outros clientes de cache (é private).In this example, the Cache-Control header specifies that the data returned should be expired after 600 seconds, and is only suitable for a single client and must not be stored in a shared cache used by other clients (it is private). O cabeçalho Cache-Control pode especificar public em vez de private, caso os dados possam ser armazenados numa cache partilhada, ou pode especificar no-store, caso os dados não sejam colocadas em cache pelo cliente.The Cache-Control header could specify public rather than private in which case the data can be stored in a shared cache, or it could specify no-store in which case the data must not be cached by the client. O exemplo de código seguinte mostra como construir um cabeçalho Cache-Control numa mensagem de resposta:The following code example shows how to construct a Cache-Control header in a response message:

public class OrdersController : ApiController
{
    ...
    [Route("api/orders/{id:int:min(0)}")]
    [HttpGet]
    public IHttpActionResult FindOrderByID(int id)
    {
        // Find the matching order
        Order order = ...;
        ...
        // Create a Cache-Control header for the response
        var cacheControlHeader = new CacheControlHeaderValue();
        cacheControlHeader.Private = true;
        cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
        ...

        // Return a response message containing the order and the cache control header
        OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)
        {
            CacheControlHeader = cacheControlHeader
        };
        return response;
    }
    ...
}

Esse código usa um personalizado IHttpActionResult com o nome de classe OkResultWithCaching.This code uses a custom IHttpActionResult class named OkResultWithCaching. Esta classe permite que o controlador defina os conteúdos do cabeçalho da cache:This class enables the controller to set the cache header contents:

public class OkResultWithCaching<T> : OkNegotiatedContentResult<T>
{
    public OkResultWithCaching(T content, ApiController controller)
        : base(content, controller) { }

    public OkResultWithCaching(T content, IContentNegotiator contentNegotiator, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
        : base(content, contentNegotiator, request, formatters) { }

    public CacheControlHeaderValue CacheControlHeader { get; set; }
    public EntityTagHeaderValue ETag { get; set; }

    public override async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response;
        try
        {
            response = await base.ExecuteAsync(cancellationToken);
            response.Headers.CacheControl = this.CacheControlHeader;
            response.Headers.ETag = ETag;
        }
        catch (OperationCanceledException)
        {
            response = new HttpResponseMessage(HttpStatusCode.Conflict) {ReasonPhrase = "Operation was cancelled"};
        }
        return response;
    }
}

Nota

O protocolo HTTP também define a diretiva no-cache para o cabeçalho Cache-Control.The HTTP protocol also defines the no-cache directive for the Cache-Control header. Curiosamente, esta diretiva não significa “não colocar em cache”, mas antes “revalidar as informações em cache com o servidor antes de as devolver”. Os dados podem ainda ser colocados em cache, mas são verificados sempre que são utilizados para garantir que ainda estão atuais.Rather confusingly, this directive does not mean "do not cache" but rather "revalidate the cached information with the server before returning it"; the data can still be cached, but it is checked each time it is used to ensure that it is still current.

A gestão de cache é da responsabilidade da aplicação cliente ou do servidor intermédio, porém, se implementada corretamente, pode poupar largura de banda e melhorar o desempenho ao remover a necessidade de obter dados que já tenham sido obtidos.Cache management is the responsibility of the client application or intermediate server, but if properly implemented it can save bandwidth and improve performance by removing the need to fetch data that has already been recently retrieved.

O valor max-age no cabeçalho de Cache-Control é apenas um guia e não uma garantia de que os dados correspondentes não serão alterados durante o período de tempo especificado.The max-age value in the Cache-Control header is only a guide and not a guarantee that the corresponding data won't change during the specified time. A API Web deve definir max-age para um valor adequado, consoante a volatilidade esperada dos dados.The web API should set the max-age to a suitable value depending on the expected volatility of the data. Quando este período expirar, o cliente deve eliminar o objeto da cache.When this period expires, the client should discard the object from the cache.

Nota

A maioria dos browsers modernos suporta a colocação em cache do lado do cliente ao adicionar os cabeçalhos cache-control adequados e ao examinar os cabeçalhos dos resultados, conforme descrito.Most modern web browsers support client-side caching by adding the appropriate cache-control headers to requests and examining the headers of the results, as described. No entanto, alguns browsers mais antigos não colocarão em cache os valores devolvidos por um URL que inclua uma cadeia de consulta.However, some older browsers will not cache the values returned from a URL that includes a query string. Normalmente, não é um problema para as aplicações cliente personalizadas que implementam a sua própria estratégia de gestão de cache com base no protocolo abordado aqui.This is not usually an issue for custom client applications which implement their own cache management strategy based on the protocol discussed here.

Alguns proxies mais antigos apresentam o mesmo comportamento e podem não colocar em cache pedidos com base nos URLs com cadeias de consulta.Some older proxies exhibit the same behavior and might not cache requests based on URLs with query strings. Tal pode ser um problema para aplicações cliente personalizadas que se ligam a um servidor Web através de um proxy deste tipo.This could be an issue for custom client applications that connect to a web server through such a proxy.

Fornecer ETags para otimizar o processamento da consultaProvide ETags to optimize query processing

Quando uma aplicação cliente obtém um objeto, a mensagem de resposta também pode incluir uma ETag (Etiqueta de Entidade).When a client application retrieves an object, the response message can also include an ETag (Entity Tag). Uma ETag é uma cadeia opaca que indica a versão de um recurso. Sempre que um recurso é alterado, a ETag também é modificada.An ETag is an opaque string that indicates the version of a resource; each time a resource changes the Etag is also modified. Esta ETag deve ser colocada em cache como parte dos dados pela aplicação cliente.This ETag should be cached as part of the data by the client application. O exemplo de código seguinte mostra como adicionar uma ETag como parte da resposta de um pedido HTTP GET.The following code example shows how to add an ETag as part of the response to an HTTP GET request. Este código utiliza o método GetHashCode de um objeto para gerar um valor numérico que identifica o objeto (se necessário, pode substituir este método e gerar a suas próprias hashes com um algoritmo como MD5):This code uses the GetHashCode method of an object to generate a numeric value that identifies the object (you can override this method if necessary and generate your own hash using an algorithm such as MD5) :

public class OrdersController : ApiController
{
    ...
    public IHttpActionResult FindOrderByID(int id)
    {
        // Find the matching order
        Order order = ...;
        ...

        var hashedOrder = order.GetHashCode();
        string hashedOrderEtag = $"\"{hashedOrder}\"";
        var eTag = new EntityTagHeaderValue(hashedOrderEtag);

        // Return a response message containing the order and the cache control header
        OkResultWithCaching<Order> response = new OkResultWithCaching<Order>(order, this)
        {
            ...,
            ETag = eTag
        };
        return response;
    }
    ...
}

A mensagem de resposta publicada pela API Web tem o seguinte aspeto:The response message posted by the web API looks like this:

HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: text/json; charset=utf-8
ETag: "2147483648"
Content-Length: ...
{"orderID":2,"productID":4,"quantity":2,"orderValue":10.00}

Dica

Por motivos de segurança, não permita que dados confidenciais ou dados devolvidos através de uma ligação autenticada (HTTPS) sejam colocados em cache.For security reasons, do not allow sensitive data or data returned over an authenticated (HTTPS) connection to be cached.

Uma aplicação cliente pode emitir um pedido GET subsequente para obter o mesmo recurso em qualquer altura e, se o recurso tiver sido alterado (tem uma ETag diferente), a versão em cache deverá ser eliminada e a nova versão adicionada à cache.A client application can issue a subsequent GET request to retrieve the same resource at any time, and if the resource has changed (it has a different ETag) the cached version should be discarded and the new version added to the cache. Se um recurso for grande e precisar de uma quantidade significativa de largura de banda para transmitir de volta para o cliente, os pedidos repetidos para obter os mesmos dados poderão tornar-se ineficientes.If a resource is large and requires a significant amount of bandwidth to transmit back to the client, repeated requests to fetch the same data can become inefficient. Para combater isto, o protocolo HTTP define o seguinte processo para otimizar pedidos GET que deve suportar numa API Web:To combat this, the HTTP protocol defines the following process for optimizing GET requests that you should support in a web API:

  • O cliente constrói um pedido GET que contém a ETag para a versão atualmente em cache do recurso referenciado num cabeçalho If-None-Match HTTP:The client constructs a GET request containing the ETag for the currently cached version of the resource referenced in an If-None-Match HTTP header:

    GET https://adventure-works.com/orders/2 HTTP/1.1
    If-None-Match: "2147483648"
    
  • A operação GET na API Web obtém a ETag atual dos dados solicitados (encomenda 2 no exemplo acima) e compara-a com o valor no cabeçalho If-None-Match.The GET operation in the web API obtains the current ETag for the requested data (order 2 in the above example), and compares it to the value in the If-None-Match header.

  • Se a ETag atual dos dados solicitados corresponder à ETag fornecida pelo pedido, o recurso não foi alterado e a API Web deverá devolver uma resposta HTTP com um corpo de mensagem vazio e um código de estado 304 (Não Modificado).If the current ETag for the requested data matches the ETag provided by the request, the resource has not changed and the web API should return an HTTP response with an empty message body and a status code of 304 (Not Modified).

  • Se a ETag atual dos dados solicitados não corresponder à ETag fornecida pelo pedido, os dados foram alterados e a API Web deverá devolver uma resposta HTTP com os novos dados no corpo da mensagem vazio e um código de estado 200 (OK).If the current ETag for the requested data does not match the ETag provided by the request, then the data has changed and the web API should return an HTTP response with the new data in the message body and a status code of 200 (OK).

  • Se os dados solicitados já não existirem, a API Web deverá devolver uma resposta HTTP com o código de estado 404 (Não Encontrado).If the requested data no longer exists then the web API should return an HTTP response with the status code of 404 (Not Found).

  • O cliente utiliza o código de estado para manter a cache.The client uses the status code to maintain the cache. Se os dados não tiverem sido alterados (código de estado 304), o objeto poderá permanecer em cache e a aplicação cliente deverá continuar a utilizar esta versão do objeto.If the data has not changed (status code 304) then the object can remain cached and the client application should continue to use this version of the object. Se os dados tiverem sido alterados (código de estado 200), o objeto em cache deverá ser eliminado e um novo inserido.If the data has changed (status code 200) then the cached object should be discarded and the new one inserted. Se os dados já não estiverem disponíveis (código de estado 404), o objeto deverá ser removido da cache.If the data is no longer available (status code 404) then the object should be removed from the cache.

Nota

Se o cabeçalho de resposta contiver o cabeçalho Cache-Control no-store, o objeto deverá ser sempre removido da cache, independentemente do código de estado HTTP.If the response header contains the Cache-Control header no-store then the object should always be removed from the cache regardless of the HTTP status code.

O código abaixo mostra o método FindOrderByID expandido para suportar o cabeçalho If-None-Match.The code below shows the FindOrderByID method extended to support the If-None-Match header. Tenha em atenção que, se o cabeçalho If-None-Match for omitido, a encomenda especificada será sempre obtida:Notice that if the If-None-Match header is omitted, the specified order is always retrieved:

public class OrdersController : ApiController
{
    [Route("api/orders/{id:int:min(0)}")]
    [HttpGet]
    public IHttpActionResult FindOrderByID(int id)
    {
        try
        {
            // Find the matching order
            Order order = ...;

            // If there is no such order then return NotFound
            if (order == null)
            {
                return NotFound();
            }

            // Generate the ETag for the order
            var hashedOrder = order.GetHashCode();
            string hashedOrderEtag = $"\"{hashedOrder}\"";

            // Create the Cache-Control and ETag headers for the response
            IHttpActionResult response;
            var cacheControlHeader = new CacheControlHeaderValue();
            cacheControlHeader.Public = true;
            cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);
            var eTag = new EntityTagHeaderValue(hashedOrderEtag);

            // Retrieve the If-None-Match header from the request (if it exists)
            var nonMatchEtags = Request.Headers.IfNoneMatch;

            // If there is an ETag in the If-None-Match header and
            // this ETag matches that of the order just retrieved,
            // then create a Not Modified response message
            if (nonMatchEtags.Count > 0 &&
                String.CompareOrdinal(nonMatchEtags.First().Tag, hashedOrderEtag) == 0)
            {
                response = new EmptyResultWithCaching()
                {
                    StatusCode = HttpStatusCode.NotModified,
                    CacheControlHeader = cacheControlHeader,
                    ETag = eTag
                };
            }
            // Otherwise create a response message that contains the order details
            else
            {
                response = new OkResultWithCaching<Order>(order, this)
                {
                    CacheControlHeader = cacheControlHeader,
                    ETag = eTag
                };
            }

            return response;
        }
        catch
        {
            return InternalServerError();
        }
    }
...
}

Este exemplo incorpora uma classe IHttpActionResult personalizada adicional denominada EmptyResultWithCaching.This example incorporates an additional custom IHttpActionResult class named EmptyResultWithCaching. Esta classe simplesmente age como um wrapper em torno de um objeto HttpResponseMessage que não contem um corpo de resposta:This class simply acts as a wrapper around an HttpResponseMessage object that does not contain a response body:

public class EmptyResultWithCaching : IHttpActionResult
{
    public CacheControlHeaderValue CacheControlHeader { get; set; }
    public EntityTagHeaderValue ETag { get; set; }
    public HttpStatusCode StatusCode { get; set; }
    public Uri Location { get; set; }

    public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = new HttpResponseMessage(StatusCode);
        response.Headers.CacheControl = this.CacheControlHeader;
        response.Headers.ETag = this.ETag;
        response.Headers.Location = this.Location;
        return response;
    }
}

Dica

Neste exemplo, a ETag dos dados é gerada por hashes dos dados obtidos a partir da origem de dados subjacente.In this example, the ETag for the data is generated by hashing the data retrieved from the underlying data source. Se a ETag puder ser calculada de outro modo, o processo poderá ser ainda mais otimizado e os dados apenas precisarão de ser obtidos a partir da origem de dados se tiverem sido alterados.If the ETag can be computed in some other way, then the process can be optimized further and the data only needs to be fetched from the data source if it has changed. Esta abordagem é particularmente útil quando os dados são grandes ou o acesso à origem de dados pode resultar numa latência significativa (por exemplo, se a origem de dados é uma base de dados remota).This approach is especially useful if the data is large or accessing the data source can result in significant latency (for example, if the data source is a remote database).

Utilizar ETags para Suportar a Simultaneidade OtimistaUse ETags to Support Optimistic Concurrency

Para ativar as atualizações de dados colocados em cache anteriormente, o protocolo HTTP suporta uma estratégia de simultaneidade otimista.To enable updates over previously cached data, the HTTP protocol supports an optimistic concurrency strategy. Se, após a obtenção e a colocação em cache de um recurso, a aplicação cliente enviar subsequentemente um pedido PUT ou DELETE para alterar ou remover o recurso, este deverá incluir um cabeçalho If-Match que faça referência à ETag.If, after fetching and caching a resource, the client application subsequently sends a PUT or DELETE request to change or remove the resource, it should include in If-Match header that references the ETag. A API Web pode, em seguida, utilizar estas informações para determinar se o recurso já foi alterado por outro utilizador desde que foi obtido e enviar uma resposta adequada de volta para a aplicação cliente da seguinte forma:The web API can then use this information to determine whether the resource has already been changed by another user since it was retrieved and send an appropriate response back to the client application as follows:

  • O cliente constrói um pedido PUT que contém os novos detalhes do recurso e da ETag para a versão atualmente em cache do recurso referenciado num cabeçalho If-Match HTTP.The client constructs a PUT request containing the new details for the resource and the ETag for the currently cached version of the resource referenced in an If-Match HTTP header. O exemplo seguinte mostra um pedido PUT que atualiza uma encomenda:The following example shows a PUT request that updates an order:

    PUT https://adventure-works.com/orders/1 HTTP/1.1
    If-Match: "2282343857"
    Content-Type: application/x-www-form-urlencoded
    Content-Length: ...
    productID=3&quantity=5&orderValue=250
    
  • A operação PUT na API Web obtém a ETag atual dos dados solicitados (encomenda 1 no exemplo acima) e compara-a com o valor no cabeçalho If-Match.The PUT operation in the web API obtains the current ETag for the requested data (order 1 in the above example), and compares it to the value in the If-Match header.

  • Se a ETag atual dos dados solicitados corresponder à ETag fornecida pelo pedido, o recurso não foi alterado e a API Web deverá realizar a atualização e devolver uma mensagem com o código de estado HTTP 204 (Sem Conteúdo) se for bem-sucedida.If the current ETag for the requested data matches the ETag provided by the request, the resource has not changed and the web API should perform the update, returning a message with HTTP status code 204 (No Content) if it is successful. A resposta pode incluir os cabeçalhos Cache-Control e ETag da versão atualizada do recurso.The response can include Cache-Control and ETag headers for the updated version of the resource. A resposta deve incluir sempre o cabeçalho Location que referencia o URI do recurso recém-atualizado.The response should always include the Location header that references the URI of the newly updated resource.

  • Se a ETag atual dos dados solicitados não corresponder à ETag fornecida pelo pedido, os dados foram alterados por outro utilizador desde que foram obtidos e a API Web deverá devolver uma resposta HTTP com um corpo de mensagem vazio e um código de estado 412 (Falha na Pré-condição).If the current ETag for the requested data does not match the ETag provided by the request, then the data has been changed by another user since it was fetched and the web API should return an HTTP response with an empty message body and a status code of 412 (Precondition Failed).

  • Se os recursos a serem atualizados já não existirem, a API Web deverá devolver uma resposta HTTP com o código de estado 404 (Não Encontrado).If the resource to be updated no longer exists then the web API should return an HTTP response with the status code of 404 (Not Found).

  • O cliente utiliza os cabeçalhos de código de estado e resposta para manter a cache.The client uses the status code and response headers to maintain the cache. Se os dados tiverem sido atualizados (código de estado 204), o objeto poderá permanecer em cache (desde que o cabeçalho Cache-Control não especifique no-store), mas a ETag deverá ser atualizada.If the data has been updated (status code 204) then the object can remain cached (as long as the Cache-Control header does not specify no-store) but the ETag should be updated. Se os dados tiverem sido alterados por outro utilizador (código de estado 412) ou não tiverem sido encontrados (código de estado 404), o objeto em cache deverá ser eliminado.If the data was changed by another user changed (status code 412) or not found (status code 404) then the cached object should be discarded.

O exemplo de código seguinte mostra uma implementação da operação PUT para o Controlador de encomendas:The next code example shows an implementation of the PUT operation for the Orders controller:

public class OrdersController : ApiController
{
    [HttpPut]
    [Route("api/orders/{id:int}")]
    public IHttpActionResult UpdateExistingOrder(int id, DTOOrder order)
    {
        try
        {
            var baseUri = Constants.GetUriFromConfig();
            var orderToUpdate = this.ordersRepository.GetOrder(id);
            if (orderToUpdate == null)
            {
                return NotFound();
            }

            var hashedOrder = orderToUpdate.GetHashCode();
            string hashedOrderEtag = $"\"{hashedOrder}\"";

            // Retrieve the If-Match header from the request (if it exists)
            var matchEtags = Request.Headers.IfMatch;

            // If there is an Etag in the If-Match header and
            // this etag matches that of the order just retrieved,
            // or if there is no etag, then update the Order
            if (((matchEtags.Count > 0 &&
                String.CompareOrdinal(matchEtags.First().Tag, hashedOrderEtag) == 0)) ||
                matchEtags.Count == 0)
            {
                // Modify the order
                orderToUpdate.OrderValue = order.OrderValue;
                orderToUpdate.ProductID = order.ProductID;
                orderToUpdate.Quantity = order.Quantity;

                // Save the order back to the data store
                // ...

                // Create the No Content response with Cache-Control, ETag, and Location headers
                var cacheControlHeader = new CacheControlHeaderValue();
                cacheControlHeader.Private = true;
                cacheControlHeader.MaxAge = new TimeSpan(0, 10, 0);

                hashedOrder = order.GetHashCode();
                hashedOrderEtag = $"\"{hashedOrder}\"";
                var eTag = new EntityTagHeaderValue(hashedOrderEtag);

                var location = new Uri($"{baseUri}/{Constants.ORDERS}/{id}");
                var response = new EmptyResultWithCaching()
                {
                    StatusCode = HttpStatusCode.NoContent,
                    CacheControlHeader = cacheControlHeader,
                    ETag = eTag,
                    Location = location
                };

                return response;
            }

            // Otherwise return a Precondition Failed response
            return StatusCode(HttpStatusCode.PreconditionFailed);
        }
        catch
        {
            return InternalServerError();
        }
    }
    ...
}

Dica

A utilização do cabeçalho If-Match é inteiramente opcional e, se for omitido, a API Web tentará sempre atualizar a encomenda especificada, possivelmente substituindo às cegas uma atualização realizada por outro utilizador.Use of the If-Match header is entirely optional, and if it is omitted the web API will always attempt to update the specified order, possibly blindly overwriting an update made by another user. Para evitar problemas devido a atualizações perdidas, forneça sempre um cabeçalho If-Match.To avoid problems due to lost updates, always provide an If-Match header.

Processamento de pedidos e respostas grandesHandling large requests and responses

Podem haver ocasiões em que uma aplicação cliente precisa de emitir pedidos que enviam ou recebem dados que podem ter vários megabytes (ou maior) de tamanho.There may be occasions when a client application needs to issue requests that send or receive data that may be several megabytes (or bigger) in size. Se ficar a aguardar enquanto esta quantidade de dados é transmitida, tal pode fazer com que a aplicação cliente deixe de responder.Waiting while this amount of data is transmitted could cause the client application to become unresponsive. Quando precisar de processar pedidos que incluam quantidades significativas de dados, considere os seguintes pontos:Consider the following points when you need to handle requests that include significant amounts of data:

Otimizar pedidos e respostas que envolvem grandes objetosOptimize requests and responses that involve large objects

Alguns recursos podem ser objetos grandes ou incluir campos grandes, como imagens gráficas ou outros tipos de dados binários.Some resources may be large objects or include large fields, such as graphics images or other types of binary data. Uma API Web deve suportar a transmissão em fluxo para permitir um carregamento e uma transferência otimizados destes recursos.A web API should support streaming to enable optimized uploading and downloading of these resources.

O protocolo HTTP fornece o mecanismo de codificação de transferência segmentada para transmitir em fluxo objetos de dados de grande dimensão de volta para um cliente.The HTTP protocol provides the chunked transfer encoding mechanism to stream large data objects back to a client. Quando o cliente envia um pedido HTTP GET para um objeto grande, a API Web pode enviar a resposta em segmentos por etapas através de uma ligação HTTP.When the client sends an HTTP GET request for a large object, the web API can send the reply back in piecemeal chunks over an HTTP connection. O comprimento dos dados na resposta pode ser desconhecido inicialmente (pode ser gerado), para que o servidor que aloja a API web deve enviar uma mensagem de resposta com cada segmento que especifica a codificação de transferência: Cabeçalho em partes em vez de um cabeçalho Content-Length.The length of the data in the reply may not be known initially (it might be generated), so the server hosting the web API should send a response message with each chunk that specifies the Transfer-Encoding: Chunked header rather than a Content-Length header. A aplicação cliente pode receber cada um dos segmentos à vez para criar a resposta completa.The client application can receive each chunk in turn to build up the complete response. A transferência de dados fica concluída quando o servidor envia um segmento final com tamanho igual a zero.The data transfer completes when the server sends back a final chunk with zero size.

É concebível que um único pedido possa resultar num objeto enorme que consome recursos consideráveis.A single request could conceivably result in a massive object that consumes considerable resources. Se durante o processo de transmissão em fluxo, a API web determinar que a quantidade de dados num pedido excedeu alguns limites aceitáveis, ele pode abortar a operação e devolver uma mensagem de resposta com o código de estado 413 (pedido entidade demasiado grande).If during the streaming process the web API determines that the amount of data in a request has exceeded some acceptable bounds, it can abort the operation and return a response message with status code 413 (Request Entity Too Large).

Pode minimizar o tamanho dos objetos grandes transmitidos através da rede com a compressão HTTP.You can minimize the size of large objects transmitted over the network by using HTTP compression. Esta abordagem ajuda a reduzir a quantidade de tráfego de rede e a latência de rede associada, mas à custa da necessidade de um processamento adicional no cliente e no servidor a alojar a API Web.This approach helps to reduce the amount of network traffic and the associated network latency, but at the cost of requiring additional processing at the client and the server hosting the web API. Por exemplo, uma aplicação cliente que conta receber dados comprimidos pode incluir um cabeçalho de pedido Accept-Encoding: gzip (também podem ser especificados outros algoritmo de compressão de dados).For example, a client application that expects to receive compressed data can include an Accept-Encoding: gzip request header (other data compression algorithms can also be specified). Se o servidor suportar a compressão, este deverá responder com o conteúdo presente num formato gzip no corpo da mensagem e o cabeçalho de resposta Content-Encoding: gzip.If the server supports compression it should respond with the content held in gzip format in the message body and the Content-Encoding: gzip response header.

Pode combinar a compressão codificado com a transmissão em fluxo; comprima os dados primeiro antes da sua transmissão em fluxo e especifique a codificação de conteúdo gzip e a codificação da transferência segmentada nos cabeçalhos das mensagens.You can combine encoded compression with streaming; compress the data first before streaming it, and specify the gzip content encoding and chunked transfer encoding in the message headers. Tenha em atenção também que alguns servidores Web (por exemplo, o Internet Information Server) podem ser configurados para comprimir automaticamente as respostas HTTP, independentemente de a API Web comprimir ou não os dados.Also note that some web servers (such as Internet Information Server) can be configured to automatically compress HTTP responses regardless of whether the web API compresses the data or not.

Implementar respostas parciais para clientes que não suportam operações assíncronasImplement partial responses for clients that do not support asynchronous operations

Como alternativa à transmissão em fluxo assíncrona, uma aplicação cliente pode explicitamente solicitar dados de objetos grandes em segmentos, conhecidos como respostas parciais.As an alternative to asynchronous streaming, a client application can explicitly request data for large objects in chunks, known as partial responses. A aplicação cliente envia um pedido HTTP HEAD para obter informações sobre o objeto.The client application sends an HTTP HEAD request to obtain information about the object. Se a API Web suportar respostas parciais, deverá responder ao pedido HEAD com uma mensagem de resposta que contém um cabeçalho Accept-Ranges e um cabeçalho Content-Length que indica o tamanho total do objeto, mas o corpo da mensagem deverá estar vazio.If the web API supports partial responses if should respond to the HEAD request with a response message that contains an Accept-Ranges header and a Content-Length header that indicates the total size of the object, but the body of the message should be empty. A aplicação cliente pode utilizar estas informações para construir uma série de pedidos GET que especificam um intervalo de bytes a receber.The client application can use this information to construct a series of GET requests that specify a range of bytes to receive. A API Web deve devolver uma mensagem de resposta com o estado HTTP 206 (Conteúdo Parcial), um cabeçalho Content-Length que especifica a quantidade real dos dados incluídos no corpo da mensagem da resposta e um cabeçalho Content-Range que indica qual a parte (por exemplo, bytes 4000 para 8000) do objeto que representa estes dados.The web API should return a response message with HTTP status 206 (Partial Content), a Content-Length header that specifies the actual amount of data included in the body of the response message, and a Content-Range header that indicates which part (such as bytes 4000 to 8000) of the object this data represents.

Pedidos de HTTP HEAD e as respostas parciais são descritas mais detalhadamente nas design de API.HTTP HEAD requests and partial responses are described in more detail in API design.

Evitar o envio desnecessários de mensagens de estado 100-Continue nas aplicações clienteAvoid sending unnecessary 100-Continue status messages in client applications

Uma aplicação cliente prestes a enviar uma grande quantidade de dados para um servidor poderá determinar primeiro se o servidor está realmente disposto a aceitar o pedido.A client application that is about to send a large amount of data to a server may determine first whether the server is actually willing to accept the request. Antes de enviar os dados, a aplicação cliente pode submeter um pedido HTTP com um Expect: 100-continue cabeçalho, um cabeçalho Content-Length que indica o tamanho de dados, mas um corpo de mensagem vazio.Prior to sending the data, the client application can submit an HTTP request with an Expect: 100-Continue header, a Content-Length header that indicates the size of the data, but an empty message body. Se o servidor estiver disposto a processar o pedido, deverá responder com uma mensagem que especifica o estado HTTP 100 (Continuar).If the server is willing to handle the request, it should respond with a message that specifies the HTTP status 100 (Continue). Assim, a aplicação cliente pode avançar e enviar o pedido completo, incluindo os dados no corpo da mensagem.The client application can then proceed and send the complete request including the data in the message body.

Se estiver a alojar um serviço com o IIS, o driver HTTP. sys Deteta automaticamente e processa Expect: 100-continue cabeçalhos antes de transmitir os pedidos para a sua aplicação web.If you are hosting a service by using IIS, the HTTP.sys driver automatically detects and handles Expect: 100-Continue headers before passing requests to your web application. o que significa que é pouco provável ver estes cabeçalhos no código da aplicação e pode assumir que o IIS já filtrou todas as mensagens que considera serem inadequadas ou demasiado grandes.This means that you are unlikely to see these headers in your application code, and you can assume that IIS has already filtered any messages that it deems to be unfit or too large.

Se estiver a criar aplicações de cliente utilizando o .NET Framework, em seguida, todas as mensagens POST e PUT enviarão primeiro mensagens com Expect: 100-continue cabeçalhos por predefinição.If you are building client applications by using the .NET Framework, then all POST and PUT messages will first send messages with Expect: 100-Continue headers by default. Tal como acontece com o lado do servidor, o processo é tratado de forma transparente pelo .NET Framework.As with the server-side, the process is handled transparently by the .NET Framework. No entanto, este processo faz com que cada pedido POST e PUT crie dois percursos de ida e volta ao servidor, mesmo para pedidos pequenos.However, this process results in each POST and PUT request causing two round-trips to the server, even for small requests. Se a aplicação não estiver a enviar pedidos com grandes quantidades de dados, poderá desativar esta funcionalidade com a classe ServicePointManager para criar objetos ServicePoint na aplicação cliente.If your application is not sending requests with large amounts of data, you can disable this feature by using the ServicePointManager class to create ServicePoint objects in the client application. Um objeto ServicePoint processa as ligações que o cliente realiza para um servidor com base nos fragmentos de esquema e alojamento dos URIs que identificam os recursos do servidor.A ServicePoint object handles the connections that the client makes to a server based on the scheme and host fragments of URIs that identify resources on the server. Pode, em seguida, definir a propriedade Expect100Continue do objeto ServicePoint como false.You can then set the Expect100Continue property of the ServicePoint object to false. Subsequentes todos os pedidos POST e PUT feitos pelo cliente através de um URI que satisfaz os fragmentos de esquema e alojamento do ServicePoint objeto será enviado sem Expect: 100-continue cabeçalhos.All subsequent POST and PUT requests made by the client through a URI that matches the scheme and host fragments of the ServicePoint object will be sent without Expect: 100-Continue headers. O código seguinte mostra como configurar um objeto ServicePoint que configura todos os pedidos enviados para os URIs com um esquema http e um anfitrião de www.contoso.com.The following code shows how to configure a ServicePoint object that configures all requests sent to URIs with a scheme of http and a host of www.contoso.com.

Uri uri = new Uri("https://www.contoso.com/");
ServicePoint sp = ServicePointManager.FindServicePoint(uri);
sp.Expect100Continue = false;

Também pode definir a estática Expect100Continue propriedade do ServicePointManager classe para especificar o valor predefinido desta propriedade para todos os criados subsequentemente ServicePoint objetos.You can also set the static Expect100Continue property of the ServicePointManager class to specify the default value of this property for all subsequently created ServicePoint objects.

Suporte de paginação para pedidos que podem devolver grandes quantidades de objetosSupport pagination for requests that may return large numbers of objects

Se uma coleção contiver um grande número de recursos, a emissão de um pedido GET para o URI correspondente poderá resultar num processamento significativo no servidor a alojar a API Web e afetar o desempenho e gerar uma quantidade significativa de tráfego de rede, resultando numa maior latência.If a collection contains a large number of resources, issuing a GET request to the corresponding URI could result in significant processing on the server hosting the web API affecting performance, and generate a significant amount of network traffic resulting in increased latency.

Para processar estes casos, a API Web deve suportar cadeias de consulta que ativam a aplicação cliente para refinar os pedidos ou obter dados em blocos (ou páginas) discretos e mais fáceis de gerir.To handle these cases, the web API should support query strings that enable the client application to refine requests or fetch data in more manageable, discrete blocks (or pages). O código abaixo mostra o método GetAllOrders para no controlador Orders.The code below shows the GetAllOrders method in the Orders controller. Este método obtém os detalhes das encomendas.This method retrieves the details of orders. Se este método não tiver restrições, será concebível devolver uma grande quantidade de dados.If this method was unconstrained, it could conceivably return a large amount of data. Os parâmetros limit e offset destinam-se a reduzir o volume de dados para um subconjunto mais pequeno; neste caso, por predefinição, apenas as primeiras 10 encomendas:The limit and offset parameters are intended to reduce the volume of data to a smaller subset, in this case only the first 10 orders by default:

public class OrdersController : ApiController
{
    ...
    [Route("api/orders")]
    [HttpGet]
    public IEnumerable<Order> GetAllOrders(int limit=10, int offset=0)
    {
        // Find the number of orders specified by the limit parameter
        // starting with the order specified by the offset parameter
        var orders = ...
        return orders;
    }
    ...
}

Uma aplicação cliente pode emitir um pedido para obter 30 encomendas a começar no desvio 50 com o URI https://www.adventure-works.com/api/orders?limit=30&offset=50.A client application can issue a request to retrieve 30 orders starting at offset 50 by using the URI https://www.adventure-works.com/api/orders?limit=30&offset=50.

Dica

Evite ativar aplicações cliente para especificar cadeias de consulta que resultam num URI com mais de 2000 caracteres de comprimento.Avoid enabling client applications to specify query strings that result in a URI that is more than 2000 characters long. Muitos clientes e servidores Web não conseguem processar URIs tão longos.Many web clients and servers cannot handle URIs that are this long.

Manter a capacidade de resposta, a escalabilidade e a disponibilidadeMaintaining responsiveness, scalability, and availability

A mesma API web pode ser utilizada por muitas aplicações de cliente em execução em qualquer lugar do mundo.The same web API might be used by many client applications running anywhere in the world. É importante confirmar se a API Web é implementada para manter a capacidade de resposta sob uma carga pesada, ser dimensionável para suportar uma carga de trabalho altamente variável e garantir a disponibilidade para clientes que executam operações críticas para a empresa.It is important to ensure that the web API is implemented to maintain responsiveness under a heavy load, to be scalable to support a highly varying workload, and to guarantee availability for clients that perform business-critical operations. Quando determinar como cumprir estes requisitos, considere os seguintes pontos:Consider the following points when determining how to meet these requirements:

Fornecer suporte assíncrono para pedidos de execução longaProvide asynchronous support for long-running requests

Um pedido que possa demorar muito tempo a processar deve ser realizado sem bloquear o cliente que submeteu o pedido.A request that might take a long time to process should be performed without blocking the client that submitted the request. A API Web pode realizar algumas verificações iniciais para validar o pedido, iniciar uma tarefa separada para realizar o trabalho e, em seguida, devolver uma mensagem de resposta com o código HTTP 202 (Aceite).The web API can perform some initial checking to validate the request, initiate a separate task to perform the work, and then return a response message with HTTP code 202 (Accepted). A tarefa pode ser executada de forma assíncrona como parte do processamento da API Web ou pode ser descarregada para uma tarefa em segundo plano.The task could run asynchronously as part of the web API processing, or it could be offloaded to a background task.

A API Web também deve fornecer um mecanismo para devolver os resultados do processamento à aplicação de cliente.The web API should also provide a mechanism to return the results of the processing to the client application. Poderá conseguir isto ao fornecer um mecanismo de consulta para aplicações cliente para consultar periodicamente se o processamento foi concluído e obter o resultado ou permitir que a API Web envie uma notificação quando a operação for concluída.You can achieve this by providing a polling mechanism for client applications to periodically query whether the processing has finished and obtain the result, or enabling the web API to send a notification when the operation has completed.

Pode implementar um mecanismo de consulta simples ao fornecer uma consulta URI que funciona como um recurso virtual com a seguinte abordagem:You can implement a simple polling mechanism by providing a polling URI that acts as a virtual resource using the following approach:

  1. A aplicação cliente envia o pedido inicial para a API Web.The client application sends the initial request to the web API.
  2. A API Web armazena informações sobre o pedido numa tabela contida num armazenamento de tabelas ou na Microsoft Azure Cache e gera uma chave exclusiva para esta entrada, possivelmente sob a forma de um GUID.The web API stores information about the request in a table held in table storage or Microsoft Azure Cache, and generates a unique key for this entry, possibly in the form of a GUID.
  3. A API Web inicia o processamento como uma tarefa separada.The web API initiates the processing as a separate task. A API Web regista o estado da tarefa na tabela como Em execução.The web API records the state of the task in the table as Running.
  4. A API Web devolve uma mensagem de resposta com o código de estado HTTP 202 (Aceite) e o GUID da entrada da tabela no corpo da mensagem.The web API returns a response message with HTTP status code 202 (Accepted), and the GUID of the table entry in the body of the message.
  5. Quando a tarefa for concluída, a API Web armazena os resultados na tabela e define o estado da tarefa como Concluído.When the task has completed, the web API stores the results in the table, and sets the state of the task to Complete. Tenha em atenção que, se a tarefa falhar, a API Web poderá também armazenar informações sobre a falha e definir o estado como Com Falhas.Note that if the task fails, the web API could also store information about the failure and set the status to Failed.
  6. Enquanto a tarefa é executada, o cliente pode continuar a executar o seu próprio processamento.While the task is running, the client can continue performing its own processing. Pode enviar periodicamente um pedido para o URI /polling/{guid} em que {guid} é o GUID devolvido na mensagem de resposta 202 pela API Web.It can periodically send a request to the URI /polling/{guid} where {guid} is the GUID returned in the 202 response message by the web API.
  7. A API Web no URI /polling/{guid} consulta o estado da tarefa correspondente na tabela e devolve uma mensagem de resposta com o código de estado HTTP 200 (OK) que contém este estado (Em Execução, Concluído ou Com Falhas).The web API at the /polling/{guid} URI queries the state of the corresponding task in the table and returns a response message with HTTP status code 200 (OK) containing this state (Running, Complete, or Failed). Se a tarefa tiver sido concluída ou falhar, a mensagem de resposta também poderá incluir os resultados do processamento ou quaisquer informações disponíveis sobre o motivo da falha.If the task has completed or failed, the response message can also include the results of the processing or any information available about the reason for the failure.

As opções para implementar as notificações incluem:Options for implementing notifications include:

  • Utilizar um hub de notificação para enviar respostas assíncronas para aplicativos cliente.Using a notification hub to push asynchronous responses to client applications. Para obter mais informações, consulte enviar notificações a utilizadores específicos com Notification Hubs do Azure.For more information, see Send notifications to specific users by using Azure Notification Hubs.
  • Utilizar o modelo Comet para manter uma ligação de rede persistente entre o cliente e o servidor a alojar a API Web e utilizar esta ligação para enviar mensagens do servidor de volta para o cliente.Using the Comet model to retain a persistent network connection between the client and the server hosting the web API, and using this connection to push messages from the server back to the client. O artigo da revista MSDN Building a Simple Comet Application in the Microsoft .NET Framework (Criar uma Aplicação Comet Simples no Microsoft .NET Framework) descreve uma solução de exemplo.The MSDN magazine article Building a Simple Comet Application in the Microsoft .NET Framework describes an example solution.
  • Utilizar SignalR para enviar dados em tempo real do servidor web para o cliente através de uma ligação de rede persistente.Using SignalR to push data in real time from the web server to the client over a persistent network connection. SignalR está disponível para aplicações Web da ASP.NET como um pacote NuGet.SignalR is available for ASP.NET web applications as a NuGet package. Pode encontrar mais informações no site ASP.NET SignalR.You can find more information on the ASP.NET SignalR website.

Confirmar que cada pedido está sem estadoEnsure that each request is stateless

Cada pedido deve ser considerado atómico.Each request should be considered atomic. Não deve haver nenhuma dependência entre um pedido realizado por uma aplicação cliente e quaisquer pedidos subsequentes submetidos pelo mesmo cliente.There should be no dependencies between one request made by a client application and any subsequent requests submitted by the same client. Esta abordagem ajuda na escalabilidade; as instâncias do serviço Web podem ser implementadas em vários servidores.This approach assists in scalability; instances of the web service can be deployed on a number of servers. Os pedidos de cliente podem ser direcionados para qualquer uma destas instâncias e os resultados devem ser sempre iguais.Client requests can be directed at any of these instances and the results should always be the same. Também melhora a disponibilidade por um motivo semelhante. Se um servidor Web falhar, os pedidos podem ser encaminhados para outra instância (com o Gestor de Tráfego do Azure) enquanto o servidor é reiniciado, sem que tal produza efeitos nocivos às aplicações cliente.It also improves availability for a similar reason; if a web server fails requests can be routed to another instance (by using Azure Traffic Manager) while the server is restarted with no ill effects on client applications.

Controlar clientes e implementar limitação para reduzir as hipóteses de ataques DOSTrack clients and implement throttling to reduce the chances of DOS attacks

Se um cliente específico realizar um grande número de pedidos num determinado período de tempo, este poderá monopolizar o serviço e afetar o desempenho de outros clientes.If a specific client makes a large number of requests within a given period of time it might monopolize the service and affect the performance of other clients. Para atenuar este problema, uma API Web pode monitorizar as chamadas das aplicações cliente, através do controlo do endereço IP de todos os pedidos recebidos ou do registo de todos os acessos autenticados.To mitigate this issue, a web API can monitor calls from client applications either by tracking the IP address of all incoming requests or by logging each authenticated access. Pode utilizar estas informações para limitar o acesso aos recursos.You can use this information to limit resource access. Se um cliente exceder um limite definido, a API Web poderá devolver uma mensagem de resposta com o estado 503 (Serviço Indisponível) e incluir um cabeçalho Retry-After que especificará quando é que o cliente pode enviar o pedido seguinte sem que este seja recusado.If a client exceeds a defined limit, the web API can return a response message with status 503 (Service Unavailable) and include a Retry-After header that specifies when the client can send the next request without it being declined. Esta estratégia pode ajudar a reduzir as possibilidades de um ataque Denial Of Service (DOS) a partir de um conjunto de clientes a bloquear o sistema.This strategy can help to reduce the chances of a Denial Of Service (DOS) attack from a set of clients stalling the system.

Gerir atentamente ligações HTTP persistentesManage persistent HTTP connections carefully

O protocolo HTTP suporta ligações HTTP persistentes quando estiverem disponíveis.The HTTP protocol supports persistent HTTP connections where they are available. A especificação HTTP 1.0 adicionada Connection: Keep-Alive cabeçalho que permite que uma aplicação cliente indicar ao servidor que pode utilizar a mesma ligação para enviar as solicitações subseqüentes, em vez de abrir novos.The HTTP 1.0 specification added the Connection:Keep-Alive header that enables a client application to indicate to the server that it can use the same connection to send subsequent requests rather than opening new ones. A ligação será fechada automaticamente se o cliente não reutilizar a ligação dentro de um período de tempo definido pelo anfitrião.The connection closes automatically if the client does not reuse the connection within a period defined by the host. Este comportamento está predefinido no HTTP 1.1, tal como utilizado pelos serviços do Azure, pelo que não é necessário incluir cabeçalhos Keep-Alive nas mensagens.This behavior is the default in HTTP 1.1 as used by Azure services, so there is no need to include Keep-Alive headers in messages.

Manter uma ligação aberta pode ajudar a melhorar a capacidade de resposta ao reduzir a latência e o congestionamento da rede, mas pode ser prejudicial para a escalabilidade ao manter ligações desnecessárias abertas por um período de tempo superior ao necessário, limitando a capacidade de outros clientes estabelecerem uma ligação em simultâneo.Keeping a connection open can help to improve responsiveness by reducing latency and network congestion, but it can be detrimental to scalability by keeping unnecessary connections open for longer than required, limiting the ability of other concurrent clients to connect. Poderá também afetar a autonomia da bateria se a aplicação cliente for executada num dispositivo móvel. Se a aplicação apenas realizar pedidos ocasionais ao servidor, manter uma ligação aberta poderá drenar a bateria mais rapidamente.It can also affect battery life if the client application is running on a mobile device; if the application only makes occasional requests to the server, maintaining an open connection can cause the battery to drain more quickly. Para garantir que uma ligação não se torna persistente com HTTP 1.1, o cliente pode incluir um cabeçalho Connection:Close com mensagens para substituir o comportamento predefinido.To ensure that a connection is not made persistent with HTTP 1.1, the client can include a Connection:Close header with messages to override the default behavior. Da mesma forma, se um servidor estiver a processar um número muito elevado de clientes, poderá incluir um cabeçalho Connection: Close nas mensagens de resposta que devem fechar a ligação e guardar os recursos do servidor.Similarly, if a server is handling a very large number of clients it can include a Connection:Close header in response messages which should close the connection and save server resources.

Nota

As ligações HTTP persistentes são uma funcionalidade puramente opcional para reduzir a sobrecarga de rede associada às repetidas tentativas de estabelecer um canal de comunicações.Persistent HTTP connections are a purely optional feature to reduce the network overhead associated with repeatedly establishing a communications channel. Nem a API Web nem a aplicação cliente devem depender da disponibilidade de uma ligação HTTP persistente.Neither the web API nor the client application should depend on a persistent HTTP connection being available. Não utilize ligações HTTP persistentes para implementar sistemas de notificação de estilo Comet; em vez disso, deve usar sockets (ou websockets, se disponível) na camada TCP.Do not use persistent HTTP connections to implement Comet-style notification systems; instead you should use sockets (or websockets if available) at the TCP layer. Por fim, tenha em atenção que os cabeçalhos Keep-Alive são de utilização limitada caso uma aplicação cliente comunique com um servidor através de um proxy; apenas a ligação com o cliente e o proxy vai ser persistente.Finally, note Keep-Alive headers are of limited use if a client application communicates with a server via a proxy; only the connection with the client and the proxy will be persistent.

Publicar e gerir uma API WebPublishing and managing a web API

Para disponibilizar uma API Web para aplicações cliente, esta tem de ser implementada num ambiente anfitrião.To make a web API available for client applications, the web API must be deployed to a host environment. Este ambiente é, geralmente, um servidor Web, embora possa ser outro tipo de processo anfitrião.This environment is typically a web server, although it may be some other type of host process. Deve considerar os seguintes pontos ao publicar uma API Web:You should consider the following points when publishing a web API:

  • Todos os pedidos têm de ser autenticados e autorizados e o nível adequado de controlo de acesso tem de ser imposto.All requests must be authenticated and authorized, and the appropriate level of access control must be enforced.
  • Uma API Web comercial pode ser sujeita a várias garantias de qualidade referentes aos tempos de resposta.A commercial web API might be subject to various quality guarantees concerning response times. Será importante assegurar que o ambiente anfitrião é dimensionável se a carga puder variar significativamente ao longo do tempo.It is important to ensure that host environment is scalable if the load can vary significantly over time.
  • Pode ser necessário medir os pedidos para fins de rentabilização.It may be necessary to meter requests for monetization purposes.
  • Pode ser necessário regular o fluxo de tráfego para a API Web e implementar a limitação para clientes específicos que tenham esgotado as respetivas quotas.It might be necessary to regulate the flow of traffic to the web API, and implement throttling for specific clients that have exhausted their quotas.
  • Os requisitos de regulamentação podem impor o registo e a auditoria de todos os pedidos e respostas.Regulatory requirements might mandate logging and auditing of all requests and responses.
  • Para garantir a disponibilidade, pode ser necessário monitorizar o estado de funcionamento do servidor a alojar a API Web e reiniciá-lo se necessário.To ensure availability, it may be necessary to monitor the health of the server hosting the web API and restart it if necessary.

É útil poder desacoplar estes problemas dos problemas técnicos respeitantes à implementação da API Web.It is useful to be able to decouple these issues from the technical issues concerning the implementation of the web API. Por este motivo, considere criar uma fachada, em execução como um processo separado e que encaminha pedidos para a API Web.For this reason, consider creating a façade, running as a separate process and that routes requests to the web API. A fachada pode fornecer as operações de gestão e encaminhar pedidos validados para a API Web.The façade can provide the management operations and forward validated requests to the web API. A utilização de uma fachada também pode disponibilizar muitas vantagens funcionais, incluindo:Using a façade can also bring many functional advantages, including:

  • Funcionar como um ponto de integração para várias APIs Web.Acting as an integration point for multiple web APIs.
  • Transformar mensagens e traduzir protocolos de comunicações para clientes criados com tecnologias variadas.Transforming messages and translating communications protocols for clients built by using varying technologies.
  • Colocar em cache pedidos e respostas para reduzir a carga no servidor a alojar a API Web.Caching requests and responses to reduce load on the server hosting the web API.

Testar uma API WebTesting a web API

Uma API Web deve ser testada tão cuidadosamente quanto qualquer outro elemento de software.A web API should be tested as thoroughly as any other piece of software. Deve considerar a criação de testes de unidade para validar a funcionalidade.You should consider creating unit tests to validate the functionality.

A natureza de uma API web apresenta seus próprios requisitos adicionais para confirmar que funciona corretamente.The nature of a web API brings its own additional requirements to verify that it operates correctly. Deve prestar especial atenção aos seguintes aspetos:You should pay particular attention to the following aspects:

  • Teste todas as rotas para verificar que invocam as operações corretas.Test all routes to verify that they invoke the correct operations. Esteja especialmente atento ao código de estado HTTP 405 (Método Não Permitido) que está a ser devolvido inesperadamente pois tal pode ser indicativo de um erro entre uma rota e os métodos HTTP (GET, POST, PUT, DELETE) que podem ser enviados para essa rota.Be especially aware of HTTP status code 405 (Method Not Allowed) being returned unexpectedly as this can indicate a mismatch between a route and the HTTP methods (GET, POST, PUT, DELETE) that can be dispatched to that route.

    O envio de pedidos HTTP para rotas que não os suportam, tal como submeter um pedido POST para um recurso específico (pedidos POST devem ser enviados apenas para coleções de recursos).Send HTTP requests to routes that do not support them, such as submitting a POST request to a specific resource (POST requests should only be sent to resource collections). Nestes casos, a única resposta válida deve ter o código de estado 405 (Não Permitido).In these cases, the only valid response should be status code 405 (Not Allowed).

  • Verifique se todas as rotas estão protegidas corretamente e estão sujeitas às verificações de autenticação e autorização adequadas.Verify that all routes are protected properly and are subject to the appropriate authentication and authorization checks.

    Nota

    Alguns aspetos de segurança, tal como a autenticação de utilizador, vão ser muito provavelmente da responsabilidade do ambiente anfitrião ao invés da API Web, mas continua a ser necessário incluir testes de segurança como parte do processo de implementação.Some aspects of security such as user authentication are most likely to be the responsibility of the host environment rather than the web API, but it is still necessary to include security tests as part of the deployment process.

  • Teste o processamento de exceções realizado por cada operação e verifique se é transmitida uma resposta HTTP adequada e significativa para a aplicação cliente.Test the exception handling performed by each operation and verify that an appropriate and meaningful HTTP response is passed back to the client application.

  • Verifique se as mensagens de pedido e resposta são bem estruturadas.Verify that request and response messages are well-formed. Por exemplo, se um pedido HTTP POST contiver os dados para um novo recurso no formato x-www-form-urlencoded, confirme se a operação correspondente analisa corretamente os dados, cria os recursos e devolve uma resposta que contém os detalhes do novo recurso, incluindo o cabeçalho Location correto.For example, if an HTTP POST request contains the data for a new resource in x-www-form-urlencoded format, confirm that the corresponding operation correctly parses the data, creates the resources, and returns a response containing the details of the new resource, including the correct Location header.

  • Verifique todas as ligações e URIs nas mensagens de resposta.Verify all links and URIs in response messages. Por exemplo, uma mensagem HTTP POST deve devolver o URI do recurso recentemente criado.For example, an HTTP POST message should return the URI of the newly created resource. Todas as ligações HATEOAS devem ser válidas.All HATEOAS links should be valid.

  • Confirme que cada operação devolve os códigos de estado corretos para diferentes combinações de entrada.Ensure that each operation returns the correct status codes for different combinations of input. Por exemplo:For example:

    • Se uma consulta for bem-sucedida, deverá devolver o código de estado 200 (OK)If a query is successful, it should return status code 200 (OK)
    • Se não for encontrado nenhum recurso, a operação deverá devolver o código de estado HTTP 404 (Não Encontrado).If a resource is not found, the operation should return HTTP status code 404 (Not Found).
    • Se o cliente enviar um pedido que elimina um recurso com sucesso, o código de estado deverá ser 204 (Sem Conteúdo).If the client sends a request that successfully deletes a resource, the status code should be 204 (No Content).
    • Se o cliente envia um pedido que cria um novo recurso, o código de estado deverá ser 201 (criado).If the client sends a request that creates a new resource, the status code should be 201 (Created).

Tenha atenção a códigos de estado de resposta inesperados no intervalo 5xx.Watch out for unexpected response status codes in the 5xx range. Normalmente, estas mensagens são reportadas pelo servidor anfitrião para indicar que não conseguiu realizar um pedido válido.These messages are usually reported by the host server to indicate that it was unable to fulfill a valid request.

  • Teste as diferentes combinações de cabeçalhos de pedidos que uma aplicação cliente pode especificar e confirme que a API Web devolve as informações esperadas nas mensagens de resposta.Test the different request header combinations that a client application can specify and ensure that the web API returns the expected information in response messages.

  • Teste as cadeias de consulta.Test query strings. Se uma operação puder utilizar parâmetros opcionais (tal como pedidos de paginação), teste as diferentes combinações e a ordem dos parâmetros.If an operation can take optional parameters (such as pagination requests), test the different combinations and order of parameters.

  • Verifique se as operações assíncronas foram concluídas com sucesso.Verify that asynchronous operations complete successfully. Se a API Web suportar a transmissão em fluxo para pedidos que devolvem grandes objetos binários (tal como vídeo ou áudio), verifique se os pedidos de cliente não são bloqueados enquanto os dados são transmitidos.If the web API supports streaming for requests that return large binary objects (such as video or audio), ensure that client requests are not blocked while the data is streamed. Se a API web implementar uma consulta para operações de modificação de dados de execução longa, certifique-se de que as operações comunicam o seu estado corretamente à medida que avançam.If the web API implements polling for long-running data modification operations, verify that the operations report their status correctly as they proceed.

Também deverá criar e executar testes de desempenho para verificar se a API Web funciona de forma satisfatória em situações de pressão.You should also create and run performance tests to check that the web API operates satisfactorily under duress. Pode criar um teste de carga e desempenho da Web com o Visual Studio Ultimate.You can build a web performance and load test project by using Visual Studio Ultimate. Para obter mais informações, veja Run performance tests on an application before a release (Executar testes de desempenho numa aplicação antes de um lançamento).For more information, see Run performance tests on an application before a release.

Utilizar a Gestão de API do AzureUsing Azure API Management

No Azure, considere a utilização gestão de API do Azure para publicar e gerir uma API web.On Azure, consider using Azure API Management to publish and manage a web API. Ao utilizar esta função, pode gerar um serviço que funciona como uma fachada para uma ou mais APIs Web.Using this facility, you can generate a service that acts as a façade for one or more web APIs. O serviço em si é um serviço web dimensionável que pode criar e configurar com o portal do Azure.The service is itself a scalable web service that you can create and configure by using the Azure portal. Pode utilizar este serviço para publicar e gerir uma API Web da seguinte forma:You can use this service to publish and manage a web API as follows:

  1. Implemente a API Web num site, no serviço cloud do Azure ou na máquina virtual do Azure.Deploy the web API to a website, Azure cloud service, or Azure virtual machine.

  2. Ligue o serviço de gestão de API à API Web.Connect the API management service to the web API. Os pedidos enviados para o URL da API de gestão estão mapeados para os URIs na API Web.Requests sent to the URL of the management API are mapped to URIs in the web API. O mesmo serviço de gestão de API pode encaminhar pedidos para mais do que uma API Web.The same API management service can route requests to more than one web API. Tal operação permite-lhe agregar várias APIs Web num único serviço de gestão.This enables you to aggregate multiple web APIs into a single management service. Da mesma forma, a mesma API Web poderá ser referenciada a partir de mais do que um serviço de gestão de API se precisar de restringir ou particionar as funcionalidades disponíveis para diferentes aplicações.Similarly, the same web API can be referenced from more than one API management service if you need to restrict or partition the functionality available to different applications.

    Nota

    Os URIs nas ligações HATEOAS gerados como parte da resposta dos pedidos HTTP GET devem referenciar o URL do serviço de gestão de API e não o servidor Web a alojar a API Web.The URIs in HATEOAS links generated as part of the response for HTTP GET requests should reference the URL of the API management service and not the web server hosting the web API.

  3. Para cada API Web, especifique as operações HTTP que expõem a API Web, juntamente com quaisquer parâmetros opcionais que uma operação pode receber como entrada.For each web API, specify the HTTP operations that the web API exposes together with any optional parameters that an operation can take as input. Também poderá configurar se o serviço de gestão de API deve colocar em cache a resposta recebida da API Web para otimizar pedidos repetidos para os mesmos dados.You can also configure whether the API management service should cache the response received from the web API to optimize repeated requests for the same data. Registe os detalhes das respostas HTTP que cada operação pode gerar.Record the details of the HTTP responses that each operation can generate. Estas informações são utilizadas para gerar documentação para programadores, pelo que é importante que sejam exatas e completas.This information is used to generate documentation for developers, so it is important that it is accurate and complete.

    Pode optar por definir operações manualmente com os assistentes fornecidos pelo portal do Azure ou pode importá-los a partir de um ficheiro que contém as definições no formato WADL ou Swagger.You can either define operations manually using the wizards provided by the Azure portal, or you can import them from a file containing the definitions in WADL or Swagger format.

  4. Configure as definições de segurança das comunicações entre o serviço de gestão de API e o servidor Web a alojar a API Web.Configure the security settings for communications between the API management service and the web server hosting the web API. Atualmente, o serviço de gestão de API suporta a autenticação Básica e a autenticação mútua com certificados, bem como a autorização de utilizador OAuth 2.0.The API management service currently supports Basic authentication and mutual authentication using certificates, and OAuth 2.0 user authorization.

  5. Crie um produto.Create a product. Um produto é a unidade de publicação. Deve adicionar APIs Web ligadas anteriormente ao serviço de gestão e ao produto.A product is the unit of publication; you add the web APIs that you previously connected to the management service to the product. Quando o produto é publicado, as APIs Web ficam disponíveis para os programadores.When the product is published, the web APIs become available to developers.

    Nota

    Antes de publicar um produto, também pode definir os grupos de utilizadores que podem aceder ao produto e adicionar utilizadores a estes grupos.Prior to publishing a product, you can also define user-groups that can access the product and add users to these groups. Este procedimento dá-lhe controlo sobre os programadores e as aplicações que podem utilizar a API Web.This gives you control over the developers and applications that can use the web API. Se uma API Web estiver sujeita a aprovação, antes de poder aceder à mesma, um programador terá de enviar um pedido ao administrador do produto.If a web API is subject to approval, prior to being able to access it a developer must send a request to the product administrator. O administrador pode conceder ou negar o acesso ao programador.The administrator can grant or deny access to the developer. Os programadores existentes poderão também ser bloqueados se as circunstâncias forem alteradas.Existing developers can also be blocked if circumstances change.

  6. Configure políticas para cada API Web.Configure policies for each web API. As políticas permitem reger os aspetos como a permissão de chamadas entre domínios, a autenticação de clientes, a conversão entre formatos de dados XML e JSON de forma transparente, a restrição das chamadas a partir de um determinado intervalo IP, a utilização de quotas e a limitação da taxa de chamadas.Policies govern aspects such as whether cross-domain calls should be allowed, how to authenticate clients, whether to convert between XML and JSON data formats transparently, whether to restrict calls from a given IP range, usage quotas, and whether to limit the call rate. As políticas podem ser aplicadas por todo o produto, a uma única API Web num produto ou a operações individuais numa API Web.Policies can be applied globally across the entire product, for a single web API in a product, or for individual operations in a web API.

Para obter mais informações, consulte a documentação de gestão de API.For more information, see the API Management documentation.

Dica

O Azure disponibiliza o Gestor de Tráfego do Azure que permite implementar a ativação pós-falha e o balanceamento de carga, assim como reduzir a latência em várias instâncias de um site alojado em diferentes localizações geográficas.Azure provides the Azure Traffic Manager which enables you to implement failover and load-balancing, and reduce latency across multiple instances of a web site hosted in different geographic locations. Pode utilizar o Gestor de Tráfego do Azure em conjunto com o Serviço de Gestão de API, o Serviço de Gestão de API pode encaminhar pedidos para instâncias de um site através do Gestor de Tráfego do Azure.You can use Azure Traffic Manager in conjunction with the API Management Service; the API Management Service can route requests to instances of a web site through Azure Traffic Manager. Para obter mais informações, consulte métodos de encaminhamento do Gestor de tráfego.For more information, see Traffic Manager routing methods.

Nesta estrutura, se estiver a utilizar nomes DNS personalizados para os sites, deverá configurar o registo CNAME adequado para que cada site aponte para o nome DNS do site do Gestor de Tráfego do Azure.In this structure, if you are using custom DNS names for your web sites, you should configure the appropriate CNAME record for each web site to point to the DNS name of the Azure Traffic Manager web site.

Suporte a programadores do lado do clienteSupporting client-side developers

Normalmente, os programadores que criam aplicações cliente necessitam de informações sobre como aceder à API Web e a documentação referente aos parâmetros, os tipos de dados, os tipos de retorno e os códigos de retorno que descrevem os diferentes pedidos e respostas entre o serviço Web e a aplicação cliente.Developers constructing client applications typically require information on how to access the web API, and documentation concerning the parameters, data types, return types, and return codes that describe the different requests and responses between the web service and the client application.

Documentar as operações REST de uma API WebDocument the REST operations for a web API

O Serviço de Gestão de API do Azure inclui um portal de programador, que descreve as operações REST expostas por uma API Web.The Azure API Management Service includes a developer portal that describes the REST operations exposed by a web API. Quando um produto é publicado, aparece neste portal.When a product has been published it appears on this portal. Os programadores podem inscrever-se neste portal para obter acesso; o administrador pode, em seguida, aprovar ou negar o pedido.Developers can use this portal to sign up for access; the administrator can then approve or deny the request. Se o programador for aprovado, receberá uma chave de subscrição que é utilizada para autenticar as chamadas a partir das aplicações cliente que desenvolve.If the developer is approved, they are assigned a subscription key that is used to authenticate calls from the client applications that they develop. Esta chave tem de ser fornecida com cada chamada à API Web. Caso contrário, será rejeitada.This key must be provided with each web API call otherwise it will be rejected.

Este portal também fornece:This portal also provides:

  • Documentação do produto, lista as operações que expõe, os parâmetros necessários e as respostas diferentes que podem ser devolvidas.Documentation for the product, listing the operations that it exposes, the parameters required, and the different responses that can be returned. Tenha em atenção que esta informação é gerada a partir dos detalhes fornecidos no passo 3 da lista na secção Publicar uma API Web com o Serviço de Gestão de API do Microsoft Azure.Note that this information is generated from the details provided in step 3 in the list in the Publishing a web API by using the Microsoft Azure API Management Service section.
  • Os fragmentos de código mostram como invocar operações de várias linguagens, incluindo JavaScript, C#, Java, Ruby, Python e PHP.Code snippets that show how to invoke operations from several languages, including JavaScript, C#, Java, Ruby, Python, and PHP.
  • Uma consola de programadores que permite ao programador enviar um pedido HTTP para cada operação de teste no produto e ver os resultados.A developers' console that enables a developer to send an HTTP request to test each operation in the product and view the results.
  • Uma página onde o programador pode reportar quaisquer problemas ou questões encontrados.A page where the developer can report any issues or problems found.

O portal do Azure permite-lhe personalizar o portal do programador para alterar o estilo e o esquema para corresponder à imagem corporativa da sua organização.The Azure portal enables you to customize the developer portal to change the styling and layout to match the branding of your organization.

Implementar um SDK do clienteImplement a client SDK

A criação de uma aplicação cliente que invoca pedidos REST para aceder a uma API Web precisa de uma quantidade significativa de código escrito para construir cada pedido e formatá-lo adequadamente, enviar o pedido para o servidor a alojar o serviço Web e analisar a resposta para saber se o pedido foi bem-sucedido ou falhou e extrair todos os dados devolvidos.Building a client application that invokes REST requests to access a web API requires writing a significant amount of code to construct each request and format it appropriately, send the request to the server hosting the web service, and parse the response to work out whether the request succeeded or failed and extract any data returned. Para proteger a aplicação cliente destas preocupações, pode fornecer um SDK que encapsula num wrapper a interface REST e deduz estes detalhes de baixo nível dentro de um conjunto de métodos mais funcional.To insulate the client application from these concerns, you can provide an SDK that wraps the REST interface and abstracts these low-level details inside a more functional set of methods. Uma aplicação cliente utiliza estes métodos que convertem de forma transparente as chamadas em pedidos REST e, em seguida, convertem as respostas de volta para os valores que o método devolveu.A client application uses these methods, which transparently convert calls into REST requests and then convert the responses back into method return values. Esta é uma técnica comum implementada por vários serviços, incluindo o SDK do Azure.This is a common technique that is implemented by many services, including the Azure SDK.

A criação de um SDK do lado do cliente é um projeto considerável, uma vez que tem de ser implementado de forma consistente e testado atentamente.Creating a client-side SDK is a considerable undertaking as it has to be implemented consistently and tested carefully. No entanto, muito deste processo pode ser realizado mecanicamente e muitos fornecedores fornecem ferramentas que podem automatizar muitas destas tarefas.However, much of this process can be made mechanical, and many vendors supply tools that can automate many of these tasks.

Monitorizar uma API WebMonitoring a web API

Dependendo de como publicou e implementou a API Web, pode monitorizar a API Web diretamente ou pode recolher informações sobre a utilização e o estado de funcionamento ao analisar o tráfego que passa através do serviço de Gestão de API.Depending on how you have published and deployed your web API you can monitor the web API directly, or you can gather usage and health information by analyzing the traffic that passes through the API Management service.

Monitorizar uma API Web diretamenteMonitoring a web API directly

Se tiver implementado a API Web com o modelo da API Web da ASP.NET (como um projeto API Web ou como uma função da Web num serviço cloud do Azure) e o Visual Studio 2013, poderá recolher dados de utilização, desempenho e disponibilidade com o Application Insights da ASP.NET.If you have implemented your web API by using the ASP.NET Web API template (either as a Web API project or as a Web role in an Azure cloud service) and Visual Studio 2013, you can gather availability, performance, and usage data by using ASP.NET Application Insights. O Application Insights é um pacote que controla e regista de forma transparente informações sobre os pedidos e as respostas quando a API Web é implementada na cloud. Depois de o pacote estar instalado e configurado, não precisa de corrigir qualquer código na API Web para utilizá-lo.Application Insights is a package that transparently tracks and records information about requests and responses when the web API is deployed to the cloud; once the package is installed and configured, you don't need to amend any code in your web API to use it. Quando implementa a API Web num site do Azure, todo o tráfego é examinado e as estatísticas seguintes são recolhidas:When you deploy the web API to an Azure web site, all traffic is examined and the following statistics are gathered:

  • Tempo de resposta do servidor.Server response time.
  • Número de pedidos do servidor e os detalhes de cada pedido.Number of server requests and the details of each request.
  • Os pedidos mais lentos em termos de tempo de resposta médio.The top slowest requests in terms of average response time.
  • Os detalhes de quaisquer pedidos falhados.The details of any failed requests.
  • O número de sessões iniciadas por browsers e agentes de utilizador diferentes.The number of sessions initiated by different browsers and user agents.
  • As páginas mais frequentemente visualizadas (principalmente útil para aplicações Web ao invés de APIs Web).The most frequently viewed pages (primarily useful for web applications rather than web APIs).
  • As diferentes funções de utilizador a aceder à API Web.The different user roles accessing the web API.

Pode ver estes dados em tempo real no portal do Azure.You can view this data in real time in the Azure portal. Também pode criar testes web que monitorizam o estado de funcionamento da web API.You can also create web tests that monitor the health of the web API. Um teste web envia um pedido periódico para um URI especificado na web API e captura a resposta.A web test sends a periodic request to a specified URI in the web API and captures the response. Pode especificar a definição de uma resposta bem-sucedida (tal como o código de estado HTTP 200) e, se o pedido não devolver esta resposta, poderá definir o envio de um alerta para um administrador.You can specify the definition of a successful response (such as HTTP status code 200), and if the request does not return this response you can arrange for an alert to be sent to an administrator. Se necessário, o administrador poderá reiniciar o servidor que aloja a API Web se tiver falhado.If necessary, the administrator can restart the server hosting the web API if it has failed.

Para obter mais informações, veja Application Insights - Introdução à ASP.NET.For more information, see Application Insights - Get started with ASP.NET.

Monitorizar uma API Web através do Serviço de Gestão de APIMonitoring a web API through the API Management Service

Se tiver publicado a API web com o serviço de gestão de API, a página de gestão de API no portal do Azure contém um dashboard que permite-lhe ver o desempenho geral do serviço.If you have published your web API by using the API Management service, the API Management page on the Azure portal contains a dashboard that enables you to view the overall performance of the service. A página de análise permite-lhe desagregar os detalhes da forma como o produto está a ser utilizado.The Analytics page enables you to drill down into the details of how the product is being used. Esta página contém os seguintes separadores:This page contains the following tabs:

  • Utilização.Usage. Este separador fornece informações sobre o número de chamadas da API realizadas e a largura de banda utilizada para processar essas chamadas ao longo do tempo.This tab provides information about the number of API calls made and the bandwidth used to handle these calls over time. Pode filtrar os detalhes de utilização por produto, API e operação.You can filter usage details by product, API, and operation.
  • Estado de Funcionamento.Health. Este separador permite-lhe ver o resultado dos pedidos da API (os códigos de estado HTTP devolvidos), a eficácia da política de colocação em cache, o tempo de resposta da API e o tempo de resposta do serviço.This tab enables you to view the outcome of API requests (the HTTP status codes returned), the effectiveness of the caching policy, the API response time, and the service response time. Novamente, pode filtrar os detalhes do cabeçalho por produto, API e operação.Again, you can filter health data by product, API, and operation.
  • Atividade.Activity. Este separador fornece um resumo de texto dos números de chamadas bem-sucedidas, chamadas falhadas, chamadas bloqueadas, tempo médio de resposta e tempos de resposta para cada produto, API Web e operação.This tab provides a text summary of the numbers of successful calls, failed calls, blocked calls, average response time, and response times for each product, web API, and operation. Esta página também apresenta o número de chamadas realizadas por cada programador.This page also lists the number of calls made by each developer.
  • Síntese.At a glance. Este separador mostra um resumo dos dados de desempenho, incluindo os programadores responsáveis por verificar a maioria das chamadas à API e os produtos, as APIs Web e as operações que receberam estas chamadas.This tab displays a summary of the performance data, including the developers responsible for making the most API calls, and the products, web APIs, and operations that received these calls.

Pode utilizar estas informações para determinar se uma determinada API Web ou operação está a provocar um estrangulamento e, se necessário, dimensionar o ambiente anfitrião e adicionar mais servidores.You can use this information to determine whether a particular web API or operation is causing a bottleneck, and if necessary scale the host environment and add more servers. Também pode apurar se uma ou mais aplicações estão a utilizar um volume desproporcional de recursos e a aplicar as políticas adequadas para definir quotas e limitar as taxas de chamadas.You can also ascertain whether one or more applications are using a disproportionate volume of resources and apply the appropriate policies to set quotas and limit call rates.

Nota

Pode alterar os detalhes de um produto publicado. As alterações são aplicadas de imediato.You can change the details for a published product, and the changes are applied immediately. Por exemplo, pode adicionar ou remover uma operação de uma API Web sem ter de voltar a publicar o produto que contém a API Web.For example, you can add or remove an operation from a web API without requiring that you republish the product that contains the web API.

Mais informaçõesMore information