

A versão 4 (V4) do AWS SDK para .NET foi lançada\$1

Para obter informações sobre mudanças significativas e migrar seus aplicativos, consulte o [tópico de migração](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html).

 [https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html)

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Ligando para AWS serviços do AWS SDK para .NET
<a name="working-with-aws-services"></a>

As seções a seguir contêm exemplos, tutoriais, tarefas e guias que mostram como usar o AWS SDK para .NET para trabalhar com AWS serviços. Esses exemplos e tutoriais dependem de uma API que o AWS SDK para .NET fornece. Para ver quais classes e métodos estão disponíveis na API, consulte a [Referência de API do AWS SDK para .NET](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/).

Se você é novo no AWS SDK para .NET, talvez queira conferir o [Criando um aplicativo simples](quick-start.md) tópico primeiro. Ele fornece uma introdução ao SDK.

Você pode encontrar mais exemplos de código no Repositório de [exemplos de AWS código e no repositório](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv4) [awslabs](https://github.com/awslabs/aws-sdk-net-samples) em. GitHub

Antes de começar, verifique se você [configurou seu ambiente](net-dg-config.md) e [configurou seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

**Topics**
+ [Exemplos de código guiado](tutorials-examples.md)
+ [AWS Lambda](aws-lambda.md)
+ [Bibliotecas e estruturas de alto nível](high-level-libraries.md)
+ [Outros serviços e configuração](other-apis-intro.md)

# Exemplos de código guiado para o AWS SDK para .NET
<a name="tutorials-examples"></a>

As seções a seguir contêm exemplos de código e fornecem orientação para os exemplos. Eles podem ajudá-lo a aprender como usar o AWS SDK para .NET para trabalhar com AWS serviços. Para obter exemplos de código adicionais, consulte [Exemplos de código](csharp_code_examples.md).

**nota**  
Exemplos de código específicos para a V3 do também AWS SDK para .NET estão disponíveis. Para encontrá-los, consulte [Exemplos de código com orientação](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/tutorials-examples.html) e [exemplos de código](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/csharp_code_examples.html) no Guia do desenvolvedor AWS SDK para .NET (V3). No entanto, lembre-se de que, se você usar os exemplos de código específicos da V3 com a V4 do SDK (a versão mais recente), talvez seja necessário fazer ajustes de acordo com as informações contidas. [Migrando para a versão 4](net-dg-v4.md)

Se você é novo no AWS SDK para .NET, talvez queira conferir o [Criando um aplicativo simples](quick-start.md) tópico primeiro. Ele fornece uma introdução ao SDK.

Antes de começar, verifique se você [configurou seu ambiente](net-dg-config.md) e [configurou seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

**Topics**
+ [CloudFormation](cloudformation-apis-intro.md)
+ [Amazon Cognito](cognito-apis-intro.md)
+ [DynamoDB](dynamodb-intro.md)
+ [Amazon EC2](ec2-apis-intro.md)
+ [IAM](iam-apis-intro.md)
+ [Amazon S3](s3-apis-intro.md)
+ [Amazon SNS](sns-apis-intro.md)
+ [Amazon SQS](sqs-apis-intro.md)

# Acessando CloudFormation com o AWS SDK para .NET
<a name="cloudformation-apis-intro"></a>

Os AWS SDK para .NET suportes [AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/), que criam e provisionam implantações de AWS infraestrutura de forma previsível e repetida.

## APIs
<a name="w2aac19c15c15b5"></a>

Eles AWS SDK para .NET fornecem APIs para CloudFormation clientes. Eles APIs permitem que você trabalhe com CloudFormation recursos como modelos e pilhas. Esta seção contém um pequeno número de exemplos que mostram os padrões que você pode seguir ao trabalhar com eles APIs. Para ver o conjunto completo de APIs, consulte a [Referência da AWS SDK para .NET API](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/) (e vá até “Amazon. CloudFormation“).

Eles AWS CloudFormation APIs são fornecidos pelo [AWSSDK. CloudFormation](https://www.nuget.org/packages/AWSSDK.CloudFormation/)pacote.

## Pré-requisitos
<a name="w2aac19c15c15b7"></a>

Antes de começar, verifique se você [configurou seu ambiente](net-dg-config.md) e [configurou seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

## Tópicos
<a name="w2aac19c15c15b9"></a>

**Topics**
+ [APIs](#w2aac19c15c15b5)
+ [Pré-requisitos](#w2aac19c15c15b7)
+ [Tópicos](#w2aac19c15c15b9)
+ [Listando AWS recursos](cfn-list-resources.md)

# Listando AWS recursos usando AWS CloudFormation
<a name="cfn-list-resources"></a>

Este exemplo mostra como usar o AWS SDK para .NET para listar os recursos em CloudFormation pilhas. O exemplo usa a API de baixo nível. O aplicativo não aceita argumentos, apenas reúne informações de todas as pilhas acessíveis às credenciais do usuário e, em seguida, exibe informações sobre essas pilhas.

## Referências do SDK
<a name="w2aac19c15c15c13b5b1"></a>

NuGet pacotes:
+ [AWSSDK.CloudFormation](https://www.nuget.org/packages/AWSSDK.CloudFormation/)

Elementos de programação:
+ [Namespace Amazon. CloudFormation](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/NCloudFormation.html)

  Classe [AmazonCloudFormationClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TCloudFormationClient.html)
+ [Namespace Amazon. CloudFormation.Modelo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/NCloudFormationModel.html)

  Classe [ICloudFormationPaginatorFactory. DescribeStacks](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/MICloudFormationPaginatorFactoryDescribeStacksDescribeStacksRequest.html)

  Classe [DescribeStackResourcesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TDescribeStackResourcesRequest.html)

  Classe [DescribeStackResourcesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TDescribeStackResourcesResponse.html)

  Classe [Stack](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TStack.html)

  Classe [StackResource](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TStackResource.html)

  Classe [Tag](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CloudFormation/TTag.html)

```
using Amazon.CloudFormation;
using Amazon.CloudFormation.Model;
using Amazon.Runtime;

namespace CloudFormationActions;

public static class HelloCloudFormation
{
    public static IAmazonCloudFormation _amazonCloudFormation;

    static async Task Main(string[] args)
    {
        // Create the CloudFormation client
        _amazonCloudFormation = new AmazonCloudFormationClient();
        Console.WriteLine($"\nIn Region: {_amazonCloudFormation.Config.RegionEndpoint}");

        // List the resources for each stack
        await ListResources();
    }

    /// <summary>
    /// Method to list stack resources and other information.
    /// </summary>
    /// <returns>True if successful.</returns>
    public static async Task<bool> ListResources()
    {
        try
        {
            Console.WriteLine("Getting CloudFormation stack information...");

            // Get all stacks using the stack paginator.
            var paginatorForDescribeStacks =
                _amazonCloudFormation.Paginators.DescribeStacks(
                    new DescribeStacksRequest());
            await foreach (Stack stack in paginatorForDescribeStacks.Stacks)
            {
                // Basic information for each stack
                Console.WriteLine("\n------------------------------------------------");
                Console.WriteLine($"\nStack: {stack.StackName}");
                Console.WriteLine($"  Status: {stack.StackStatus.Value}");
                Console.WriteLine($"  Created: {stack.CreationTime}");

                // The tags of each stack (etc.)
                if (stack.Tags.Count > 0)
                {
                    Console.WriteLine("  Tags:");
                    foreach (Tag tag in stack.Tags)
                        Console.WriteLine($"    {tag.Key}, {tag.Value}");
                }

                // The resources of each stack
                DescribeStackResourcesResponse responseDescribeResources =
                    await _amazonCloudFormation.DescribeStackResourcesAsync(
                        new DescribeStackResourcesRequest
                        {
                            StackName = stack.StackName
                        });
                if (responseDescribeResources.StackResources.Count > 0)
                {
                    Console.WriteLine("  Resources:");
                    foreach (StackResource resource in responseDescribeResources
                                 .StackResources)
                        Console.WriteLine(
                            $"    {resource.LogicalResourceId}: {resource.ResourceStatus}");
                }
            }

            Console.WriteLine("\n------------------------------------------------");
            return true;
        }
        catch (AmazonCloudFormationException ex)
        {
            Console.WriteLine("Unable to get stack information:\n" + ex.Message);
            return false;
        }
        catch (AmazonServiceException ex)
        {
            if (ex.Message.Contains("Unable to get IAM security credentials"))
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("If you are usnig SSO, be sure to install" +
                                  " the AWSSDK.SSO and AWSSDK.SSOOIDC packages.");
            }
            else
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }

            return false;
        }
        catch (ArgumentNullException ex)
        {
            if (ex.Message.Contains("Options property cannot be empty: ClientName"))
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("If you are using SSO, have you logged in?");
            }
            else
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }

            return false;
        }
    }
```

# Autenticar usuários com o Amazon Cognito
<a name="cognito-apis-intro"></a>

**nota**  
As informações neste tópico são específicas para projetos baseados no.NET Framework e na AWS SDK para .NET versão 3.3 e anteriores.

Usando o Amazon Cognito Identity, você pode criar identidades exclusivas para seus usuários e autenticá-los para acesso seguro aos seus AWS recursos, como o Amazon S3 ou o Amazon DynamoDB. O Amazon Cognito Identity é compatível com provedores de identidade públicos, como o Amazon, o Facebook e o Google, ou qualquer provedor compatível com o OpenID Connect, bem como identidades não autenticadas. O Amazon Cognito é compatível também com as [identidades autenticadas pelos desenvolvedores](https://aws.amazon.com/blogs/mobile/amazon-cognito-announcing-developer-authenticated-identities/), que permitem registrar e autenticar usuários por meio do processo de autenticação de back-end, sem deixar de usar a Sincronização do Amazon Cognito para sincronizar os dados do usuário e acessar os recursos AWS .

Para obter mais informações sobre o [Amazon Cognito](https://aws.amazon.com/cognito/), consulte o [Amazon Cognito Developer Guide](https://docs.aws.amazon.com/cognito/latest/developerguide/).

Os exemplos de código a seguir mostram como usar facilmente o Amazon Cognito Identity. O exemplo [Provedor de credenciais](cognito-creds-provider.md) mostra como criar e autenticar identidades de usuários. O [CognitoAuthentication biblioteca de extensão](cognito-authentication-extension.md) exemplo mostra como usar a biblioteca de CognitoAuthentication extensões para autenticar grupos de usuários do Amazon Cognito.

**Topics**
+ [Provedor de credenciais](cognito-creds-provider.md)
+ [CognitoAuthentication biblioteca de extensão](cognito-authentication-extension.md)

# Provedor de credenciais do Amazon Cognito
<a name="cognito-creds-provider"></a>

**nota**  
As informações neste tópico são específicas para projetos baseados no.NET Framework e na AWS SDK para .NET versão 3.3 e anteriores.

 `Amazon.CognitoIdentity.CognitoAWSCredentials`, encontrado no [AWSSDK. CognitoIdentity](https://www.nuget.org/packages/AWSSDK.CognitoIdentity/) NuGetpackage, é um objeto de credenciais que usa o Amazon Cognito e AWS Security Token Service o AWS STS() para recuperar credenciais para fazer chamadas. AWS 

A primeira etapa da configuração do `CognitoAWSCredentials` é criar um "grupo de identidades". Um grupo de identidades é um armazenamento de informações de identidades de usuários específico para sua conta. As informações podem ser recuperadas entre plataformas, dispositivos e sistemas operacionais de clientes, para que, se um usuário começar a usar o aplicativo em um telefone e depois mudar para um tablet, as informações mantidas do aplicativo ainda estejam disponíveis para esse usuário. É possível criar um novo banco de identidades no console do Amazon Cognito. Se você está usando o console, ele também oferece outras informações de que você precisa:
+ Seu número de conta – um número de 12 dígitos, como 123456789012, que é exclusivo para sua conta.
+ O ARN da função não autenticada – uma função que os usuários não autenticados assumirão. Por exemplo, essa função pode fornecer permissões somente leitura aos seus dados.
+ O ARN da função autenticada – uma função que os usuários autenticados assumirão. Essa função pode fornecer permissões mais amplas aos seus dados.

## Configurar o Cognito AWSCredentials
<a name="set-up-cognitoawscredentials"></a>

O código de exemplo a seguir mostra como configurar o `CognitoAWSCredentials`, que pode ser usado para fazer uma chamada para o Amazon S3 como usuário não autenticado. Isso permite que você faça chamadas com apenas uma quantidade mínima de dados necessária para autenticar o usuário. As permissões de usuários são controladas pela função para que seja possível configurar o acesso conforme necessário.

```
CognitoAWSCredentials credentials = new CognitoAWSCredentials(
    accountId,        // Account number
    identityPoolId,   // Identity pool ID
    unAuthRoleArn,    // Role for unauthenticated users
    null,             // Role for authenticated users, not set
    region);
using (var s3Client = new AmazonS3Client(credentials))
{
    s3Client.ListBuckets();
}
```

## Use AWS como um usuário não autenticado
<a name="use-aws-as-an-unauthenticated-user"></a>

O exemplo de código a seguir mostra como você pode começar a usar AWS como usuário não autenticado, depois se autenticar pelo Facebook e atualizar as credenciais para usar as credenciais do Facebook. Usando essa abordagem, você pode conceder capacidades diferentes a usuários autenticados por meio da função autenticada. Por exemplo, você pode ter um aplicativo de telefone que permite que os usuários visualizem conteúdo anonimamente, mas lhes permite publicar se eles estão conectados com um ou mais dos provedores configurados.

```
CognitoAWSCredentials credentials = new CognitoAWSCredentials(
    accountId, identityPoolId,
    unAuthRoleArn,    // Role for unauthenticated users
    authRoleArn,      // Role for authenticated users
    region);
using (var s3Client = new AmazonS3Client(credentials))
{
    // Initial use will be unauthenticated
    s3Client.ListBuckets();

    // Authenticate user through Facebook
    string facebookToken = GetFacebookAuthToken();

    // Add Facebook login to credentials. This clears the current AWS credentials
    // and retrieves new AWS credentials using the authenticated role.
    credentials.AddLogin("graph.facebook.com", facebookAccessToken);

    // This call is performed with the authenticated role and credentials
    s3Client.ListBuckets();
}
```

O objeto `CognitoAWSCredentials` oferecerá ainda mais funcionalidades se você usá-lo com o `AmazonCognitoSyncClient` que faz parte do AWS SDK para .NET. Se você estiver usando `AmazonCognitoSyncClient` e `CognitoAWSCredentials`, não é necessário especificar as propriedades `IdentityPoolId` e `IdentityId` ao fazer chamadas com o `AmazonCognitoSyncClient`. Essas propriedades são preenchidas automaticamente em `CognitoAWSCredentials`. O exemplo de código a seguir ilustra isso, bem como um evento que notifica você sempre que o `IdentityId` para `CognitoAWSCredentials` é alterado. O `IdentityId` pode ser alterado em alguns casos, como na alteração de um usuário não autenticado para um autenticado.

```
CognitoAWSCredentials credentials = GetCognitoAWSCredentials();

// Log identity changes
credentials.IdentityChangedEvent += (sender, args) =>
{
    Console.WriteLine("Identity changed: [{0}] => [{1}]", args.OldIdentityId, args.NewIdentityId);
};

using (var syncClient = new AmazonCognitoSyncClient(credentials))
{
    var result = syncClient.ListRecords(new ListRecordsRequest
    {
        DatasetName = datasetName
        // No need to specify these properties
        //IdentityId = "...",
        //IdentityPoolId = "..."        
    });
}
```

# Exemplos de bibliotecas CognitoAuthentication de extensões da Amazon
<a name="cognito-authentication-extension"></a>

**nota**  
As informações neste tópico são específicas para projetos baseados no.NET Framework e na AWS SDK para .NET versão 3.3 e anteriores.

A biblioteca CognitoAuthentication de extensões, encontrada em [Amazon.Extensions. CognitoAuthentication](https://www.nuget.org/packages/Amazon.Extensions.CognitoAuthentication/) NuGet pacote, simplifica o processo de autenticação dos grupos de usuários do Amazon Cognito para desenvolvedores do.NET Core e Xamarin. A biblioteca foi criada com base na API do provedor de identidade do Amazon Cognito para criar e enviar chamadas de API de autenticação de usuários.

## Usando a biblioteca CognitoAuthentication de extensões
<a name="using-the-cognitoauthentication-extension-library"></a>

O Amazon Cognito tem alguns valores `AuthFlow` e `ChallengeName` integrados para que um fluxo de autenticação padrão valide o nome de usuário e a senha pelo protocolo SRP (Secure Remote Password). Para obter mais informações sobre o fluxo de autenticação, consulte [Amazon Cognito User Pool Authentication Flow (Fluxo de autenticação de grupos de usuários do Amazon Cognito)](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html).

Os exemplos a seguir exigem estas instruções `using`:

```
// Required for all examples
using System;
using Amazon;
using Amazon.CognitoIdentity;
using Amazon.CognitoIdentityProvider;
using Amazon.Extensions.CognitoAuthentication;
using Amazon.Runtime;
// Required for the GetS3BucketsAsync example
using Amazon.S3;
using Amazon.S3.Model;
```

### Usando a autenticação básica
<a name="use-basic-authentication"></a>

Crie um [AmazonCognitoIdentityProviderClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/CognitoIdentityProvider/TCognitoIdentityProviderClient.html)usando [Anonymous AWSCredentials](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Runtime/TAnonymousAWSCredentials.html), que não exige solicitações assinadas. Você não precisa fornecer uma região. O código subjacente chamará `FallbackRegionFactory.GetRegionEndpoint()` se uma região não for fornecida. Crie objetos `CognitoUserPool` e `CognitoUser`. Chame o método `StartWithSrpAuthAsync` com um `InitiateSrpAuthRequest` que contenha a senha do usuário.

```
public static async void GetCredsAsync()
{
    AmazonCognitoIdentityProviderClient provider =
        new AmazonCognitoIdentityProviderClient(new Amazon.Runtime.AnonymousAWSCredentials());
    CognitoUserPool userPool = new CognitoUserPool("poolID", "clientID", provider);
    CognitoUser user = new CognitoUser("username", "clientID", userPool, provider);
    InitiateSrpAuthRequest authRequest = new InitiateSrpAuthRequest()
    {
        Password = "userPassword"
    };

    AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(authRequest).ConfigureAwait(false);
    accessToken = authResponse.AuthenticationResult.AccessToken;

}
```

### Autenticar com desafios
<a name="authenticate-with-challenges"></a>

Continuar o fluxo de autenticação com desafios, como com NewPasswordRequired e Multi-Factor Authentication (MFA), também é mais simples. Os únicos requisitos são os CognitoAuthentication objetos, a senha do usuário para o SRP e as informações necessárias para o próximo desafio, que são adquiridas após a solicitação do usuário para inseri-la. O código a seguir mostra uma forma de verificar o tipo de desafio e obter as respostas apropriadas para MFA e NewPasswordRequired desafios durante o fluxo de autenticação.

Faça uma solicitação de autenticação básica como antes, e `await` um `AuthFlowResponse`. Quando a resposta for recebida, percorra o objeto retornado `AuthenticationResult`. Se o tipo de `ChallengeName` for `NEW_PASSWORD_REQUIRED`, chame o método `RespondToNewPasswordRequiredAsync`.

```
public static async void GetCredsChallengesAsync()
{
    AmazonCognitoIdentityProviderClient provider = 
        new AmazonCognitoIdentityProviderClient(new Amazon.Runtime.AnonymousAWSCredentials());
    CognitoUserPool userPool = new CognitoUserPool("poolID", "clientID", provider);
    CognitoUser user = new CognitoUser("username", "clientID", userPool, provider);
    InitiateSrpAuthRequest authRequest = new InitiateSrpAuthRequest(){
        Password = "userPassword"
    };

    AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(authRequest).ConfigureAwait(false);

    while (authResponse.AuthenticationResult == null)
    {
        if (authResponse.ChallengeName == ChallengeNameType.NEW_PASSWORD_REQUIRED)
        {
            Console.WriteLine("Enter your desired new password:");
            string newPassword = Console.ReadLine();

            authResponse = await user.RespondToNewPasswordRequiredAsync(new RespondToNewPasswordRequiredRequest()
            {
                SessionID = authResponse.SessionID,
                NewPassword = newPassword
            });
            accessToken = authResponse.AuthenticationResult.AccessToken;
        }
        else if (authResponse.ChallengeName == ChallengeNameType.SMS_MFA)
        {
            Console.WriteLine("Enter the MFA Code sent to your device:");
            string mfaCode = Console.ReadLine();

            AuthFlowResponse mfaResponse = await user.RespondToSmsMfaAuthAsync(new RespondToSmsMfaRequest()
            {
                SessionID = authResponse.SessionID,
                MfaCode = mfaCode

            }).ConfigureAwait(false);
            accessToken = authResponse.AuthenticationResult.AccessToken;
        }
        else
        {
            Console.WriteLine("Unrecognized authentication challenge.");
            accessToken = "";
            break;
        }
    }

    if (authResponse.AuthenticationResult != null)
    {
        Console.WriteLine("User successfully authenticated.");
    }
    else
    {
        Console.WriteLine("Error in authentication process.");
    }
 
}
```

### Use AWS recursos após a autenticação
<a name="use-aws-resources-after-authentication"></a>

Depois que um usuário é autenticado usando a CognitoAuthentication biblioteca, a próxima etapa é permitir que o usuário acesse os AWS recursos apropriados. Para fazer isso, crie um banco de identidades por meio do console de identidades federadas do Amazon Cognito. Ao especificar o grupo de usuários do Amazon Cognito que você criou como provedor, usando seu poolID e clientID, você pode permitir que grupo de usuários do Amazon Cognito acesse os recursos AWS conectados à sua conta. Você também pode especificar diferentes funções para permitir que usuários autenticados e não autenticados acessem recursos diferentes. Você pode alterar essas regras no console do IAM, em que você pode adicionar ou remover permissões no campo **Action (Ação)** da política anexada da função. Em seguida, usando o grupo de identidades, o grupo de usuários e as informações de usuário do Amazon Cognito apropriados, você pode fazer chamadas para diferentes AWS recursos. O exemplo a seguir mostra um usuário autenticado com SRP acessando os diferentes buckets do Amazon S3 permitidos pela função do grupo de identidades associado

```
public async void GetS3BucketsAsync()
{
    var provider = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials());
    CognitoUserPool userPool = new CognitoUserPool("poolID", "clientID", provider);
    CognitoUser user = new CognitoUser("username", "clientID", userPool, provider);

    string password = "userPassword";

    AuthFlowResponse context = await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
    {
        Password = password
    }).ConfigureAwait(false);

    CognitoAWSCredentials credentials =
        user.GetCognitoAWSCredentials("identityPoolID", RegionEndpoint.< YourIdentityPoolRegion >);

    using (var client = new AmazonS3Client(credentials))
    {
        ListBucketsResponse response =
            await client.ListBucketsAsync(new ListBucketsRequest()).ConfigureAwait(false);

        foreach (S3Bucket bucket in response.Buckets)
        {
            Console.WriteLine(bucket.BucketName);
        }
    }
}
```

## Opções adicionais de autenticação
<a name="more-authentication-options"></a>

Além do SRP e do MFA NewPasswordRequired, CognitoAuthentication a biblioteca de extensões oferece um fluxo de autenticação mais fácil para:
+ Personalizado – iniciar com uma chamada para `StartWithCustomAuthAsync(InitiateCustomAuthRequest customRequest)` 
+ RefreshToken - Inicie com uma chamada para `StartWithRefreshTokenAuthAsync(InitiateRefreshTokenAuthRequest refreshTokenRequest)` 
+ RefreshTokenSRP - Inicie com uma chamada para `StartWithRefreshTokenAuthAsync(InitiateRefreshTokenAuthRequest refreshTokenRequest)` 
+ AdminNoSRP - Inicie com uma chamada para `StartWithAdminNoSrpAuthAsync(InitiateAdminNoSrpAuthRequest adminAuthRequest)` 

Chame o método adequado de acordo com o fluxo que você deseja. Em seguida, continue abordando o usuário com desafios à medida que são apresentados nos objetos `AuthFlowResponse` de cada chamada de método. Além disso, chame o método de resposta adequado, como `RespondToSmsMfaAuthAsync` para desafios de MFA e `RespondToCustomAuthAsync` para desafios personalizados.

# Como usar os bancos de dados NoSQL Amazon DynamoDB
<a name="dynamodb-intro"></a>

**nota**  
Os modelos de programação nesses tópicos estão presentes tanto no .NET Framework quanto no .NET (Core), mas as convenções de chamada diferem, sejam síncronas ou assíncronas.

O AWS SDK para .NET suporta o Amazon DynamoDB, que é um serviço rápido de banco de dados NoSQL oferecido pela. AWS O SDK fornece três módulos de programação para comunicar-se com o DynamoDB: o modelo de *baixo nível*, o modelo de *documento* e o modelo de *persistência de objetos*.

As informações a seguir apresentam esses modelos e seus APIs, fornecem exemplos de como e quando usá-los e fornecem links para recursos adicionais de programação do DynamoDB no. AWS SDK para .NET

## Modelo de baixo nível
<a name="dynamodb-intro-apis-low-level"></a>

O modelo de programação de baixo nível envolve chamadas diretas para o serviço do DynamoDB. Você acessa esse modelo por meio do [namespace DBv2 Amazon.Dynamo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/NDynamoDBv2.html).

Dos três modelos, o de baixo nível é o que exige que você escreva mais código. Por exemplo, você deve converter tipos de dados .NET para seus equivalentes no DynamoDB. Contudo, esse modelo fornece acesso à maioria dos recursos.

Os exemplos a seguir mostram como usar o modelo de baixo nível para criar ou modificar uma tabela e inserir itens em uma tabela no DynamoDB.

### Criar uma tabela
<a name="dynamodb-intro-apis-low-level-create-table"></a>

No exemplo a seguir, você cria uma tabela usando o método `CreateTable` da classe `AmazonDynamoDBClient`. O método `CreateTable` usa uma instância da classe `CreateTableRequest` que contém características como nomes de atributo do item obrigatório, definição de chave primária e a capacidade de transferência. O método `CreateTable` retorna uma instância da classe `CreateTableResponse`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();

Console.WriteLine("Getting list of tables");
List<string> currentTables = client.ListTables().TableNames;
Console.WriteLine("Number of tables: " + currentTables.Count);
if (!currentTables.Contains("AnimalsInventory"))
{
    var request = new CreateTableRequest
    {
        TableName = "AnimalsInventory",
        AttributeDefinitions = new List<AttributeDefinition>
      {
        new AttributeDefinition
        {
          AttributeName = "Id",
          // "S" = string, "N" = number, and so on.
          AttributeType = "N"
        },
        new AttributeDefinition
        {
          AttributeName = "Type",
          AttributeType = "S"
        }
      },
        KeySchema = new List<KeySchemaElement>
      {
        new KeySchemaElement
        {
          AttributeName = "Id",
          // "HASH" = hash key, "RANGE" = range key.
          KeyType = "HASH"
        },
        new KeySchemaElement
        {
          AttributeName = "Type",
          KeyType = "RANGE"
        },
      },
        ProvisionedThroughput = new ProvisionedThroughput
        {
            ReadCapacityUnits = 10,
            WriteCapacityUnits = 5
        },
    };

    var response = client.CreateTable(request);

    Console.WriteLine("Table created with request ID: " +
      response.ResponseMetadata.RequestId);
}
```

### Verificação de que uma tabela está pronta para ser modificada
<a name="dynamodb-intro-apis-low-level-verify-table"></a>

Antes que você possa alterar ou modificar uma tabela, esta tem de estar pronta para modificação. O exemplo a seguir mostra como usar o modelo de baixo nível para verificar se uma tabela do DynamoDB está pronta. Neste exemplo, a tabela de destino a ser verificada é mencionada pelo método `DescribeTable` da classe `AmazonDynamoDBClient`. A cada cinco segundos, o código verifica o valor da propriedade `TableStatus` da tabela. Quando o status é definido como `ACTIVE`, a tabela está pronta para ser modificada.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();      
var status = "";

do
{
  // Wait 5 seconds before checking (again).
  System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
        
  try
  {
    var response = client.DescribeTable(new DescribeTableRequest
    {
      TableName = "AnimalsInventory"
    });

    Console.WriteLine("Table = {0}, Status = {1}",
      response.Table.TableName,
      response.Table.TableStatus);

    status = response.Table.TableStatus;
  }
  catch (ResourceNotFoundException)
  {
    // DescribeTable is eventually consistent. So you might
    //   get resource not found. 
  }

} while (status != TableStatus.ACTIVE);
```

### Introdução um item em uma tabela
<a name="dynamodb-intro-apis-low-level-insert-item"></a>

No exemplo a seguir, você usa o modelo de baixo nível para inserir dois itens em uma tabela do DynamoDB. Cada item é inserido pelo método `PutItem` da classe `AmazonDynamoDBClient` usando uma instância da classe `PutItemRequest`. Cada uma das duas instâncias da classe `PutItemRequest` pega o nome da tabela em que os itens serão introduzidos, com uma série de valores de atributos de item.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();

var request1 = new PutItemRequest
{
  TableName = "AnimalsInventory",
  Item = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "1" }},
    { "Type", new AttributeValue { S = "Dog" }},
    { "Name", new AttributeValue { S = "Fido" }}
  }
};

var request2 = new PutItemRequest
{
  TableName = "AnimalsInventory",
  Item = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "2" }},
    { "Type", new AttributeValue { S = "Cat" }},
    { "Name", new AttributeValue { S = "Patches" }}
  }
};
        
client.PutItem(request1);
client.PutItem(request2);
```

## Modelo de documento
<a name="dynamodb-intro-apis-document"></a>

O modelo de programação de documento oferece uma maneira mais fácil para trabalhar com dados dentro do DynamoDB. Esse modelo é destinado especificamente a acessar tabelas e itens nas tabelas. Você acessa esse modelo por meio do [DBv2Amazon.Dynamo. DocumentModel](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/NDynamoDBv2DocumentModel.html)namespace.

Em comparação com o modelo de programação de baixo nível, o modelo de documento é mais fácil de codificar em relação aos dados do DynamoDB. Por exemplo, não é necessário converter tantos tipos de dados .NET em seus equivalentes no DynamoDB. Contudo, esse modelo não fornece acesso a tantos recursos como o modelo de programação de baixo nível. Por exemplo, você pode usar esse modelo para criar, recuperar, atualizar e excluir itens nas tabelas. No entanto, para criar as tabelas, é preciso usar o módulo de baixo nível. Em comparação com o modelo de persistência de objetos, este modelo exige que você grave mais código para armazenar, carregar e consultar objetos .NET.

Para obter mais informações sobre o modelo de programação de documentos do DynamoDB, consulte [.NET: modelo de documento](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetSDKMidLevel.html) no [Amazon DynamoDB Developer Guide](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/).

As seções a seguir fornecem informações sobre como criar uma representação da tabela desejada do DynamoDB e exemplos sobre como usar o modelo de documento para inserir itens em tabelas e obter itens de tabelas.

### Criar uma representação da tabela
<a name="dynamodb-intro-apis-document-table"></a>

Para realizar operações de dados usando o modelo de documento, você deve primeiro criar uma instância da classe `Table` que representa uma tabela específica. Há duas maneiras Principais de fazer isso:

**LoadTable method**

O primeiro mecanismo é usar um dos métodos estáticos `LoadTable` da classe [https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTable.html](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTable.html), semelhante ao exemplo a seguir:

```
var client = new AmazonDynamoDBClient();
Table table = Table.LoadTable(client, "Reply");
```

**nota**  
Embora esse mecanismo funcione, em determinadas condições, ele às vezes pode resultar em latência ou bloqueios adicionais devido aos comportamentos de inicialização a frio e de thread-pool. Para obter mais informações sobre esses comportamentos, consulte a postagem do blog [Padrões aprimorados de inicialização do DynamoDB para o AWS SDK para .NET](https://aws.amazon.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/).

**TableBuilder**

Um mecanismo alternativo, a [https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTableBuilder.html](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTableBuilder.html)classe, foi introduzido na [versão 3.7.203 do pacote .Dynamo AWSSDK](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/3.7.203). DBv2 NuGet Esse mecanismo pode abordar os comportamentos mencionados acima removendo certas chamadas de método implícitas, especificamente, o método `DescribeTable`. Esse mecanismo é usado de maneira semelhante ao seguinte exemplo:

```
var client = new AmazonDynamoDBClient();
var table = new TableBuilder(client, "Reply")
    .AddHashKey("Id", DynamoDBEntryType.String)
    .AddRangeKey("ReplyDateTime", DynamoDBEntryType.String)
    .AddGlobalSecondaryIndex("PostedBy-Message-index", "Author", DynamoDBEntryType.String, "Message", DynamoDBEntryType.String)
    .Build();
```

Para obter mais informações sobre esse mecanismo alternativo, consulte novamente a postagem do blog [Padrões aprimorados de inicialização do DynamoDB para o AWS SDK para .NET](https://aws.amazon.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/).

### Introdução de um item em uma tabela
<a name="dynamodb-intro-apis-document-insert-item"></a>

No exemplo a seguir, um item é introduzido na tabela de respostas por maio do método `PutItemAsync` da classe `Table`. O método `PutItemAsync` leva uma instância da classe `Document`; a classe `Document` é simplesmente uma coleção de atributos inicializados.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;

// Create a representation of the "Reply" table
//  by using one of the mechanisms described previously.

// Then, add a reply to the table.
var newReply = new Document();
newReply["Id"] = Guid.NewGuid().ToString();
newReply["ReplyDateTime"] = DateTime.UtcNow;
newReply["PostedBy"] = "Author1";
newReply["Message"] = "Thank you!";

await table.PutItemAsync(newReply);
```

### Obtendo um item de uma tabela
<a name="dynamodb-intro-apis-document-get-item"></a>

No exemplo a seguir, uma resposta é recuperada pelo método `GetItemAsync` da classe `Table`. Para determinar a resposta a ser obtida, o `GetItemAsync` método usa a chave hash-and-range primária da resposta de destino.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;

// Create a representation of the "Reply" table
//  by using one of the mechanisms described previously.

// Then, get a reply from the table
//  where "guid" is the hash key and "datetime" is the range key.
var reply = await table.GetItemAsync(guid, datetime);
Console.WriteLine("Id = " + reply["Id"]);
Console.WriteLine("ReplyDateTime = " + reply["ReplyDateTime"]);
Console.WriteLine("PostedBy = " + reply["PostedBy"]);
Console.WriteLine("Message = " + reply["Message"]);
```

O exemplo anterior converte implicitamente valores de tabela em strings para o método `WriteLine`. Você pode fazer conversões explícitas usando os vários métodos de “As[type]” da classe `DynamoDBEntry`. Por exemplo, você pode converter explicitamente o valor para o `Id` a partir do tipo de dado `Primitive` para um GUID por meio do método `AsGuid()`:

```
var guid = reply["Id"].AsGuid();
```

## Modelo de persistência de objeto
<a name="dynamodb-intro-apis-object-persistence"></a>

O modelo de programação de persistência de objetos é especificamente projetado para armazenar, carregar e consultar objetos .NET no DynamoDB. Você acessa esse modelo por meio do [DBv2Amazon.Dynamo. DataModel](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/NDynamoDBv2DataModel.html)namespace.

Dos três modelos, o modelo de persistência de objetos é o mais fácil de codificar sempre que estiver armazenando, carregando ou consultando dados do DynamoDB. Por exemplo, você trabalha diretamente com os tipos de dados do DynamoDB. Contudo, este modelo fornece acesso somente a operações que armazenam, carregam e consultam objetos .NET no DynamoDB. Por exemplo, você pode usar esse modelo para criar, recuperar, atualizar e excluir itens nas tabelas. No entanto, é preciso primeiro criar suas tabelas usando o modelo de baixo nível e, em seguida, usar esse modelo para mapear suas classes .NET para as tabelas.

Para obter mais informações sobre o modelo de programação de persistência de objetos do DynamoDB, consulte [.NET: modelo de persistência de objetos](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetSDKHighLevel.html) no [Guia do desenvolvedor do Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/).

Os exemplos a seguir mostram como definir uma classe .NET que representa um item DynamoDB, usa uma instância da classe .NET para inserir um item no DynamoDB e usa uma instância de uma classe .NET para obter um item de uma tabela.

### Definindo uma classe .NET que represente um item em uma tabela
<a name="dynamodb-intro-apis-object-persistence-net-class-item"></a>

No exemplo a seguir de uma definição de classe, o `DynamoDBTable` atributo especifica o nome da tabela, enquanto os `DynamoDBRangeKey` atributos `DynamoDBHashKey` e modelam a chave hash-and-range primária da tabela. O atributo `DynamoDBGlobalSecondaryIndexHashKey` é definido para que uma consulta de respostas de um autor específico possa ser construída.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

[DynamoDBTable("Reply")]
public class Reply
{
    [DynamoDBHashKey]
    public string Id { get; set; }

    [DynamoDBRangeKey(StoreAsEpoch = false)]
    public DateTime ReplyDateTime { get; set; }

    [DynamoDBGlobalSecondaryIndexHashKey("PostedBy-Message-Index",
        AttributeName ="PostedBy")]
    public string Author { get; set; }

    [DynamoDBGlobalSecondaryIndexRangeKey("PostedBy-Message-Index")]
    public string Message { get; set; }
}
```

### Criando um contexto para o modelo de persistência de objetos
<a name="dynamodb-intro-apis-object-persistence-context"></a>

Para usar o modelo de programação de persistência de objetos para o DynamoDB, você deve criar um contexto que forneça uma conexão ao DynamoDB e permita acessar tabelas, e realizar diversas operações e executar consultas.

**Contexto básico**

O exemplo de código a seguir mostra como criar o contexto mais básico.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
```

**Contexto com DisableFetchingTableMetadata propriedade**

O exemplo a seguir mostra como você também pode definir a propriedade `DisableFetchingTableMetadata` da classe `DynamoDBContextConfig` para evitar chamadas implícitas ao método `DescribeTable`.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client, new DynamoDBContextConfig
{
    DisableFetchingTableMetadata = true
});
```

Se a propriedade `DisableFetchingTableMetadata` estiver definida como `false` (o padrão), conforme mostrado no primeiro exemplo, você poderá omitir os atributos que descrevem a estrutura de chave e índice dos itens da tabela da classe `Reply`. Em vez disso, esses atributos serão inferidos por meio de uma chamada implícita ao método `DescribeTable`. Se o `DisableFetchingTableMetadata` for definido como `true`, conforme mostrado no segundo exemplo, métodos do modelo de persistência de objetos, como o `SaveAsync` e o `QueryAsync` depende inteiramente dos atributos definidos na classe `Reply`. Nesse caso, uma chamada para o método `DescribeTable` não ocorre.

**nota**  
Sob certas condições, as chamadas para o método `DescribeTable` às vezes podem levar a latência ou bloqueios adicionais devido aos comportamentos de inicialização a frio e thread-pool. Por esse motivo, às vezes é vantajoso evitar chamadas para esse método.  
Para obter mais informações sobre esses comportamentos, consulte a postagem do blog [Padrões aprimorados de inicialização do DynamoDB para o AWS SDK para .NET](https://aws.amazon.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/).

### Usando uma instância da classe .NET para inserir um item em uma tabela
<a name="dynamodb-intro-apis-object-persistence-net-insert-item"></a>

Neste exemplo, um item é inserido pelo método `SaveAsync` da classe `DynamoDBContext`, que recebe uma instância inicializada da classe .NET que representa o item.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

// Create an appropriate context for the object persistence programming model,
//  examples of which have been described earlier.

// Create an object that represents the new item.
var reply = new Reply()
{
    Id = Guid.NewGuid().ToString(),
    ReplyDateTime = DateTime.UtcNow,
    Author = "Author1",
    Message = "Thank you!"
};

// Insert the item into the table.
await context.SaveAsync<Reply>(reply, new DynamoDBOperationConfig
{
    IndexName = "PostedBy-Message-index"
});
```

### Usando uma instância de um objeto .NET para obter itens de uma tabela
<a name="dynamodb-intro-apis-object-persistence-net-get-item"></a>

Neste exemplo, uma consulta é criada para encontrar todos os registros de “Author1” usando o método `QueryAsync` da classe `DynamoDBContext`. Em seguida, os itens são recuperados por meio do método `GetNextSetAsync` de consulta.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

// Create an appropriate context for the object persistence programming model,
//  examples of which have been described earlier.

// Construct a query that finds all replies by a specific author.
var query = context.QueryAsync<Reply>("Author1", new DynamoDBOperationConfig
{
    IndexName = "PostedBy-Message-index"
});

// Display the result.
var set = await query.GetNextSetAsync();
foreach (var item in set)
{
    Console.WriteLine("Id = " + item.Id);
    Console.WriteLine("ReplyDateTime = " + item.ReplyDateTime);
    Console.WriteLine("PostedBy = " + item.Author);
    Console.WriteLine("Message = " + item.Message);
}
```

### Informações adicionais sobre o modelo de persistência de objetos
<a name="dynamodb-intro-apis-object-persistence-more-into"></a>

Os exemplos e explicações mostrados acima às vezes incluem uma propriedade da classe `DynamoDBContext` chamada `DisableFetchingTableMetadata`. Essa propriedade, que foi introduzida na [versão 3.7.203 do DBv2 NuGet pacote AWSSDK .Dynamo](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/3.7.203), permite que você evite certas condições que podem causar latência adicional ou bloqueios devido aos comportamentos de inicialização a frio e pool de threads. Para obter mais informações, consulte a postagem de blog [Padrões aprimorados de inicialização do Dynamo DB para o AWS SDK para .NET](https://aws.amazon.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/).

A seguir, algumas informações adicionais sobre essa propriedade.
+ Essa propriedade pode ser definida globalmente em seu arquivo `app.config` ou `web.config` se estiver usando o .NET Framework.
+ Essa propriedade pode ser definida globalmente usando a classe [https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Amazon/TAWSConfigsDynamoDB.html](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Amazon/TAWSConfigsDynamoDB.html), como mostra o exemplo a seguir.

  ```
  // Set the DisableFetchingTableMetadata property globally
  // before constructing any context objects.
  AWSConfigsDynamoDB.Context.DisableFetchingTableMetadata = true;
  
  var client = new AmazonDynamoDBClient();
  var context = new DynamoDBContext(client);
  ```
+ Em alguns casos, você não pode adicionar atributos do DynamoDB a uma classe .NET, por exemplo, se a classe estiver definida em uma dependência. Nesses casos, ainda é possível aproveitar a propriedade `DisableFetchingTableMetadata`. Para fazer isso, use a classe [https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTableBuilder.html](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TTableBuilder.html) além da propriedade `DisableFetchingTableMetadata`. A `TableBuilder` classe também foi introduzida na [versão 3.7.203 do pacote .Dynamo AWSSDK](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/3.7.203). DBv2 NuGet 

  ```
  // Set the DisableFetchingTableMetadata property globally
  // before constructing any context objects.
  AWSConfigsDynamoDB.Context.DisableFetchingTableMetadata = true;
  
  var client = new AmazonDynamoDBClient();
  var context = new DynamoDBContext(client);
  
  var table = new TableBuilder(client, "Reply")
      .AddHashKey("Id", DynamoDBEntryType.String)
      .AddRangeKey("ReplyDateTime", DynamoDBEntryType.String)
      .AddGlobalSecondaryIndex("PostedBy-Message-index", "Author", DynamoDBEntryType.String,
          "Message", DynamoDBEntryType.String)
      .Build();
  
  // This registers the "Reply" table we constructed via the builder.
  context.RegisterTableDefinition(table);
  
  // Now operations like this will work,
  // even if the Reply class was not annotated with this index.
  var query = context.QueryAsync<Reply>("Author1", new DynamoDBOperationConfig()
  {
      IndexName = "PostedBy-Message-index"
  });
  ```

## Mais informações
<a name="dynamodb-intro-more-info"></a>

 **Usando o AWS SDK para .NET para programar o DynamoDB, informações e exemplos**
+  [DynamoDB APIs](http://blogs.aws.amazon.com/net/post/Tx17SQHVEMW8MXC/DynamoDB-APIs) 
+  [Kickoff do DynamoDB Series](http://blogs.aws.amazon.com/net/post/Tx2XQOCY08QMTKO/DynamoDB-Series-Kickoff) 
+  [DynamoDB Series – Modelo de documento](http://blogs.aws.amazon.com/net/post/Tx2R0WG46GQI1JI/DynamoDB-Series-Document-Model) 
+  [DynamoDB Series – Esquemas de conversão](http://blogs.aws.amazon.com/net/post/Tx2TCOGWG7ARUH5/DynamoDB-Series-Conversion-Schemas) 
+  [DynamoDB Series – Modelo de persistência de objetos](http://blogs.aws.amazon.com/net/post/Tx20L86FLMBW51P/DynamoDB-Series-Object-Persistence-Model) 
+  [DynamoDB Series – Expressões](http://blogs.aws.amazon.com/net/post/TxZQM7VA9AUZ9L/DynamoDB-Series-Expressions) 
+  [Usando expressões com o Amazon DynamoDB e o AWS SDK para .NET](dynamodb-expressions.md) 
+  [Suporte para JSON no Amazon DynamoDB](dynamodb-json.md) 

 **Informações e exemplos do modelo de baixo nível** 
+  [Trabalhando com tabelas usando a API AWS SDK para .NET de baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetWorkingWithTables.html) 
+  [Trabalhando com itens usando a API AWS SDK para .NET de baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetItemCRUD.html) 
+  [Consultando tabelas usando a API de AWS SDK para .NET baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetQuerying.html) 
+  [Digitalizando tabelas usando a API AWS SDK para .NET de baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetScanning.html) 
+  [Trabalhando com índices secundários locais usando a API AWS SDK para .NET de baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSILowLevelDotNet.html) 
+  [Trabalhando com índices secundários globais usando a API AWS SDK para .NET de baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSILowLevelDotNet.html) 

 **Informações e exemplos do modelo de documentos** 
+  [Tipos de dados do DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataModel.html#DataModel.DataTypes) 
+  [Dínamo DBEntry](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TDynamoDBv2DocumentModelDynamoDBEntry.html) 
+  [.NET: Modelo de documento](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetSDKMidLevel.html) 

 **Informações e exemplos de modelo de persistência de objetos** 
+  [.NET: Modelo de persistência de objeto](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DotNetSDKHighLevel.html) 

 **Outras informações úteis** 
+ Consulte [Integração AWS com o.NET Aspire](aspire-integrations.md) para acessar informações sobre o desenvolvimento com o Amazon DynamoDB local por meio do .NET Aspire.

**Topics**
+ [Modelo de baixo nível](#dynamodb-intro-apis-low-level)
+ [Modelo de documento](#dynamodb-intro-apis-document)
+ [Modelo de persistência de objeto](#dynamodb-intro-apis-object-persistence)
+ [Mais informações](#dynamodb-intro-more-info)
+ [Usar expressões](dynamodb-expressions.md)
+ [Suporte para JSON](dynamodb-json.md)

# Usando expressões com o Amazon DynamoDB e o AWS SDK para .NET
<a name="dynamodb-expressions"></a>

**nota**  
As informações neste tópico são específicas para projetos baseados no.NET Framework e na AWS SDK para .NET versão 3.3 e anteriores.

Os exemplos de código a seguir demonstram como usar o para AWS SDK para .NET programar o DynamoDB com expressões. As *expressões* denotam os atributos que você deseja ler de um item na tabela do DynamoDB. Você também usa expressões ao gravar um item, de forma a indicar quaisquer condições devam ser atendidas (também conhecido como *atualização condicional*) e como os atributos devem ser atualizados. Alguns exemplos de atualização substituem o atributo por um valor novo ou adicionam novos dados a uma lista ou um mapa. Para obter mais informações, consulte [Reading and Writing Items Using Expressions (Leitura e gravação de itens usando expressões)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.html).

**Topics**
+ [Dados de exemplo](#dynamodb-expressions-sample-data)
+ [Obtenha um único item usando expressões e a chave principal do item](#dynamodb-expressions-get-item)
+ [Obtenha vários itens usando expressões e a chave principal da tabela](#dynamodb-expressions-query)
+ [Obtenha vários itens usando expressões e outros atributos do item](#dynamodb-expressions-scan)
+ [Imprimir um item](#dynamodb-expressions-print-item)
+ [Criar ou substituir um item usando expressões](#dynamodb-expressions-put-item)
+ [Atualização de um item usando expressões](#dynamodb-expressions-update-item)
+ [Exclusão de um item usando expressões](#dynamodb-expressions-delete-item)
+ [Mais informações](#dynamodb-expressions-resources)

## Dados de exemplo
<a name="dynamodb-expressions-sample-data"></a>

Os exemplos de código neste tópico dependem dos dois itens de exemplo a seguir em uma tabela do DynamoDB chamada `ProductCatalog`. Esses itens descrevem as informações sobre entradas do produto em um catálogo fictício de loja de bicicleta. Esses itens são baseados no exemplo fornecido em [Estudo de caso: um ProductCatalog item](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.CaseStudy.html). Os descritores de tipos de dados, como `BOOL`, `L`, `M`, `N`, `NS`, `S` e `SS`, corresponde aos em [JSON Data Format (Formato de dados JSON)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataFormat.html).

```
{
  "Id": {
    "N": "205"
  },
  "Title": {
    "S": "20-Bicycle 205"
  },
  "Description": {
    "S": "205 description"
  },
  "BicycleType": {
    "S": "Hybrid"
  },
  "Brand": {
    "S": "Brand-Company C"
  },
  "Price": {
    "N": "500"
  },
  "Gender": {
    "S": "B"
  },
  "Color": {
    "SS": [
      "Red",
      "Black"
    ]
  },
  "ProductCategory": {
    "S": "Bike"
  },
  "InStock": {
    "BOOL": true
  },
  "QuantityOnHand": {
    "N": "1"
  },
  "RelatedItems": {
    "NS": [
      "341",
      "472",
      "649"
    ]
  },
  "Pictures": {
    "L": [
      {
        "M": {
          "FrontView": {
            "S": "http://example/products/205_front.jpg"
          }
        }
      },
      {
        "M": {
          "RearView": {
            "S": "http://example/products/205_rear.jpg"
          }
        }
      },
      {
        "M": {
          "SideView": {
            "S": "http://example/products/205_left_side.jpg"
          }
        }
      }
    ]
  },
  "ProductReviews": {
    "M": {
      "FiveStar": {
        "SS": [
          "Excellent! Can't recommend it highly enough! Buy it!",
          "Do yourself a favor and buy this."
        ]
      },
      "OneStar": {
        "SS": [
          "Terrible product! Do not buy this."
        ]
      }
    }
  }
},
{
  "Id": {
    "N": "301"
  },
  "Title": {
    "S": "18-Bicycle 301"
  },
  "Description": {
    "S": "301 description"
  },
  "BicycleType": {
    "S": "Road"
  },
  "Brand": {
    "S": "Brand-Company C"
  },
  "Price": {
    "N": "185"
  },
  "Gender": {
    "S": "F"
  },
  "Color": {
    "SS": [
      "Blue",
      "Silver"
    ]
  },
  "ProductCategory": {
    "S": "Bike"
  },
  "InStock": {
    "BOOL": true
  },
  "QuantityOnHand": {
    "N": "3"
  },
  "RelatedItems": {
    "NS": [
      "801",
      "822",
      "979"
    ]
  },
  "Pictures": {
    "L": [
      {
        "M": {
          "FrontView": {
            "S": "http://example/products/301_front.jpg"
          }
        }
      },
      {
        "M": {
          "RearView": {
            "S": "http://example/products/301_rear.jpg"
          }
        }
      },
      {
        "M": {
          "SideView": {
            "S": "http://example/products/301_left_side.jpg"
          }
        }
      }
    ]
  },
  "ProductReviews": {
    "M": {
      "FiveStar": {
        "SS": [
          "My daughter really enjoyed this bike!"
        ]
      },
      "ThreeStar": {
        "SS": [
          "This bike was okay, but I would have preferred it in my color.",
	      "Fun to ride."
        ]
      }
    }
  }
}
```

## Obtenha um único item usando expressões e a chave principal do item
<a name="dynamodb-expressions-get-item"></a>

O exemplo a seguir apresenta o método `Amazon.DynamoDBv2.AmazonDynamoDBClient.GetItem` e um conjunto de expressões para obter e imprimir o item que tem um `Id` of `205`. Somente os atributos a seguir do item são retornados: `Id`, `Title`, `Description`, `Color`, `RelatedItems`, `Pictures` e `ProductReviews`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new GetItemRequest
{
  TableName = "ProductCatalog",
  ProjectionExpression = "Id, Title, Description, Color, #ri, Pictures, #pr",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#pr", "ProductReviews" },
    { "#ri", "RelatedItems" }
  },
  Key = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "205" } }
  },
};
var response = client.GetItem(request);

// PrintItem() is a custom function.
PrintItem(response.Item);
```

No exemplo anterior, a propriedade `ProjectionExpression` especifica os atributos a serem retornados. A propriedade `ExpressionAttributeNames` especifica o placeholder `#pr` para representar o atributo `ProductReviews` e o placeholder `#ri` para representar o atributo `RelatedItems`. A chamada para `PrintItem` refere-se uma função personalizada, como descrito em [Imprimir um item](#dynamodb-expressions-print-item).

## Obtenha vários itens usando expressões e a chave principal da tabela
<a name="dynamodb-expressions-query"></a>

O exemplo a seguir caracteriza o método `Amazon.DynamoDBv2.AmazonDynamoDBClient.Query` e uma série de expressões para obter e imprimir o item que tenha um `Id` of `301`, mas somente se o valor de `Price` for maior que `150`. Somente os atributos a seguir do item são retornados: `Id`, `Title` e todos os atributos `ThreeStar` em `ProductReviews`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new QueryRequest
{
  TableName = "ProductCatalog",
  KeyConditions = new Dictionary<string,Condition>
  {
    { "Id", new Condition()
      {
        ComparisonOperator = ComparisonOperator.EQ,
        AttributeValueList = new List<AttributeValue>
        {
          new AttributeValue { N = "301" }
        }
      }
    }
  },
  ProjectionExpression = "Id, Title, #pr.ThreeStar",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#pr", "ProductReviews" },
    { "#p", "Price" }
  },
  ExpressionAttributeValues = new Dictionary<string,AttributeValue>
  {
    { ":val", new AttributeValue { N = "150" } }
  },
  FilterExpression = "#p > :val"
};
var response = client.Query(request);

foreach (var item in response.Items)
{
  // Write out the first page of an item's attribute keys and values.
  // PrintItem() is a custom function.
  PrintItem(item);
  Console.WriteLine("=====");
}
```

No exemplo anterior, a propriedade `ProjectionExpression` especifica os atributos a serem retornados. A propriedade `ExpressionAttributeNames` especifica o espaço reservado `#pr` para representar o atributo `ProductReviews` e o espaço reservado `#p` para representar o atributo `Price`. `#pr.ThreeStar` especifica para retornar somente o atributo `ThreeStar`. A propriedade `ExpressionAttributeValues` especifica o placeholder `:val` para representar o valor `150`. A propriedade `FilterExpression` especifica que `#p` (`Price`) deve ser maior que `:val` (`150`). A chamada para `PrintItem` refere-se uma função personalizada, como descrito em [Imprimir um item](#dynamodb-expressions-print-item).

## Obtenha vários itens usando expressões e outros atributos do item
<a name="dynamodb-expressions-scan"></a>

O exemplo a seguir apresenta o método `Amazon.DynamoDBv2.AmazonDynamoDBClient.Scan` e um conjunto de expressões para obter e imprimir todos os itens que tenham `ProductCategory` of `Bike`. Somente os atributos a seguir do item são retornados: `Id`, `Title` e todos os atributos em `ProductReviews`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new ScanRequest
{
  TableName = "ProductCatalog",
  ProjectionExpression = "Id, Title, #pr",
  ExpressionAttributeValues = new Dictionary<string,AttributeValue>
  {
    { ":catg", new AttributeValue { S = "Bike" } }
  },
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#pr", "ProductReviews" },
    { "#pc", "ProductCategory" }
  },
  FilterExpression = "#pc = :catg",  
};
var response = client.Scan(request);

foreach (var item in response.Items)
{
  // Write out the first page/scan of an item's attribute keys and values.
  // PrintItem() is a custom function.
  PrintItem(item);
  Console.WriteLine("=====");
}
```

No exemplo anterior, a propriedade `ProjectionExpression` especifica os atributos a serem retornados. A propriedade `ExpressionAttributeNames` especifica o placeholder `#pr` para representar o atributo `ProductReviews` e o placeholder `#pc` para representar o atributo `ProductCategory`. A propriedade `ExpressionAttributeValues` especifica o placeholder `:catg` para representar o valor `Bike`. A propriedade `FilterExpression` especifica que `#pc` (`ProductCategory`) deve ser igual a `:catg` (`Bike`). A chamada para `PrintItem` refere-se uma função personalizada, como descrito em [Imprimir um item](#dynamodb-expressions-print-item).

## Imprimir um item
<a name="dynamodb-expressions-print-item"></a>

O exemplo a seguir mostra como imprimir os atributos e os valores de um item. Este exemplo é usado nos exemplos anteriores que mostram como [Obter um único item usando expressões e a chave principal do item](#dynamodb-expressions-get-item), [Obter vários itens usando expressões e a chave principal da tabela](#dynamodb-expressions-query) e [Obter vários itens usando expressões e outros atributos do item](#dynamodb-expressions-scan).

```
// using Amazon.DynamoDBv2.Model;

// Writes out an item's attribute keys and values.
public static void PrintItem(Dictionary<string, AttributeValue> attrs)
{
  foreach (KeyValuePair<string, AttributeValue> kvp in attrs)
  {
    Console.Write(kvp.Key + " = ");
    PrintValue(kvp.Value);
  }
}

// Writes out just an attribute's value.
public static void PrintValue(AttributeValue value)
{
  // Binary attribute value.
  if (value.B != null)
  {
    Console.Write("Binary data");
  }
  // Binary set attribute value.
  else if (value.BS.Count > 0)
  {
    foreach (var bValue in value.BS)
    {
      Console.Write("\n  Binary data");
    }
  }
  // List attribute value.
  else if (value.L.Count > 0)
  {
    foreach (AttributeValue attr in value.L)
    {
      PrintValue(attr);
    }
  }
  // Map attribute value.
  else if (value.M.Count > 0)
  {
    Console.Write("\n");
    PrintItem(value.M);
  }
  // Number attribute value.
  else if (value.N != null)
  {
    Console.Write(value.N);
  }
  // Number set attribute value.
  else if (value.NS.Count > 0)
  {
    Console.Write("{0}", string.Join("\n", value.NS.ToArray()));
  }
  // Null attribute value.
  else if (value.NULL)
  {
    Console.Write("Null");
  }
  // String attribute value.
  else if (value.S != null)
  {
    Console.Write(value.S);
  }
  // String set attribute value.
  else if (value.SS.Count > 0)
  {
    Console.Write("{0}", string.Join("\n", value.SS.ToArray()));
  }
  // Otherwise, boolean value.
  else
  {
    Console.Write(value.BOOL);
  }
 
  Console.Write("\n");
}
```

No exemplo anterior, cada valor de atributo tem várias data-type-specific propriedades que podem ser avaliadas para determinar o formato correto para imprimir o atributo. Essas propriedades incluem `B`, `BOOL`, `BS`, `L`, `M`, `N`, `NS`, `NULL`, `S` e `SS`, que correspondem às no [formato de dados JSON](DataFormat.html). Para propriedades como `B`, `N`, `NULL` e `S`, se a propriedade correspondente não for `null`, o atributo será o tipo de dados não `null` correspondente. Para propriedades como`BS`,,`L`, `M``NS`, e`SS`, se `Count` for maior que zero, o atributo será do tipo de non-zero-value dados correspondente. Se todas as data-type-specific propriedades do atributo forem iguais `null` ou `Count` iguais a zero, o atributo corresponderá ao tipo de `BOOL` dados.

## Criar ou substituir um item usando expressões
<a name="dynamodb-expressions-put-item"></a>

O exemplo a seguir apresenta o método `Amazon.DynamoDBv2.AmazonDynamoDBClient.PutItem` e um conjunto de expressões para atualizar o item com `Title` of `18-Bicycle 301`. Se o item não existir ainda, será adicionado um novo item.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new PutItemRequest
{
  TableName = "ProductCatalog",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#title", "Title" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
    { ":product", new AttributeValue { S = "18-Bicycle 301" } }
  },
  ConditionExpression = "#title = :product", 
  // CreateItemData() is a custom function.
  Item = CreateItemData()
};
client.PutItem(request);
```

No exemplo anterior, a propriedade `ExpressionAttributeNames` especifica o placeholder `#title` para representar o atributo `Title`. A propriedade `ExpressionAttributeValues` especifica o placeholder `:product` para representar o valor `18-Bicycle 301`. A propriedade `ConditionExpression` especifica que `#title` (`Title`) deve ser igual a `:product` (`18-Bicycle 301`). A chamada para `CreateItemData` refere-se à seguinte função personalizada:

```
// using Amazon.DynamoDBv2.Model;

// Provides a sample item that can be added to a table.
public static Dictionary<string, AttributeValue> CreateItemData()
{
  var itemData = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "301" } },
    { "Title", new AttributeValue { S = "18\" Girl's Bike" } },
    { "BicycleType", new AttributeValue { S = "Road" } },
    { "Brand" , new AttributeValue { S = "Brand-Company C" } },
    { "Color", new AttributeValue { SS = new List<string>{ "Blue", "Silver" } } },
    { "Description", new AttributeValue { S = "301 description" } },
    { "Gender", new AttributeValue { S = "F" } },
    { "InStock", new AttributeValue { BOOL = true } },
    { "Pictures", new AttributeValue { L = new List<AttributeValue>{ 
      { new AttributeValue { M = new Dictionary<string,AttributeValue>{
        { "FrontView", new AttributeValue { S = "http://example/products/301_front.jpg" } } } } },
      { new AttributeValue { M = new Dictionary<string,AttributeValue>{
        { "RearView", new AttributeValue {S = "http://example/products/301_rear.jpg" } } } } },
      { new AttributeValue { M = new Dictionary<string,AttributeValue>{
        { "SideView", new AttributeValue { S = "http://example/products/301_left_side.jpg" } } } } }
    } } },
    { "Price", new AttributeValue { N = "185" } },
    { "ProductCategory", new AttributeValue { S = "Bike" } },
    { "ProductReviews", new AttributeValue { M = new Dictionary<string,AttributeValue>{
      { "FiveStar", new AttributeValue { SS = new List<string>{
        "My daughter really enjoyed this bike!" } } },
      { "OneStar", new AttributeValue { SS = new List<string>{
        "Fun to ride.",
        "This bike was okay, but I would have preferred it in my color." } } }
    } } },
    { "QuantityOnHand", new AttributeValue { N = "3" } },
    { "RelatedItems", new AttributeValue { NS = new List<string>{ "979", "822", "801" } } }
  };

  return itemData;
}
```

No exemplo anterior, um item de exemplo com dados de exemplo é retornado ao chamador. Uma série de atributos e valores correspondentes é construída usando os tipos de dados como `BOOL`, `L`, `M`, `N`, `NS`, `S` e `SS`, que correspondem aos do [JSON Data Format (formato de dados JSON)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataFormat.html).

## Atualização de um item usando expressões
<a name="dynamodb-expressions-update-item"></a>

O exemplo a seguir apresenta o método `Amazon.DynamoDBv2.AmazonDynamoDBClient.UpdateItem` e um conjunto de expressões para alterar `Title` para `18" Girl's Bike` para o item com `Id` de `301`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new UpdateItemRequest
{
  TableName = "ProductCatalog",
  Key = new Dictionary<string,AttributeValue>
  {
     { "Id", new AttributeValue { N = "301" } }
  },
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#title", "Title" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
    { ":newproduct", new AttributeValue { S = "18\" Girl's Bike" } }
  },
  UpdateExpression = "SET #title = :newproduct"
};
client.UpdateItem(request);
```

No exemplo anterior, a propriedade `ExpressionAttributeNames` especifica o placeholder `#title` para representar o atributo `Title`. A propriedade `ExpressionAttributeValues` especifica o placeholder `:newproduct` para representar o valor `18" Girl's Bike`. A propriedade `UpdateExpression` especifica a alteração de `#title` (`Title`) para `:newproduct` (`18" Girl's Bike`).

## Exclusão de um item usando expressões
<a name="dynamodb-expressions-delete-item"></a>

O exemplo a seguir caracteriza o método `Amazon.DynamoDBv2.AmazonDynamoDBClient.DeleteItem` e um conjunto de expressões para excluir o item com `Id` de `301`, mas somente se o `Title` do item for `18-Bicycle 301`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new DeleteItemRequest
{
  TableName = "ProductCatalog",
  Key = new Dictionary<string,AttributeValue>
  {
     { "Id", new AttributeValue { N = "301" } }
  },
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#title", "Title" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
    { ":product", new AttributeValue { S = "18-Bicycle 301" } }
  },
  ConditionExpression = "#title = :product"
};
client.DeleteItem(request);
```

No exemplo anterior, a propriedade `ExpressionAttributeNames` especifica o placeholder `#title` para representar o atributo `Title`. A propriedade `ExpressionAttributeValues` especifica o placeholder `:product` para representar o valor `18-Bicycle 301`. A propriedade `ConditionExpression` especifica que `#title` (`Title`) deve ser igual a `:product` (`18-Bicycle 301`).

## Mais informações
<a name="dynamodb-expressions-resources"></a>

Para obter mais informações e exemplos de código, consulte:
+  [DynamoDB Series – Expressões](http://blogs.aws.amazon.com/net/post/TxZQM7VA9AUZ9L/DynamoDB-Series-Expressions) 
+  [Acesso aos atributos do item com expressões de projeção](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) 
+  [Uso de placeholders para nomes e valores de atributo](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ExpressionPlaceholders.html) 
+  [Especificação de condições com expressões de condição](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) 
+  [Modificação de itens e atributos com expressões de atualização](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Modifying.html) 
+  [Trabalhando com itens usando a API AWS SDK para .NET de baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetItemCRUD.html) 
+  [Consultando tabelas usando a API de AWS SDK para .NET baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetQuerying.html) 
+  [Digitalizando tabelas usando a API AWS SDK para .NET de baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetScanning.html) 
+  [Trabalhando com índices secundários locais usando a API AWS SDK para .NET de baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSILowLevelDotNet.html) 
+  [Trabalhando com índices secundários globais usando a API AWS SDK para .NET de baixo nível](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSILowLevelDotNet.html) 

# Suporte para JSON no Amazon DynamoDB
<a name="dynamodb-json"></a>

**nota**  
As informações neste tópico são específicas para projetos baseados no.NET Framework e na AWS SDK para .NET versão 3.3 e anteriores.

O AWS SDK para .NET suporta dados JSON ao trabalhar com o Amazon DynamoDB. Isso permite que você obtenha dados formatados para JSON com mais facilidade e insira documentos em JSON nas tabelas do DynamoDB.

**Topics**
+ [Obtenha dados de uma tabela do DynamoDB em formato JSON](#dynamodb-json-get-table-data)
+ [Inserira os dados do formato JSON em uma tabela do DynamoDB](#dynamodb-json-insert-table-data)
+ [Conversões do tipo de dados do DynamoDB para JSON](#dynamodb-json-datatypes)
+ [Mais informações](#dynamodb-json-more-info)

## Obtenha dados de uma tabela do DynamoDB em formato JSON
<a name="dynamodb-json-get-table-data"></a>

O exemplo a seguir mostra como obter dados de uma tabela em formato JSON:

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.DocumentModel;

var client = new AmazonDynamoDBClient();
var table = Table.LoadTable(client, "AnimalsInventory");
var item = table.GetItem(3, "Horse");

var jsonText = item.ToJson();
Console.Write(jsonText);
      
// Output:
//   {"Name":"Shadow","Type":"Horse","Id":3}

var jsonPrettyText = item.ToJsonPretty();
Console.WriteLine(jsonPrettyText);
      
// Output:
//   {
//     "Name" : "Shadow",
//     "Type" : "Horse",
//     "Id"   : 3
//   }
```

No exemplo anterior, o método `ToJson` da classe `Document` converte um item da tabela em uma string formatada para JSON. O item é recuperado pelo método `GetItem` da classe `Table`. Para determinar o item a ser obtido, neste exemplo, o `GetItem` método usa a chave hash-and-range primária do item de destino. Para determinar a tabela de onde se obter o item, o método `LoadTable` da classe `Table` usa uma instância da classe `AmazonDynamoDBClient` e o nome da tabela de destino no DynamoDB.

## Inserira os dados do formato JSON em uma tabela do DynamoDB
<a name="dynamodb-json-insert-table-data"></a>

O exemplo a seguir mostra como usar o formato JSON para inserir um item em uma tabela do DynamoDB:

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.DocumentModel;

var client = new AmazonDynamoDBClient();
var table = Table.LoadTable(client, "AnimalsInventory");
var jsonText = "{\"Id\":6,\"Type\":\"Bird\",\"Name\":\"Tweety\"}";
var item = Document.FromJson(jsonText);

table.PutItem(item);
```

No exemplo anterior, o método `FromJson` da classe `Document` converte uma string formatada para JSON em um item. O item é inserido na tabela pelo método `PutItem` da classe `Table`, que usa a instância da classe `Document` que contém o item. Para determinar a tabela na qual inserir o item, o método `LoadTable` da classe `Table` é chamado, especificando uma instância da classe `AmazonDynamoDBClient` e o nome da tabela de destino no DynamoDB.

## Conversões do tipo de dados do DynamoDB para JSON
<a name="dynamodb-json-datatypes"></a>

Sempre que você chamar o método `ToJson` da classe `Document` e depois nos dados JSON resultantes chamar o método `FromJson` para converter dados JSON de volta a uma instância de uma classe `Document`, alguns tipos de dados do DynamoDB não serão convertidos como esperado. Especificamente:
+ Os conjuntos do DynamoDB (os tipos `SS`, `NS` e `BS`) serão convertidos em matrizes JSON.
+ Conjuntos e escalares binários do DynamoDB (os tipos `B` e `BS`) serão convertidos em strings JSON codificadas para base64 ou em listas de strings.

  Nesse cenário, você deverá chamar o método `DecodeBase64Attributes` da classe `Document` para substituir os dados de JSON codificados para base64 pela representação binária correta. O exemplo a seguir substitui um atributo de item escalar binário codificado para base64 em uma instância de uma classe `Document`, de nome `Picture`, pela representação binária correta. Este exemplo também faz o mesmo pelo atributo do item do conjunto binário codificado para base64 na mesma instância da classe `Document`, de nome `RelatedPictures`:

  ```
  item.DecodeBase64Attributes("Picture", "RelatedPictures");
  ```

## Mais informações
<a name="dynamodb-json-more-info"></a>

Para obter mais informações e exemplos de programação de JSON com o DynamoDB com o, consulte: AWS SDK para .NET
+  [Suporte a JSON pelo DynamoDB](https://aws.amazon.com/blogs/developer/dynamodb-json-support/) 
+  [Atualização do Amazon DynamoDB – JSON, nível gratuito expandido, escalabilidade flexível, itens maiores](https://aws.amazon.com/blogs/aws/dynamodb-update-json-and-more/) 

# Trabalhar com o Amazon EC2
<a name="ec2-apis-intro"></a>

O AWS SDK para .NET suporta o [Amazon EC2](https://docs.aws.amazon.com/ec2/), que é um serviço web que fornece capacidade de computação redimensionável. Você usa essa capacidade de computação para criar e hospedar seus sistemas de software.

## APIs
<a name="w2aac19c15c21b5"></a>

 AWS SDK para .NET Ele fornece APIs para clientes do Amazon EC2. As APIs permitem que você trabalhe com recursos do EC2, como grupos de segurança e pares de chaves. As APIs também permitem que você controle as instâncias do Amazon EC2. Esta seção contém um pequeno número de exemplos que mostram os padrões que você pode seguir ao trabalhar com eles APIs. Para ver o conjunto completo de APIs, consulte a [Referência da AWS SDK para .NET API](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/) (e vá até “Amazon.ec2").

O Amazon EC2 APIs é fornecido pelo [AWSSDK NuGet pacote.EC2](https://www.nuget.org/packages/AWSSDK.EC2).

## Pré-requisitos
<a name="w2aac19c15c21b7"></a>

Antes de começar, verifique se você [configurou seu ambiente](net-dg-config.md) e [configurou seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

## Sobre os exemplos
<a name="ec2-apis-intro-about"></a>

Os exemplos nesta seção mostram como trabalhar com clientes do Amazon EC2 e como gerenciar as instâncias do Amazon EC2.

Os [tutoriais de instâncias spot do EC2](how-to-spot-instances.md) mostram como solicitar instâncias spot do Amazon EC2. As instâncias spot permitem que você acesse a capacidade do EC2 não utilizada por um valor mais baixo que o preço sob demanda.

**Topics**
+ [APIs](#w2aac19c15c21b5)
+ [Pré-requisitos](#w2aac19c15c21b7)
+ [Sobre os exemplos](#ec2-apis-intro-about)
+ [Grupos de segurança](security-groups.md)
+ [Pares de chaves](key-pairs.md)
+ [Regiões e zonas de disponibilidade](using-regions-and-availability-zones.md)
+ [Instâncias do EC2](how-to-ec2.md)
+ [Tutorial: instância spot](how-to-spot-instances.md)

# Como trabalhar com grupos de segurança no Amazon EC2
<a name="security-groups"></a>

No Amazon EC2, um *grupo de segurança* atua como um firewall virtual que controla o tráfego de rede para uma ou mais instâncias do EC2. Por padrão, o EC2 associa as instâncias a um grupo de segurança que não permite tráfego de entrada. Você pode criar um security group que permita que as instâncias do EC2 aceitem um determinado tráfego. Por exemplo, se você precisar se conectar a uma instância do EC2 em Windows, deverá configurar o security group para permitir tráfego RDP.

Para ler mais sobre grupos de segurança, consulte [Grupos de segurança do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-security-groups.html) no [Guia de usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

**Atenção**  
O EC2-Classic foi removido em 15 de agosto de 2022. É recomendável migrar do EC2-Classic para uma VPC. Para obter mais informações, consulte a postagem do blog [EC2-Classic Networking is Retiring – Here's How to Prepare](https://aws.amazon.com/blogs/aws/ec2-classic-is-retiring-heres-how-to-prepare/).

Para obter informações sobre os pré-requisitos APIs e, consulte a seção principal (). [Trabalhar com o Amazon EC2](ec2-apis-intro.md)

**Topics**
+ [Como enumerar grupos de segurança](enumerate-security-groups.md)
+ [Como criar grupos de segurança](creating-security-group.md)
+ [Como atualizar Grupos de Segurança](authorize-ingress.md)

# Como enumerar grupos de segurança
<a name="enumerate-security-groups"></a>

Este exemplo mostra como usar o AWS SDK para .NET para enumerar grupos de segurança. Se você fornecer um [Amazon Private Cloud](https://docs.aws.amazon.com/vpc/latest/userguide/) ID, o aplicativo enumera os grupos de segurança dessa VPC específica. Caso contrário, o aplicativo exibirá apenas uma lista de todos os grupos de segurança disponíveis.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#enum-sec-groups-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Como enumerar seus grupos de segurança](#enum-sec-groups-enum)
+ [Código completo](#enum-sec-groups-complete-code)
+ [Considerações adicionais](#enum-sec-groups-additional)

## Como enumerar seus grupos de segurança
<a name="enum-sec-groups-enum"></a>

O snippet a seguir enumera seus grupos de segurança. Ele enumera todos os grupos ou os grupos de uma VPC específica, se houver um.

O exemplo [no final deste tópico](#enum-sec-groups-complete-code) mostra o snippet em uso.

```
    //
    // Method to enumerate the security groups
    private static async Task EnumerateGroups(IAmazonEC2 ec2Client, string vpcID)
    {
      // A request object, in case we need it.
      var request = new DescribeSecurityGroupsRequest();

      // Put together the properties, if needed
      if(!string.IsNullOrEmpty(vpcID))
      {
        // We have a VPC ID. Find the security groups for just that VPC.
        Console.WriteLine($"\nGetting security groups for VPC {vpcID}...\n");
        request.Filters.Add(new Filter
        {
          Name = "vpc-id",
          Values = new List<string>() { vpcID }
        });
      }

      // Get the list of security groups
      DescribeSecurityGroupsResponse response =
        await ec2Client.DescribeSecurityGroupsAsync(request);

      // Display the list of security groups.
      foreach (SecurityGroup item in response.SecurityGroups)
      {
        Console.WriteLine("Security group: " + item.GroupId);
        Console.WriteLine("\tGroupId: " + item.GroupId);
        Console.WriteLine("\tGroupName: " + item.GroupName);
        Console.WriteLine("\tVpcId: " + item.VpcId);
        Console.WriteLine();
      }
    }
```

## Código completo
<a name="enum-sec-groups-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c21c13c13c15b5b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [DescribeSecurityGroupsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsRequest.html)

  Classe [DescribeSecurityGroupsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsResponse.html)

  Classe [Filter](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TFilter.html)

  Classe [SecurityGroup](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TSecurityGroup.html)

### O Código
<a name="w2aac19c15c21c13c13c15b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2EnumerateSecGroups
{
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line
       string vpcID = string.Empty;
      if(args.Length == 0)
      {
        Console.WriteLine("\nEC2EnumerateSecGroups [vpc_id]");
        Console.WriteLine("  vpc_id - The ID of the VPC for which you want to see security groups.");
        Console.WriteLine("\nSince you specified no arguments, showing all available security groups.");
      }
      else
      {
        vpcID = args[0];
      }

      if(vpcID.StartsWith("vpc-") || string.IsNullOrEmpty(vpcID))
      {
        // Create an EC2 client object
        var ec2Client = new AmazonEC2Client();

        // Enumerate the security groups
        await EnumerateGroups(ec2Client, vpcID);
      }
      else
      {
        Console.WriteLine("Could not find a valid VPC ID in the command-line arguments:");
        Console.WriteLine($"{args[0]}");
      }
    }


    //
    // Method to enumerate the security groups
    private static async Task EnumerateGroups(IAmazonEC2 ec2Client, string vpcID)
    {
      // A request object, in case we need it.
      var request = new DescribeSecurityGroupsRequest();

      // Put together the properties, if needed
      if(!string.IsNullOrEmpty(vpcID))
      {
        // We have a VPC ID. Find the security groups for just that VPC.
        Console.WriteLine($"\nGetting security groups for VPC {vpcID}...\n");
        request.Filters.Add(new Filter
        {
          Name = "vpc-id",
          Values = new List<string>() { vpcID }
        });
      }

      // Get the list of security groups
      DescribeSecurityGroupsResponse response =
        await ec2Client.DescribeSecurityGroupsAsync(request);

      // Display the list of security groups.
      foreach (SecurityGroup item in response.SecurityGroups)
      {
        Console.WriteLine("Security group: " + item.GroupId);
        Console.WriteLine("\tGroupId: " + item.GroupId);
        Console.WriteLine("\tGroupName: " + item.GroupName);
        Console.WriteLine("\tVpcId: " + item.VpcId);
        Console.WriteLine();
      }
    }
  }
}
```

## Considerações adicionais
<a name="enum-sec-groups-additional"></a>
+ Observe que, no caso da VPC, o filtro é construído com a parte `Name` do par nome-valor definida como “vpc-id”. Esse nome vem da descrição da `Filters` propriedade da [DescribeSecurityGroupsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsRequest.html)classe.
+ Para obter a lista completa dos seus grupos de segurança, você também pode usar [ DescribeSecurityGroupsAsync sem parâmetros](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/MEC2DescribeSecurityGroupsAsyncCancellationToken.html).
+ Você pode verificar os resultados consultando a lista de grupos de segurança no [console do Amazon EC2](https://console.aws.amazon.com/ec2/v2/home#SecurityGroups).

# Como criar grupos de segurança
<a name="creating-security-group"></a>

Este exemplo mostra como usar o AWS SDK para .NET para criar um grupo de segurança. Você pode fornecer o ID de uma VPC existente para criar um grupo de segurança para o EC2 em uma VPC. Se você não fornecer essa ID, o novo grupo de segurança será para o EC2-Classic se sua AWS conta suportar isso.

Se você não fornecer uma VPC ID e sua AWS conta não for compatível com o EC2-Classic, o novo grupo de segurança pertencerá à VPC padrão da sua conta.

**Atenção**  
O EC2-Classic foi removido em 15 de agosto de 2022. É recomendável migrar do EC2-Classic para uma VPC. Para acessar mais informações, consulte a postagem do blog [EC2-Classic Networking is Retiring - Here's How to Prepare](https://aws.amazon.com/blogs/aws/ec2-classic-is-retiring-heres-how-to-prepare/).

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#create-sec-groups-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Como encontrar grupos de segurança existentes](#create-sec-groups-find)
+ [Criar um grupo de segurança](#create-sec-groups-enum)
+ [Código completo](#create-sec-groups-complete-code)

## Como encontrar grupos de segurança existentes
<a name="create-sec-groups-find"></a>

O snippet a seguir pesquisa grupos de segurança existentes com o nome fornecido na VPC fornecida.

O exemplo [no final deste tópico](#create-sec-groups-complete-code) mostra o snippet em uso.

```
    //
    // Method to determine if a security group with the specified name
    // already exists in the VPC
    private static async Task<List<SecurityGroup>> FindSecurityGroups(
      IAmazonEC2 ec2Client, string groupName, string vpcID)
    {
      var request = new DescribeSecurityGroupsRequest();
      request.Filters.Add(new Filter{
        Name = "group-name",
        Values = new List<string>() { groupName }
      });
      if(!string.IsNullOrEmpty(vpcID))
        request.Filters.Add(new Filter{
          Name = "vpc-id",
          Values = new List<string>() { vpcID }
        });

      var response = await ec2Client.DescribeSecurityGroupsAsync(request);
      return response.SecurityGroups;
    }
```

## Criar um grupo de segurança
<a name="create-sec-groups-enum"></a>

O snippet a seguir cria um novo grupo de segurança se um grupo com esse nome não existir na VPC fornecida. Se nenhuma VPC for fornecida e existir um ou mais grupos com esse nome, o snippet apenas retornará a lista de grupos.

O exemplo [no final deste tópico](#create-sec-groups-complete-code) mostra o snippet em uso.

```
    //
    // Method to create a new security group (either EC2-Classic or EC2-VPC)
    // If vpcID is empty, the security group will be for EC2-Classic
    private static async Task<List<SecurityGroup>> CreateSecurityGroup(
      IAmazonEC2 ec2Client, string groupName, string vpcID)
    {
      // See if one or more security groups with that name
      // already exist in the given VPC. If so, return the list of them.
      var securityGroups = await FindSecurityGroups(ec2Client, groupName, vpcID);
      if (securityGroups.Count > 0)
      {
        Console.WriteLine(
          $"\nOne or more security groups with name {groupName} already exist.\n");
        return securityGroups;
      }

      // If the security group doesn't already exists, create it.
      var createRequest = new CreateSecurityGroupRequest{
        GroupName = groupName
      };
      if(string.IsNullOrEmpty(vpcID))
      {
        createRequest.Description = "My .NET example security group for EC2-Classic";
      }
      else
      {
        createRequest.VpcId = vpcID;
        createRequest.Description = "My .NET example security group for EC2-VPC";
      }
      CreateSecurityGroupResponse createResponse =
        await ec2Client.CreateSecurityGroupAsync(createRequest);

      // Return the new security group
      DescribeSecurityGroupsResponse describeResponse =
        await ec2Client.DescribeSecurityGroupsAsync(new DescribeSecurityGroupsRequest{
          GroupIds = new List<string>() { createResponse.GroupId }
        });
      return describeResponse.SecurityGroups;
    }
```

## Código completo
<a name="create-sec-groups-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c21c13c15c23b5b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [CreateSecurityGroupRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCreateSecurityGroupRequest.html)

  Classe [CreateSecurityGroupResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCreateSecurityGroupResponse.html)

  Classe [DescribeSecurityGroupsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsRequest.html)

  Classe [DescribeSecurityGroupsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSecurityGroupsResponse.html)

  Classe [Filter ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TFilter.html)

  Classe [SecurityGroup](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TSecurityGroup.html)

### O código
<a name="w2aac19c15c21c13c15c23b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2CreateSecGroup
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to create a security group
  class Program
  {
    private const int MaxArgs = 2;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }
      if(parsedArgs.Count > MaxArgs)
        CommandLine.ErrorExit("\nThe number of command-line arguments is incorrect." +
          "\nRun the command with no arguments to see help.");

      // Get the application arguments from the parsed list
      var groupName = CommandLine.GetArgument(parsedArgs, null, "-g", "--group-name");
      var vpcID = CommandLine.GetArgument(parsedArgs, null, "-v", "--vpc-id");
      if(string.IsNullOrEmpty(groupName))
        CommandLine.ErrorExit("\nYou must supply a name for the new group." +
          "\nRun the command with no arguments to see help.");
      if(!string.IsNullOrEmpty(vpcID) && !vpcID.StartsWith("vpc-"))
        CommandLine.ErrorExit($"\nNot a valid VPC ID: {vpcID}");

      // groupName has a value and vpcID either has a value or is null (which is fine)
      // Create the new security group and display information about it
      var securityGroups =
        await CreateSecurityGroup(new AmazonEC2Client(), groupName, vpcID);
      Console.WriteLine("Information about the security group(s):");
      foreach(var group in securityGroups)
      {
        Console.WriteLine($"\nGroupName: {group.GroupName}");
        Console.WriteLine($"GroupId: {group.GroupId}");
        Console.WriteLine($"Description: {group.Description}");
        Console.WriteLine($"VpcId (if any): {group.VpcId}");
      }
    }


    //
    // Method to create a new security group (either EC2-Classic or EC2-VPC)
    // If vpcID is empty, the security group will be for EC2-Classic
    private static async Task<List<SecurityGroup>> CreateSecurityGroup(
      IAmazonEC2 ec2Client, string groupName, string vpcID)
    {
      // See if one or more security groups with that name
      // already exist in the given VPC. If so, return the list of them.
      var securityGroups = await FindSecurityGroups(ec2Client, groupName, vpcID);
      if (securityGroups.Count > 0)
      {
        Console.WriteLine(
          $"\nOne or more security groups with name {groupName} already exist.\n");
        return securityGroups;
      }

      // If the security group doesn't already exists, create it.
      var createRequest = new CreateSecurityGroupRequest{
        GroupName = groupName
      };
      if(string.IsNullOrEmpty(vpcID))
      {
        createRequest.Description = "Security group for .NET code example (no VPC specified)";
      }
      else
      {
        createRequest.VpcId = vpcID;
        createRequest.Description = "Security group for .NET code example (VPC: " + vpcID + ")";
      }
      CreateSecurityGroupResponse createResponse =
        await ec2Client.CreateSecurityGroupAsync(createRequest);

      // Return the new security group
      DescribeSecurityGroupsResponse describeResponse =
        await ec2Client.DescribeSecurityGroupsAsync(new DescribeSecurityGroupsRequest{
          GroupIds = new List<string>() { createResponse.GroupId }
        });
      return describeResponse.SecurityGroups;
    }


    //
    // Method to determine if a security group with the specified name
    // already exists in the VPC
    private static async Task<List<SecurityGroup>> FindSecurityGroups(
      IAmazonEC2 ec2Client, string groupName, string vpcID)
    {
      var request = new DescribeSecurityGroupsRequest();
      request.Filters.Add(new Filter{
        Name = "group-name",
        Values = new List<string>() { groupName }
      });
      if(!string.IsNullOrEmpty(vpcID))
        request.Filters.Add(new Filter{
          Name = "vpc-id",
          Values = new List<string>() { vpcID }
        });

      var response = await ec2Client.DescribeSecurityGroupsAsync(request);
      return response.SecurityGroups;
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2CreateSecGroup -g <group-name> [-v <vpc-id>]" +
        "\n  -g, --group-name: The name you would like the new security group to have." +
        "\n  -v, --vpc-id: The ID of a VPC to which the new security group will belong." +
        "\n     If vpc-id isn't present, the security group will be" +
        "\n     for EC2-Classic (if your AWS account supports this)" +
        "\n     or will use the default VCP for EC2-VPC.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

# Como atualizar Grupos de Segurança
<a name="authorize-ingress"></a>

Este exemplo mostra como usar o AWS SDK para .NET para adicionar uma regra a um grupo de segurança. Em particular, o exemplo adiciona uma regra para permitir tráfego de entrada em uma determinada porta TCP, que pode ser usada, por exemplo, para conexões remotas com uma instância do EC2. O aplicativo usa a ID de um grupo de segurança existente, um endereço IP (ou intervalo de endereços) no formato CIDR e, opcionalmente, um número de porta TCP. Em seguida, ele adiciona uma regra de entrada ao grupo de segurança fornecido.

**nota**  
Para usar esse exemplo, você precisa de um endereço IP (ou intervalo de endereços) no formato CIDR. Consulte **Considerações adicionais** no final deste tópico para obter o endereço IP do seu computador local.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#authorize-ingress-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Como adicionar uma regra de entrada](#authorize-ingress-add-rule)
+ [Código completo](#authorize-ingress-complete-code)
+ [Considerações adicionais](#authorize-ingress-additional)

## Como adicionar uma regra de entrada
<a name="authorize-ingress-add-rule"></a>

O trecho a seguir adiciona uma regra de entrada a um grupo de segurança para um determinado endereço IP (ou intervalo) e porta TCP.

O exemplo [no final deste tópico](#authorize-ingress-complete-code) mostra o snippet em uso.

```
    //
    // Method that adds a TCP ingress rule to a security group
    private static async Task AddIngressRule(
      IAmazonEC2 eC2Client, string groupID, string ipAddress, int port)
    {
      // Create an object to hold the request information for the rule.
      // It uses an IpPermission object to hold the IP information for the rule.
      var ingressRequest = new AuthorizeSecurityGroupIngressRequest{
        GroupId = groupID};
      ingressRequest.IpPermissions.Add(new IpPermission{
        IpProtocol = "tcp",
        FromPort = port,
        ToPort = port,
        Ipv4Ranges = new List<IpRange>() { new IpRange { CidrIp = ipAddress } }
      });

      // Create the inbound rule for the security group
      AuthorizeSecurityGroupIngressResponse responseIngress =
        await eC2Client.AuthorizeSecurityGroupIngressAsync(ingressRequest);
      Console.WriteLine($"\nNew RDP rule was written in {groupID} for {ipAddress}.");
      Console.WriteLine($"Result: {responseIngress.HttpStatusCode}");
    }
```

## Código completo
<a name="authorize-ingress-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c21c13c17c17b5b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [AuthorizeSecurityGroupIngressRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TAuthorizeSecurityGroupIngressRequest.html)

  Classe [AuthorizeSecurityGroupIngressResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TAuthorizeSecurityGroupIngressResponse.html)

  Classe [IpPermission](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TIpPermission.html)

  Classe [IpRange](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TIpRange.html)

### O código
<a name="w2aac19c15c21c13c17c17b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2AddRuleForRDP
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to add a rule that allows inbound traffic on TCP a port
  class Program
  {
    private const int DefaultPort = 3389;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      var groupID = CommandLine.GetArgument(parsedArgs, null, "-g", "--group-id");
      var ipAddress = CommandLine.GetArgument(parsedArgs, null, "-i", "--ip-address");
      var portStr = CommandLine.GetArgument(parsedArgs, DefaultPort.ToString(), "-p", "--port");
      if(string.IsNullOrEmpty(ipAddress))
        CommandLine.ErrorExit("\nYou must supply an IP address in CIDR format.");
      if(string.IsNullOrEmpty(groupID) || !groupID.StartsWith("sg-"))
        CommandLine.ErrorExit("\nThe ID for a security group is missing or incorrect.");
      if(int.Parse(portStr) == 0)
        CommandLine.ErrorExit($"\nThe given TCP port number, {portStr}, isn't allowed.");

      // Add a rule to the given security group that allows
      // inbound traffic on a TCP port
      await AddIngressRule(
        new AmazonEC2Client(), groupID, ipAddress, int.Parse(portStr));
    }


    //
    // Method that adds a TCP ingress rule to a security group
    private static async Task AddIngressRule(
      IAmazonEC2 eC2Client, string groupID, string ipAddress, int port)
    {
      // Create an object to hold the request information for the rule.
      // It uses an IpPermission object to hold the IP information for the rule.
      var ingressRequest = new AuthorizeSecurityGroupIngressRequest{
        GroupId = groupID};
      ingressRequest.IpPermissions.Add(new IpPermission{
        IpProtocol = "tcp",
        FromPort = port,
        ToPort = port,
        Ipv4Ranges = new List<IpRange>() { new IpRange { CidrIp = ipAddress } }
      });

      // Create the inbound rule for the security group
      AuthorizeSecurityGroupIngressResponse responseIngress =
        await eC2Client.AuthorizeSecurityGroupIngressAsync(ingressRequest);
      Console.WriteLine($"\nNew RDP rule was written in {groupID} for {ipAddress}.");
      Console.WriteLine($"Result: {responseIngress.HttpStatusCode}");
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2AddRuleForRDP -g <group-id> -i <ip-address> [-p <port>]" +
        "\n  -g, --group-id: The ID of the security group to which you want to add the inbound rule." +
        "\n  -i, --ip-address: An IP address or address range in CIDR format." +
        "\n  -p, --port: The TCP port number. Defaults to 3389.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## Considerações adicionais
<a name="authorize-ingress-additional"></a>
+ Se você não fornecer um número de porta, o aplicativo usará como padrão a porta 3389. Essa é a porta do Windows RDP, que permite que você se conecte a uma instância do EC2 executando o Windows. Se você iniciar uma instância EC2 do Linux, use a porta TCP 22 (SSH).
+ Observe que o exemplo é definido como `IpProtocol` “tcp”. Os valores de `IpProtocol` podem ser encontrados na descrição da `IpProtocol` propriedade da [IpPermission](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TIpPermission.html)classe.
+ Talvez você queira o endereço IP do computador local ao usar este exemplo. A seguir estão algumas das maneiras pelas quais você pode obter o endereço.
  + Se seu computador local (do qual você se conectará à instância do EC2) tiver um endereço IP público estático, você poderá usar um serviço para obter esse endereço. Um desses serviços é o [http://checkip.amazonaws.com/](http://checkip.amazonaws.com/). Para ler mais sobre a autorização de tráfego de entrada, consulte [Regras de grupos de segurança](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/working-with-security-groups.html#adding-security-group-rule) e [Regras de grupo de segurança para diferentes casos de uso](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-rules-reference.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).
  + Outra maneira de obter o endereço IP do seu computador local é usar o [console do Amazon EC2](https://console.aws.amazon.com/ec2/v2/home#SecurityGroups).

    Selecione um dos seus grupos de segurança, selecione a guia **Regras de entrada** e escolha **Editar regras de entrada**. Em uma regra de entrada, abra o menu suspenso na coluna **Fonte** e escolha **Meu IP** para ver o endereço IP do seu computador local no formato CIDR. Certifique-se de **cancelar** a operação.
+ Você pode verificar os resultados desse exemplo examinando a lista de grupos de segurança no [console do Amazon EC2](https://console.aws.amazon.com/ec2/v2/home#SecurityGroups).

# Trabalhar com pares de chaves do Amazon EC2
<a name="key-pairs"></a>

O Amazon EC2 utiliza criptografia de chave pública para criptografar e descriptografar as informações de login. A criptografia de chave pública usa uma chave pública para criptografar dados e, em seguida, o destinatário usa a chave privada para descriptografar os dados. As chaves pública e privada são conhecidas como par de chaves. Se quiser fazer login em uma instância do EC2, você deve especificar um par de chaves ao iniciá-la e, em seguida, fornecer a chave privada do par ao se conectar a ela.

Ao iniciar uma instância do EC2, é possível criar um par de chave para ela ou usar um que já foi usado ao iniciar outras instâncias. Para ler mais sobre pares de chaves do Amazon EC2, consulte [Working with Amazon EC2 key pairs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

Para obter informações sobre os pré-requisitos APIs e, consulte a seção principal (). [Trabalhar com o Amazon EC2](ec2-apis-intro.md)

**Topics**
+ [Criar e exibir pares de chaves](create-save-key-pair.md)
+ [Excluir pares de chaves](delete-key-pairs.md)

# Criar e exibir pares de chaves
<a name="create-save-key-pair"></a>

Este exemplo mostra como usar o AWS SDK para .NET para criar um par de chaves. O aplicativo usa o nome do novo par de chaves e o nome de um arquivo PEM (com a extensão “.pem”). Ele cria o par de chaves, grava a chave privada no arquivo PEM e exibe todos os pares de chaves disponíveis. Se você não fornecer argumentos de linha de comando, o aplicativo apenas exibirá todos os pares de chaves disponíveis.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#create-save-key-pair-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Criar o par de chaves](#create-save-key-pair-create)
+ [Exibir pares de chaves disponíveis](#create-save-key-pair-display)
+ [Código completo](#create-save-key-pair-complete-code)
+ [Considerações adicionais](#create-save-key-pair-additional)

## Criar o par de chaves
<a name="create-save-key-pair-create"></a>

O snippet a seguir cria um par de chaves e, em seguida, armazena a chave privada no arquivo PEM fornecido.

O exemplo [no final deste tópico](#create-save-key-pair-complete-code) mostra o snippet em uso.

```
    //
    // Method to create a key pair and save the key material in a PEM file
    private static async Task CreateKeyPair(
      IAmazonEC2 ec2Client, string keyPairName, string pemFileName)
    {
      // Create the key pair
      CreateKeyPairResponse response =
        await ec2Client.CreateKeyPairAsync(new CreateKeyPairRequest{
          KeyName = keyPairName
        });
      Console.WriteLine($"\nCreated new key pair: {response.KeyPair.KeyName}");

      // Save the private key in a PEM file
      using (var s = new FileStream(pemFileName, FileMode.Create))
      using (var writer = new StreamWriter(s))
      {
        writer.WriteLine(response.KeyPair.KeyMaterial);
      }
    }
```

## Exibir pares de chaves disponíveis
<a name="create-save-key-pair-display"></a>

O snippet a seguir exibe uma lista dos pares de chaves disponíveis.

O exemplo [no final deste tópico](#create-save-key-pair-complete-code) mostra o snippet em uso.

```
    //
    // Method to show the key pairs that are available
    private static async Task EnumerateKeyPairs(IAmazonEC2 ec2Client)
    {
      DescribeKeyPairsResponse response = await ec2Client.DescribeKeyPairsAsync();
      Console.WriteLine("Available key pairs:");
      foreach (KeyPairInfo item in response.KeyPairs)
        Console.WriteLine($"  {item.KeyName}");
    }
```

## Código completo
<a name="create-save-key-pair-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c21c15c11c19b5b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [CreateKeyPairRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCreateKeyPairRequest.html)

  Classe [CreateKeyPairResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCreateKeyPairResponse.html)

  Classe [DescribeKeyPairsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeKeyPairsResponse.html)

  Classe [KeyPairInfo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TKeyPairInfo.html)

### O código
<a name="w2aac19c15c21c15c11c19b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.IO;
using Amazon.EC2;
using Amazon.EC2.Model;
using System.Collections.Generic;

namespace EC2CreateKeyPair
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to create and store a key pair
  class Program
  {
    static async Task Main(string[] args)
    {
      // Create the EC2 client
      var ec2Client = new AmazonEC2Client();

      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        // In the case of no command-line arguments,
        // just show help and the existing key pairs
        PrintHelp();
        Console.WriteLine("\nNo arguments specified.");
        Console.Write(
          "Do you want to see a list of the existing key pairs? ((y) or n): ");
        string response = Console.ReadLine();
        if((string.IsNullOrEmpty(response)) || (response.ToLower() == "y"))
          await EnumerateKeyPairs(ec2Client);
        return;
      }

      // Get the application arguments from the parsed list
      string keyPairName =
        CommandLine.GetArgument(parsedArgs, null, "-k", "--keypair-name");
      string pemFileName =
        CommandLine.GetArgument(parsedArgs, null, "-p", "--pem-filename");
      if(string.IsNullOrEmpty(keyPairName))
        CommandLine.ErrorExit("\nNo key pair name specified." +
          "\nRun the command with no arguments to see help.");
      if(string.IsNullOrEmpty(pemFileName) || !pemFileName.EndsWith(".pem"))
        CommandLine.ErrorExit("\nThe PEM filename is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create the key pair
      await CreateKeyPair(ec2Client, keyPairName, pemFileName);
      await EnumerateKeyPairs(ec2Client);
    }


    //
    // Method to create a key pair and save the key material in a PEM file
    private static async Task CreateKeyPair(
      IAmazonEC2 ec2Client, string keyPairName, string pemFileName)
    {
      // Create the key pair
      CreateKeyPairResponse response =
        await ec2Client.CreateKeyPairAsync(new CreateKeyPairRequest{
          KeyName = keyPairName
        });
      Console.WriteLine($"\nCreated new key pair: {response.KeyPair.KeyName}");

      // Save the private key in a PEM file
      using (var s = new FileStream(pemFileName, FileMode.Create))
      using (var writer = new StreamWriter(s))
      {
        writer.WriteLine(response.KeyPair.KeyMaterial);
      }
    }


    //
    // Method to show the key pairs that are available
    private static async Task EnumerateKeyPairs(IAmazonEC2 ec2Client)
    {
      DescribeKeyPairsResponse response = await ec2Client.DescribeKeyPairsAsync();
      Console.WriteLine("Available key pairs:");
      foreach (KeyPairInfo item in response.KeyPairs)
        Console.WriteLine($"  {item.KeyName}");
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2CreateKeyPair -k <keypair-name> -p <pem-filename>" +
        "\n  -k, --keypair-name: The name you want to assign to the key pair." +
        "\n  -p, --pem-filename: The name of the PEM file to create, with a \".pem\" extension.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## Considerações adicionais
<a name="create-save-key-pair-additional"></a>
+ Depois de executar o exemplo, você pode ver o novo par de chaves no [console do Amazon EC2](https://console.aws.amazon.com/ec2/#KeyPairs).
+ Ao criar um par de chaves, você deve salvar a chave privada que é retornada, pois não vai poder recuperá-la depois.

# Excluir pares de chaves
<a name="delete-key-pairs"></a>

Este exemplo mostra como usar o AWS SDK para .NET para excluir um par de chaves. O aplicativo usa o nome de um par de chave. Ele exclui o par de chave e, em seguida, exibe todos os pares de chaves disponíveis. Se você não fornecer argumentos de linha de comando, o aplicativo apenas exibirá todos os pares de chaves disponíveis.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#delete-key-pairs-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Criar pares de chaves](#delete-key-pairs-create)
+ [Exibir pares de chaves disponíveis](#delete-key-pairs-display)
+ [Código completo](#delete-key-pairs-complete-code)

## Criar pares de chaves
<a name="delete-key-pairs-create"></a>

O snippet a seguir exclui um par de chave.

O exemplo [no final deste tópico](#delete-key-pairs-complete-code) mostra o snippet em uso.

```
    //
    // Method to delete a key pair
    private static async Task DeleteKeyPair(IAmazonEC2 ec2Client, string keyName)
    {
      await ec2Client.DeleteKeyPairAsync(new DeleteKeyPairRequest{
        KeyName = keyName});
      Console.WriteLine($"\nKey pair {keyName} has been deleted (if it existed).");
    }
```

## Exibir pares de chaves disponíveis
<a name="delete-key-pairs-display"></a>

O snippet a seguir exibe uma lista dos pares de chaves disponíveis.

O exemplo [no final deste tópico](#delete-key-pairs-complete-code) mostra o snippet em uso.

```
    //
    // Method to show the key pairs that are available
    private static async Task EnumerateKeyPairs(IAmazonEC2 ec2Client)
    {
      DescribeKeyPairsResponse response = await ec2Client.DescribeKeyPairsAsync();
      Console.WriteLine("Available key pairs:");
      foreach (KeyPairInfo item in response.KeyPairs)
        Console.WriteLine($"  {item.KeyName}");
    }
```

## Código completo
<a name="delete-key-pairs-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c21c15c13c19b5b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [https://docs.aws.amazon.com/sdkfornet/v4/apidocs/](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/)

  Classe [DescribeKeyPairsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeKeyPairsResponse.html)

  Classe [KeyPairInfo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TKeyPairInfo.html)

### O código
<a name="w2aac19c15c21c15c13c19b7b1"></a>

```
using System;
using System.Threading.Tasks;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2DeleteKeyPair
{
  class Program
  {
    static async Task Main(string[] args)
    {
      // Create the EC2 client
      var ec2Client = new AmazonEC2Client();

      if(args.Length == 1)
      {
        // Delete a key pair (if it exists)
        await DeleteKeyPair(ec2Client, args[0]);

        // Display the key pairs that are left
        await EnumerateKeyPairs(ec2Client);
      }
      else
      {
        Console.WriteLine("\nUsage: EC2DeleteKeyPair keypair-name");
        Console.WriteLine("  keypair-name - The name of the key pair you want to delete.");
        Console.WriteLine("\nNo arguments specified.");
        Console.Write(
          "Do you want to see a list of the existing key pairs? ((y) or n): ");
        string response = Console.ReadLine();
        if((string.IsNullOrEmpty(response)) || (response.ToLower() == "y"))
          await EnumerateKeyPairs(ec2Client);
      }
    }


    //
    // Method to delete a key pair
    private static async Task DeleteKeyPair(IAmazonEC2 ec2Client, string keyName)
    {
      await ec2Client.DeleteKeyPairAsync(new DeleteKeyPairRequest{
        KeyName = keyName});
      Console.WriteLine($"\nKey pair {keyName} has been deleted (if it existed).");
    }


    //
    // Method to show the key pairs that are available
    private static async Task EnumerateKeyPairs(IAmazonEC2 ec2Client)
    {
      DescribeKeyPairsResponse response = await ec2Client.DescribeKeyPairsAsync();
      Console.WriteLine("Available key pairs:");
      foreach (KeyPairInfo item in response.KeyPairs)
        Console.WriteLine($"  {item.KeyName}");
    }
  }
}
```

# Consulte regiões e zonas de disponibilidade (AZs) no Amazon EC2
<a name="using-regions-and-availability-zones"></a>

O Amazon EC2 está hospedado em vários locais do mundo. Esses locais são compostos por regiões da e zonas de disponibilidade. Cada região é uma área geográfica separada, com vários locais isolados, conhecidos como zonas de disponibilidade.

Para ler mais sobre regiões e zonas de disponibilidade, consulte [Regiões e zonas de disponibilidade](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

Este exemplo mostra como usar o AWS SDK para .NET para obter detalhes sobre as regiões e zonas de disponibilidade relacionadas a um cliente EC2. O aplicativo exibe listas das regiões e zonas de disponibilidade disponíveis para um cliente EC2.

## Referências do SDK
<a name="w2aac19c15c21c17b9b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [DescribeAvailabilityZonesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeAvailabilityZonesResponse.html)

  Classe [DescribeRegionsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeRegionsResponse.html)

  Classe [AvailabilityZone](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TAvailabilityZone.html)

  Classe [Region](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRegion.html)

```
using System;
using System.Threading.Tasks;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2RegionsAndZones
{
  class Program
  {
    static async Task Main(string[] args)
    {
      Console.WriteLine(
        "Finding the Regions and Availability Zones available to an EC2 client...");

      // Create the EC2 client
      var ec2Client = new AmazonEC2Client();

      // Display the Regions and Availability Zones
      await DescribeRegions(ec2Client);
      await DescribeAvailabilityZones(ec2Client);
    }


    //
    // Method to display Regions
    private static async Task DescribeRegions(IAmazonEC2 ec2Client)
    {
      Console.WriteLine("\nRegions that are enabled for the EC2 client:");
      DescribeRegionsResponse response = await ec2Client.DescribeRegionsAsync();
      foreach (Region region in response.Regions)
        Console.WriteLine(region.RegionName);
    }


    //
    // Method to display Availability Zones
    private static async Task DescribeAvailabilityZones(IAmazonEC2 ec2Client)
    {
      Console.WriteLine("\nAvailability Zones for the EC2 client's region:");
      DescribeAvailabilityZonesResponse response =
        await ec2Client.DescribeAvailabilityZonesAsync();
      foreach (AvailabilityZone az in response.AvailabilityZones)
        Console.WriteLine(az.ZoneName);
    }
  }
}
```

# Trabalhar com as instâncias do Amazon EC2
<a name="how-to-ec2"></a>

Você pode usar o AWS SDK para .NET para controlar instâncias do Amazon EC2 com operações como criar, iniciar e encerrar. Os tópicos nesta seção fornecem alguns exemplos de como fazer isso. Para ler mais sobre instâncias do EC2, consulte as [Instâncias do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Instances.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

Para obter informações sobre os pré-requisitos APIs e, consulte a seção principal (). [Trabalhar com o Amazon EC2](ec2-apis-intro.md)

**Topics**
+ [Iniciar uma instância do EC2](run-instance.md)
+ [Encerramento de uma instância do EC2](terminate-instance.md)

# Iniciar uma instância do Amazon EC2
<a name="run-instance"></a>

Este exemplo mostra como usar o AWS SDK para .NET para iniciar uma ou mais instâncias do Amazon EC2 configuradas de forma idêntica a partir da mesma Amazon Machine Image (AMI). Ao usar [várias entradas](#run-instance-gather) que você fornece, o aplicativo executa uma instância do EC2 e monitora a instância até que ela saia do estado “Pendente”.

Quando a instância do EC2 estiver em execução, será possível se conectar a ela remotamente, conforme descrito em [(opcional) Conecte-se à instância](#connect-to-instance).

**Atenção**  
O EC2-Classic foi removido em 15 de agosto de 2022. É recomendável migrar do EC2-Classic para uma VPC. Para acessar mais informações, consulte a postagem do blog [EC2-Classic Networking is Retiring - Here's How to Prepare](https://aws.amazon.com/blogs/aws/ec2-classic-is-retiring-heres-how-to-prepare/).

As seções a seguir fornecem snippets e outras informações para este exemplo. O [código completo do exemplo](#run-instance-complete-code) é mostrado após os snippets e pode ser criado e executado como está.

**Topics**
+ [Colete o que você precisa](#run-instance-gather)
+ [Iniciar uma instância](#run-instance-launch)
+ [Monitorar instância](#run-instance-monitor)
+ [Código completo](#run-instance-complete-code)
+ [Considerações adicionais](#run-instance-additional)
+ [(opcional) Conecte-se à instância](#connect-to-instance)
+ [Limpeza](#run-instance-cleanup)

## Colete o que você precisa
<a name="run-instance-gather"></a>

Para iniciar uma instância do EC2, você precisará de várias coisas.
+ Uma [VPC](https://docs.aws.amazon.com/vpc/latest/userguide/) onde a instância será iniciada. Se for uma instância do Windows e você estiver se conectando a ela por meio de RDP, a VPC provavelmente precisará de um gateway da Internet anexado a ela, bem como uma entrada para o gateway de Internet na tabela de rotas. Para obter mais informações, consulte [Gateways da Internet](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html) no *Guia do usuário da Amazon VPC*.
+ O ID da sub-rede na qual a instância será iniciada. Uma maneira fácil de encontrar ou criar isso é fazer login no [console da Amazon VPC](https://console.aws.amazon.com/vpc/home#subnets), mas você também pode obtê-lo programaticamente usando os métodos e. [CreateSubnetAsync[DescribeSubnetsAsync](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/MEC2DescribeSubnetsAsyncDescribeSubnetsRequestCancellationToken.html)](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/MEC2CreateSubnetAsyncCreateSubnetRequestCancellationToken.html)
**nota**  
Se você não fornecer esse parâmetro, a nova instância será executada na VPC padrão da conta.
+ O ID de um grupo de segurança existente que pertence à VPC em que a instância será iniciada. Para obter mais informações, consulte [Como trabalhar com grupos de segurança no Amazon EC2](security-groups.md).
+ Se você quiser se conectar à nova instância, o grupo de segurança mencionado anteriormente deve ter uma regra de entrada apropriada que permita tráfego SSH na porta 22 (instância Linux) ou tráfego RDP na porta 3389 (instância do Windows). Para obter informações sobre como fazer isso, consulte [Como atualizar Grupos de Segurança](authorize-ingress.md), inclusive o [Considerações adicionais](authorize-ingress.md#authorize-ingress-additional) próximo ao final desse tópico.
+ A imagem de máquina da Amazon (AMI) que será usada para criar a instância. Para obter informações sobre isso AMIs, consulte [Amazon Machine Images (AMIs)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) no Guia do [usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/). Em particular, consulte [Encontre uma AMI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html) e [compartilhe AMIs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharing-amis.html).
+ O nome de um par de chave do EC2 existente, que é usado para se conectar à nova instância. Para obter mais informações, consulte [Trabalhar com pares de chaves do Amazon EC2](key-pairs.md).
+ O nome do arquivo PEM que contém a chave privada do par de chave EC2 mencionado anteriormente. O arquivo PEM é usado quando você se [conecta remotamente](#connect-to-instance) à instância.

## Iniciar uma instância
<a name="run-instance-launch"></a>

O seguinte snippet inicia uma instância do EC2.

Os exemplos [no final deste tópico](#run-instance-complete-code) mostram o snippet em uso.

```
    //
    // Method to launch the instances
    // Returns a list with the launched instance IDs
    private static async Task<List<string>> LaunchInstances(
      IAmazonEC2 ec2Client, RunInstancesRequest requestLaunch)
    {
      var instanceIds = new List<string>();
      RunInstancesResponse responseLaunch =
        await ec2Client.RunInstancesAsync(requestLaunch);

      Console.WriteLine("\nNew instances have been created.");
      foreach (Instance item in responseLaunch.Reservation.Instances)
      {
        instanceIds.Add(item.InstanceId);
        Console.WriteLine($"  New instance: {item.InstanceId}");
      }

      return instanceIds;
    }
```

## Monitorar instância
<a name="run-instance-monitor"></a>

O snippet a seguir monitora a instância até que ela saia do estado “Pendente”.

Os exemplos [no final deste tópico](#run-instance-complete-code) mostram o snippet em uso.

Consulte a [InstanceState](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceState.html)classe para ver os valores válidos da `Instance.State.Code` propriedade.

```
    //
    // Method to wait until the instances are running (or at least not pending)
    private static async Task CheckState(IAmazonEC2 ec2Client, List<string> instanceIds)
    {
      Console.WriteLine(
        "\nWaiting for the instances to start." +
        "\nPress any key to stop waiting. (Response might be slightly delayed.)");

      int numberRunning;
      DescribeInstancesResponse responseDescribe;
      var requestDescribe = new DescribeInstancesRequest{
        InstanceIds = instanceIds};

      // Check every couple of seconds
      int wait = 2000;
      while(true)
      {
        // Get and check the status for each of the instances to see if it's past pending.
        // Once all instances are past pending, break out.
        // (For this example, we are assuming that there is only one reservation.)
        Console.Write(".");
        numberRunning = 0;
        responseDescribe = await ec2Client.DescribeInstancesAsync(requestDescribe);
        foreach(Instance i in responseDescribe.Reservations[0].Instances)
        {
          // Check the lower byte of State.Code property
          // Code == 0 is the pending state
          if((i.State.Code & 255) > 0) numberRunning++;
        }
        if(numberRunning == responseDescribe.Reservations[0].Instances.Count)
          break;

        // Wait a bit and try again (unless the user wants to stop waiting)
        Thread.Sleep(wait);
        if(Console.KeyAvailable)
          break;
      }

      Console.WriteLine("\nNo more instances are pending.");
      foreach(Instance i in responseDescribe.Reservations[0].Instances)
      {
        Console.WriteLine($"For {i.InstanceId}:");
        Console.WriteLine($"  VPC ID: {i.VpcId}");
        Console.WriteLine($"  Instance state: {i.State.Name}");
        Console.WriteLine($"  Public IP address: {i.PublicIpAddress}");
        Console.WriteLine($"  Public DNS name: {i.PublicDnsName}");
        Console.WriteLine($"  Key pair name: {i.KeyName}");
      }
    }
```

## Código completo
<a name="run-instance-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c21c19b9c27b5b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)

  Classe [InstanceType](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceType.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [DescribeInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeInstancesRequest.html)

  Classe [DescribeInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeInstancesResponse.html)

  Classe [Instância](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstance.html)

  Classe [InstanceNetworkInterfaceSpecification](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceNetworkInterfaceSpecification.html)

  Classe [RunInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRunInstancesRequest.html)

  Classe [RunInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRunInstancesResponse.html)

### O código
<a name="w2aac19c15c21c19b9c27b7b1"></a>

```
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2LaunchInstance
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to launch an EC2 instance
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string groupID =
        CommandLine.GetArgument(parsedArgs, null, "-g", "--group-id");
      string ami =
        CommandLine.GetArgument(parsedArgs, null, "-a", "--ami-id");
      string keyPairName =
        CommandLine.GetArgument(parsedArgs, null, "-k", "--keypair-name");
      string subnetID =
        CommandLine.GetArgument(parsedArgs, null, "-s", "--subnet-id");
      if(   (string.IsNullOrEmpty(groupID) || !groupID.StartsWith("sg-"))
         || (string.IsNullOrEmpty(ami) || !ami.StartsWith("ami-"))
         || (string.IsNullOrEmpty(keyPairName))
         || (!string.IsNullOrEmpty(subnetID) && !subnetID.StartsWith("subnet-")))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create an EC2 client
      var ec2Client = new AmazonEC2Client();

      // Create an object with the necessary properties
      RunInstancesRequest request = GetRequestData(groupID, ami, keyPairName, subnetID);

      // Launch the instances and wait for them to start running
      var instanceIds = await LaunchInstances(ec2Client, request);
      await CheckState(ec2Client, instanceIds);
    }


    //
    // Method to put together the properties needed to launch the instance.
    private static RunInstancesRequest GetRequestData(
      string groupID, string ami, string keyPairName, string subnetID)
    {
      // Common properties
      var groupIDs = new List<string>() { groupID };
      var request = new RunInstancesRequest()
      {
        // The first three of these would be additional command-line arguments or similar.
        InstanceType = InstanceType.T1Micro,
        MinCount = 1,
        MaxCount = 1,
        ImageId = ami,
        KeyName = keyPairName
      };

      // Properties specifically for EC2 in a VPC.
      if(!string.IsNullOrEmpty(subnetID))
      {
        request.NetworkInterfaces =
          new List<InstanceNetworkInterfaceSpecification>() {
            new InstanceNetworkInterfaceSpecification() {
              DeviceIndex = 0,
              SubnetId = subnetID,
              Groups = groupIDs,
              AssociatePublicIpAddress = true
            }
          };
      }

      // Properties specifically for EC2-Classic
      else
      {
        request.SecurityGroupIds = groupIDs;
      }
      return request;
    }


    //
    // Method to launch the instances
    // Returns a list with the launched instance IDs
    private static async Task<List<string>> LaunchInstances(
      IAmazonEC2 ec2Client, RunInstancesRequest requestLaunch)
    {
      var instanceIds = new List<string>();
      RunInstancesResponse responseLaunch =
        await ec2Client.RunInstancesAsync(requestLaunch);

      Console.WriteLine("\nNew instances have been created.");
      foreach (Instance item in responseLaunch.Reservation.Instances)
      {
        instanceIds.Add(item.InstanceId);
        Console.WriteLine($"  New instance: {item.InstanceId}");
      }

      return instanceIds;
    }


    //
    // Method to wait until the instances are running (or at least not pending)
    private static async Task CheckState(IAmazonEC2 ec2Client, List<string> instanceIds)
    {
      Console.WriteLine(
        "\nWaiting for the instances to start." +
        "\nPress any key to stop waiting. (Response might be slightly delayed.)");

      int numberRunning;
      DescribeInstancesResponse responseDescribe;
      var requestDescribe = new DescribeInstancesRequest{
        InstanceIds = instanceIds};

      // Check every couple of seconds
      int wait = 2000;
      while(true)
      {
        // Get and check the status for each of the instances to see if it's past pending.
        // Once all instances are past pending, break out.
        // (For this example, we are assuming that there is only one reservation.)
        Console.Write(".");
        numberRunning = 0;
        responseDescribe = await ec2Client.DescribeInstancesAsync(requestDescribe);
        foreach(Instance i in responseDescribe.Reservations[0].Instances)
        {
          // Check the lower byte of State.Code property
          // Code == 0 is the pending state
          if((i.State.Code & 255) > 0) numberRunning++;
        }
        if(numberRunning == responseDescribe.Reservations[0].Instances.Count)
          break;

        // Wait a bit and try again (unless the user wants to stop waiting)
        Thread.Sleep(wait);
        if(Console.KeyAvailable)
          break;
      }

      Console.WriteLine("\nNo more instances are pending.");
      foreach(Instance i in responseDescribe.Reservations[0].Instances)
      {
        Console.WriteLine($"For {i.InstanceId}:");
        Console.WriteLine($"  VPC ID: {i.VpcId}");
        Console.WriteLine($"  Instance state: {i.State.Name}");
        Console.WriteLine($"  Public IP address: {i.PublicIpAddress}");
        Console.WriteLine($"  Public DNS name: {i.PublicDnsName}");
        Console.WriteLine($"  Key pair name: {i.KeyName}");
      }
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2LaunchInstance -g <group-id> -a <ami-id> -k <keypair-name> [-s <subnet-id>]" +
        "\n  -g, --group-id: The ID of the security group." +
        "\n  -a, --ami-id: The ID of an Amazon Machine Image." +
        "\n  -k, --keypair-name - The name of a key pair." +
        "\n  -s, --subnet-id: The ID of a subnet. Required only for EC2 in a VPC.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## Considerações adicionais
<a name="run-instance-additional"></a>
+ Ao verificar o estado de uma instância do EC2, você pode adicionar um filtro à `Filter` propriedade do [DescribeInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeInstancesRequest.html)objeto. Usando essa técnica, você pode limitar a solicitação a determinadas instâncias; por exemplo, instâncias com uma tag específica determinada pelo usuário.
+ Para resumir, algumas propriedades receberam valores típicos. Em vez disso, qualquer uma, ou todas essas propriedades, podem ser determinadas programaticamente ou por meio da entrada do usuário.
+ Os valores que você pode usar para as `MaxCount` propriedades `MinCount` e do [RunInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRunInstancesRequest.html)objeto são determinados pela zona de disponibilidade de destino e pelo número máximo de instâncias permitidas para o tipo de instância. Para obter mais informações, consulte [Quantas instâncias posso executar no Amazon EC2?](https://aws.amazon.com/ec2/faqs/#How_many_instances_can_I_run_in_Amazon_EC2) nas perguntas frequentes (FAQs) do Amazon EC2.
+ Se você quiser usar um tipo de instância diferente deste exemplo, há alguns tipos para escolher. Para acessar mais informações, consulte [Tipos de instâncias do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/). Consulte também [Detalhes do tipo de instância](https://aws.amazon.com/ec2/instance-types/) e [Explorador de tipos de instância](https://aws.amazon.com/ec2/instance-explorer/).
+ Você também pode anexar um [perfil do IAM](net-dg-hosm.md) a uma instância ao iniciá-la. Para fazer isso, crie um [IamInstanceProfileSpecification](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TIamInstanceProfileSpecification.html)objeto cuja `Name` propriedade esteja definida como o nome de uma função do IAM. Em seguida, adicione esse objeto à `IamInstanceProfile` propriedade do [RunInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRunInstancesRequest.html)objeto.
**nota**  
Para iniciar uma instância do EC2 com um perfil do IAM anexado, uma configuração de um usuário do IAM deve incluir determinadas permissões. Para acessar mais informações sobre as permissões necessárias, consulte [Conceder permissão a um usuário para passar um perfil do IAM para uma instância](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#permission-to-pass-iam-roles) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

## (opcional) Conecte-se à instância
<a name="connect-to-instance"></a>

Depois que uma instância estiver sendo executada, você pode conectar-se a ela remotamente usando o cliente remoto apropriado. Para instâncias Linux e Windows, você precisa do endereço IP público ou do nome DNS público da instância. Você precisará também dos seguintes itens:

**Para instâncias do Linux**

Também é possível usar um cliente SSH para conectar-se à sua instância do Linux. Certifique-se de que o grupo de segurança que você usou ao iniciar a instância permita tráfego SSH na porta 22, conforme descrito em [Como atualizar Grupos de Segurança](authorize-ingress.md).

Você também precisa da parte privada do par de chaves que você usou para iniciar a instância, ou seja, o arquivo PEM.

Para acessar mais informações, consulte [Conectar-se à instância do Linux](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instance.html) no Guia do usuário do Amazon EC2.

**Para instâncias do Windows**

Também é possível usar um cliente RDP para conectar-se à sua instância. Certifique-se de que o grupo de segurança que você usou ao iniciar a instância permita tráfego RDP na porta 3389, conforme descrito em [Como atualizar Grupos de Segurança](authorize-ingress.md).

Você precisará também da senha do administrador. Você pode obter isso usando o código de exemplo a seguir, que exige o ID da instância e a parte privada do par de chave usado para iniciar a instância, ou seja, o arquivo PEM.

Para acessar mais informações, consulte [Conectar-se à sua instância do Windows](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connecting_to_windows_instance.html) no Guia do usuário do Amazon EC2.

**Atenção**  
Esse código de exemplo retorna a senha de administrador em texto simples para sua instância.

### Referências do SDK
<a name="w2aac19c15c21c19b9c35c23b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [GetPasswordDataRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TGetPasswordDataRequest.html)

  Classe [GetPasswordDataResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TGetPasswordDataResponse.html)

### O código
<a name="w2aac19c15c21c19b9c35c25b1"></a>

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2GetWindowsPassword
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to get the Administrator password of a Windows EC2 instance
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string instanceID =
        CommandLine.GetArgument(parsedArgs, null, "-i", "--instance-id");
      string pemFileName =
        CommandLine.GetArgument(parsedArgs, null, "-p", "--pem-filename");
      if(   (string.IsNullOrEmpty(instanceID) || !instanceID.StartsWith("i-"))
         || (string.IsNullOrEmpty(pemFileName) || !pemFileName.EndsWith(".pem")))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create the EC2 client
      var ec2Client = new AmazonEC2Client();

      // Get and display the password
      string password = await GetPassword(ec2Client, instanceID, pemFileName);
      Console.WriteLine($"\nPassword: {password}");
    }


    //
    // Method to get the administrator password of a Windows EC2 instance
    private static async Task<string> GetPassword(
      IAmazonEC2 ec2Client, string instanceID, string pemFilename)
    {
      string password = string.Empty;
      GetPasswordDataResponse response =
        await ec2Client.GetPasswordDataAsync(new GetPasswordDataRequest{
          InstanceId = instanceID});
      if(response.PasswordData != null)
      {
        password = response.GetDecryptedPassword(File.ReadAllText(pemFilename));
      }
      else
      {
        Console.WriteLine($"\nThe password is not available for instance {instanceID}.");
        Console.WriteLine($"If this is a Windows instance, the password might not be ready.");
      }
      return password;
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: EC2GetWindowsPassword -i <instance-id> -p pem-filename" +
        "\n  -i, --instance-id: The name of the EC2 instance." +
        "\n  -p, --pem-filename: The name of the PEM file with the private key.");
    }
  }

  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## Limpeza
<a name="run-instance-cleanup"></a>

Quando você não precisar mais da instância do EC2, encerre-a, conforme descrito em [Encerramento de uma instância Amazon EC2](terminate-instance.md).

# Encerramento de uma instância Amazon EC2
<a name="terminate-instance"></a>

Quando uma ou mais instâncias do Amazon EC2 não forem mais necessárias, é possível encerrá-las.

Este exemplo mostra como usar o para AWS SDK para .NET encerrar instâncias do EC2. A entrada requer um ID de instância.

## Referências do SDK
<a name="w2aac19c15c21c19c11b7b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [TerminateInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TTerminateInstancesRequest.html)

  Classe [TerminateInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TTerminateInstancesResponse.html)

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2TerminateInstance
{
  class Program
  {
    static async Task Main(string[] args)
    {
      if((args.Length == 1) && (args[0].StartsWith("i-")))
      {
        // Terminate the instance
        var ec2Client = new AmazonEC2Client();
        await TerminateInstance(ec2Client, args[0]);
      }
      else
      {
        Console.WriteLine("\nCommand-line argument missing or incorrect.");
        Console.WriteLine("\nUsage: EC2TerminateInstance instance-ID");
        Console.WriteLine("  instance-ID - The EC2 instance you want to terminate.");
        return;
      }
    }

    //
    // Method to terminate an EC2 instance
    private static async Task TerminateInstance(IAmazonEC2 ec2Client, string instanceID)
    {
      var request = new TerminateInstancesRequest{
        InstanceIds = new List<string>() { instanceID }};
      TerminateInstancesResponse response =
        await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{
          InstanceIds = new List<string>() { instanceID }
        });
      foreach (InstanceStateChange item in response.TerminatingInstances)
      {
        Console.WriteLine("Terminated instance: " + item.InstanceId);
        Console.WriteLine("Instance state: " + item.CurrentState.Name);
      }
    }
  }
}
```

Depois de executar o exemplo, é uma boa ideia fazer login no [console do Amazon EC2](https://console.aws.amazon.com/ec2/) para verificar se a [instância do EC2](https://console.aws.amazon.com/ec2/v2/home#Instances) foi encerrada.

# Tutorial de instância spot do Amazon EC2
<a name="how-to-spot-instances"></a>

Este tutorial mostra como usar o AWS SDK para .NET para gerenciar instâncias spot do Amazon EC2.

## Visão geral do
<a name="tutor-spot-net-overview"></a>

Instâncias spot permitem solicitar capacidade não utilizada do Amazon EC2 por um valor mais baixo que o preço sob demanda. Isso pode reduzir significativamente os custos do EC2 para aplicativos que podem ser interrompidos.

O resumo a seguir detalha como as instâncias spot são solicitadas e usadas.

1. Criação uma solicitação de instância spot, especificando o preço máximo que está disposto a pagar.

1. Quando a solicitação for atendida, execute a instância como faria com qualquer outra instância do Amazon EC2.

1. Execute a instância por quanto tempo quiser e, em seguida, encerre-a, a menos que o *preço de spot* mude de maneira que a instância fique encerrada para você.

1. Limpe a solicitação da Instância Spot quando não for mais necessária, para que as Instâncias Spot não sejam mais criadas.

Essa tem sido uma visão geral de alto nível das Instâncias Spot. Para ter uma melhor compreensão das instâncias spot, consulte [Instâncias spot](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

## Sobre este tutorial
<a name="about-spot-instances-tutorial"></a>

Ao seguir este tutorial, você usa o AWS SDK para .NET para fazer o seguinte:
+ Criar uma solicitação de instância spot
+ Determinar quando a solicitação de instância spot é atendida
+ Cancelar a solicitação de instância spot
+ Encerrar as instâncias associadas

As seções a seguir fornecem snippets e outras informações para este exemplo. O [código completo do exemplo](#tutor-spot-net-main) é mostrado após os snippets e pode ser criado e executado como está.

**Topics**
+ [Visão geral do](#tutor-spot-net-overview)
+ [Sobre este tutorial](#about-spot-instances-tutorial)
+ [Pré-requisitos](#tutor-spot-net-prereq)
+ [Colete o que você precisa](#tutor-spot-net-gather)
+ [Como criar uma solicitação de instância spot](#tutor-spot-net-submit)
+ [Determinar o estado da solicitação de instância spot](#tutor-spot-net-request-state)
+ [Limpar suas solicitações de instância spot](#tutor-spot-net-clean-up-request)
+ [Limpar as instâncias spot](#tutor-spot-net-clean-up-instance)
+ [Código completo](#tutor-spot-net-main)
+ [Considerações adicionais](#tutor-spot-net-additional)

## Pré-requisitos
<a name="tutor-spot-net-prereq"></a>

Para obter informações sobre os pré-requisitos APIs e, consulte a seção principal (). [Trabalhar com o Amazon EC2](ec2-apis-intro.md)

## Colete o que você precisa
<a name="tutor-spot-net-gather"></a>

Para criar uma solicitação de instância spot, você precisará de várias coisas. 
+ O número da instância e o seu tipo. Há alguns tipos de instância a escolher. Para obter mais informações, consulte [Tipos de instâncias do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/). Consulte também [Detalhes do tipo de instância](https://aws.amazon.com/ec2/instance-types/) e [Explorador de tipos de instância](https://aws.amazon.com/ec2/instance-explorer/).

  Para número padrão para este tutorial é o 1.
+ A imagem de máquina da Amazon (AMI) que será usada para criar a instância. Para obter informações sobre isso AMIs, consulte [Amazon Machine Images (AMIs)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) no Guia do [usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/). Em particular, consulte [Encontre uma AMI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html) e [compartilhe AMIs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharing-amis.html).
+ O preço máximo que você está disposto a pagar por hora por instância. Você pode ver os preços de todos os tipos de instâncias (tanto para instâncias sob demanda quanto para instâncias spot) na [página de preços do Amazon EC2](https://aws.amazon.com/ec2/pricing/). O preço padrão deste tutorial será explicado posteriormente.
+ Se você quiser se conectar remotamente a uma instância, a um grupo de segurança com a configuração e os recursos adequados. Isso está descrito em [Como trabalhar com grupos de segurança no Amazon EC2](security-groups.md) e as informações sobre como [coletar o que você precisa](run-instance.md#run-instance-gather) e [conectar-se a uma instância](run-instance.md#connect-to-instance) em [Iniciar uma instância do Amazon EC2](run-instance.md). Para simplificar, este tutorial usa o grupo de segurança chamado **padrão**, que todas as contas AWS mais recentes possuem.

Há muitas maneiras de abordar a solicitação de instâncias spot. Estas são estratégias comuns:
+ Faça solicitações que certamente custarão menos que os preços sob demanda.
+ Solicitar com base no valor da computação resultante.
+ Solicitar para adquirir capacidade de computação o mais rápido possível.

As explicações a seguir se referem ao [histórico de preços de instâncias spot](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances-history.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

### Reduzir custos abaixo sob demanda
<a name="reduce-cost"></a>

Você tem um job de processamento em lote que modera determinado número de horas ou dias para ser executado. Contudo, você tem flexibilidade em relação ao início e ao fim. Você quer ver se pode o concluído por um custo inferior ao das instâncias sob demanda.

Você examina o histórico de preços spot para tipos de instância usando o console da Amazon EC2 ou a API do Amazon EC2. Depois de analisar o histórico de preços do tipo de instância desejado em determinada zona de disponibilidade, há duas abordagens alternativas para sua solicitação:
+ Especificar uma solicitação na extremidade superior do intervalo de preços spot que ainda estão abaixo do preço sob demanda, prevendo que sua solicitação instância spot única seria provavelmente cumprida e executada pelo tempo de computação consecutivo suficiente para concluir o trabalho.
+ Especificar uma solicitação na extremidade inferior do intervalo de preço e planejar a combinação de várias instâncias executadas ao longo do tempo por meio de uma requisição persistente. As instâncias seriam executadas por tempo suficiente, ao todo, para concluir o trabalho com um custo total ainda inferior.

### Não pagar mais que o valor do resultado
<a name="value-of-result"></a>

Você tem um job de processamento de dados para ser executado. Você entende o valor dos resultados do trabalho bem o suficiente para saber o quanto valem em termos de custos computação.

Após analisar o histórico de preços spot para seu tipo de instância, escolha o preço de lance no qual o custo do tempo computacional não é mais que o valor dos resultados do job. Você cria uma requisição persistente e a deixa ser executada de forma intermitente, à medida que o preço spot flutua acima ou abaixo da sua solicitação.

### Adquirir capacidade de computação rapidamente
<a name="acquire-quickly"></a>

Você tem uma necessidade imprevista e de curto prazo para capacidade adicional indisponível pelas instâncias sob demanda. Depois de analisar o histórico de preços spot para seu tipo de instância, você escolhe um preço acima do preço histórico mais alto para aumentar significativamente a probabilidade de sua solicitação ser atendida com rapidez e continuar a computação até a conclusão.

Depois de coletar o que precisa e escolher uma estratégia, você está pronto para solicitar uma Instância Spot. Para este tutorial, o preço máximo da instância spot padrão está definido para ser o mesmo que o preço da instância sob demanda (que é 0,003 USD para este tutorial). Definir o preço desta forma maximiza as chances de que o pedido seja atendido.

## Como criar uma solicitação de instância spot
<a name="tutor-spot-net-submit"></a>

O snippet a seguir mostra como criar uma solicitação de instância spot com os elementos coletados anteriormente.

O exemplo [no final deste tópico](#tutor-spot-net-main) mostra o snippet em uso.

```
    //
    // Method to create a Spot Instance request
    private static async Task<SpotInstanceRequest> CreateSpotInstanceRequest(
      IAmazonEC2 ec2Client, string amiId, string securityGroupName,
      InstanceType instanceType, string spotPrice, int instanceCount)
    {
      var launchSpecification = new LaunchSpecification{
        ImageId = amiId,
        InstanceType = instanceType
      };
      launchSpecification.SecurityGroups.Add(securityGroupName);
      var request = new RequestSpotInstancesRequest{
        SpotPrice = spotPrice,
        InstanceCount = instanceCount,
        LaunchSpecification = launchSpecification
      };

      RequestSpotInstancesResponse result =
        await ec2Client.RequestSpotInstancesAsync(request);
      return result.SpotInstanceRequests[0];
    }
```

O valor importante retornado desse método é o ID da solicitação da Instância Spot, que está contido no `SpotInstanceRequestId` membro do [SpotInstanceRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TSpotInstanceRequest.html)objeto retornado.

**nota**  
Você será cobrado por todas as instâncias spot que forem iniciadas. Para evitar custos desnecessários, certifique-se de [cancelar todas as solicitações](#tutor-spot-net-clean-up-request) e [encerrar todas as instâncias](#tutor-spot-net-clean-up-instance).

## Determinar o estado da solicitação de instância spot
<a name="tutor-spot-net-request-state"></a>

O snippet a seguir mostra como obter informações sobre sua solicitação de instância spot. Você pode usar essas informações para tomar certas decisões em seu código, como decidir continuar esperando o atendimento de uma solicitação de instância spot.

O exemplo [no final deste tópico](#tutor-spot-net-main) mostra o snippet em uso.

```
    //
    // Method to get information about a Spot Instance request, including the status,
    // instance ID, etc.
    // It gets the information for a specific request (as opposed to all requests).
    private static async Task<SpotInstanceRequest> GetSpotInstanceRequestInfo(
      IAmazonEC2 ec2Client, string requestId)
    {
      var describeRequest = new DescribeSpotInstanceRequestsRequest();
      describeRequest.SpotInstanceRequestIds.Add(requestId);

      DescribeSpotInstanceRequestsResponse describeResponse =
        await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest);
      return describeResponse.SpotInstanceRequests[0];
    }
```

O método retorna informações sobre a solicitação da instância spot, como o ID da instância, seu estado e o código de status. Para acessar mais informações sobre os códigos de status das solicitações de Instância spot, consulte [Spot request status](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html#spot-instance-bid-status-understand) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

## Limpar suas solicitações de instância spot
<a name="tutor-spot-net-clean-up-request"></a>

Quando você não precisar mais solicitar instâncias spot, é importante cancelar todas as solicitações pendentes para evitar que essas solicitações sejam atendidas novamente. O snippet a seguir mostra como cancelar uma solicitação de instância spot.

O exemplo [no final deste tópico](#tutor-spot-net-main) mostra o snippet em uso.

```
    //
    // Method to cancel a Spot Instance request
    private static async Task CancelSpotInstanceRequest(
      IAmazonEC2 ec2Client, string requestId)
    {
      var cancelRequest = new CancelSpotInstanceRequestsRequest();
      cancelRequest.SpotInstanceRequestIds.Add(requestId);

      await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest);
    }
```

## Limpar as instâncias spot
<a name="tutor-spot-net-clean-up-instance"></a>

Para evitar custos desnecessários, é importante que você encerre todas as instâncias que foram iniciadas a partir de solicitações de instância spot. Apenas cancelar a solicitação de instância spot não encerrará as instâncias, o que significa que você continuará a ser cobrado por elas. O snippet a seguir mostra como encerrar uma instância depois de obter o identificador da instância para uma instância spot ativa.

O exemplo [no final deste tópico](#tutor-spot-net-main) mostra o snippet em uso.

```
    //
    // Method to terminate a Spot Instance
    private static async Task TerminateSpotInstance(
      IAmazonEC2 ec2Client, string requestId)
    {
      var describeRequest = new DescribeSpotInstanceRequestsRequest();
      describeRequest.SpotInstanceRequestIds.Add(requestId);

      // Retrieve the Spot Instance request to check for running instances.
      DescribeSpotInstanceRequestsResponse describeResponse =
        await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest);

      // If there are any running instances, terminate them
      if(   (describeResponse.SpotInstanceRequests[0].Status.Code
              == "request-canceled-and-instance-running")
         || (describeResponse.SpotInstanceRequests[0].State == SpotInstanceState.Active))
      {
        TerminateInstancesResponse response =
          await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{
            InstanceIds = new List<string>(){
              describeResponse.SpotInstanceRequests[0].InstanceId } });
        foreach (InstanceStateChange item in response.TerminatingInstances)
        {
          Console.WriteLine($"\n  Terminated instance: {item.InstanceId}");
          Console.WriteLine($"  Instance state: {item.CurrentState.Name}\n");
        }
      }
    }
```

## Código completo
<a name="tutor-spot-net-main"></a>

O exemplo de código a seguir chama os métodos descritos anteriormente para criar e cancelar uma solicitação de instância spot e encerrar uma instância spot.

### Referências do SDK
<a name="w2aac19c15c21c21c43b5b1"></a>

NuGet pacotes:
+ [AWSSDK.EC2](https://www.nuget.org/packages/AWSSDK.EC2)

Elementos de programação:
+ Namespace [Amazon.EC2](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2.html)

  Classe [Amazon EC2 Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TEC2Client.html)

  Classe [InstanceType](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceType.html)
+ Namespace [Amazon.EC2.model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/NEC2Model.html)

  Classe [CancelSpotInstanceRequestsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TCancelSpotInstanceRequestsRequest.html)

  Classe [DescribeSpotInstanceRequestsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSpotInstanceRequestsRequest.html)

  Classe [DescribeSpotInstanceRequestsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TDescribeSpotInstanceRequestsResponse.html)

  Classe [InstanceStateChange](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TInstanceStateChange.html)

  Classe [LaunchSpecification](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TLaunchSpecification.html)

  Classe [RequestSpotInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRequestSpotInstancesRequest.html)

  Classe [RequestSpotInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TRequestSpotInstancesResponse.html)

  Classe [SpotInstanceRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TSpotInstanceRequest.html)

  Classe [TerminateInstancesRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TTerminateInstancesRequest.html)

  Classe [TerminateInstancesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/EC2/TTerminateInstancesResponse.html)

### O código
<a name="w2aac19c15c21c21c43b7b1"></a>

```
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.EC2;
using Amazon.EC2.Model;

namespace EC2SpotInstanceRequests
{
  class Program
  {
    static async Task Main(string[] args)
    {
      // Some default values.
      // These could be made into command-line arguments instead.
      var instanceType = InstanceType.T1Micro;
      string securityGroupName = "default";
      string spotPrice = "0.003";
      int instanceCount = 1;

      // Parse the command line arguments
      if((args.Length != 1) || (!args[0].StartsWith("ami-")))
      {
        Console.WriteLine("\nUsage: EC2SpotInstanceRequests ami");
        Console.WriteLine("  ami: the Amazon Machine Image to use for the Spot Instances.");
        return;
      }

      // Create the Amazon EC2 client.
      var ec2Client = new AmazonEC2Client();

      // Create the Spot Instance request and record its ID
      Console.WriteLine("\nCreating spot instance request...");
      var req = await CreateSpotInstanceRequest(
        ec2Client, args[0], securityGroupName, instanceType, spotPrice, instanceCount);
      string requestId = req.SpotInstanceRequestId;

      // Wait for an EC2 Spot Instance to become active
      Console.WriteLine(
        $"Waiting for Spot Instance request with ID {requestId} to become active...");
      int wait = 1;
      var start = DateTime.Now;
      while(true)
      {
        Console.Write(".");

        // Get and check the status to see if the request has been fulfilled.
        var requestInfo = await GetSpotInstanceRequestInfo(ec2Client, requestId);
        if(requestInfo.Status.Code == "fulfilled")
        {
          Console.WriteLine($"\nSpot Instance request {requestId} " +
            $"has been fulfilled by instance {requestInfo.InstanceId}.\n");
          break;
        }

        // Wait a bit and try again, longer each time (1, 2, 4, ...)
        Thread.Sleep(wait);
        wait = wait * 2;
      }

      // Show the user how long it took to fulfill the Spot Instance request.
      TimeSpan span = DateTime.Now.Subtract(start);
      Console.WriteLine($"That took {span.TotalMilliseconds} milliseconds");

      // Perform actions here as needed.
      // For this example, simply wait for the user to hit a key.
      // That gives them a chance to look at the EC2 console to see
      // the running instance if they want to.
      Console.WriteLine("Press any key to start the cleanup...");
      Console.ReadKey(true);

      // Cancel the request.
      // Do this first to make sure that the request can't be re-fulfilled
      // once the Spot Instance has been terminated.
      Console.WriteLine("Canceling Spot Instance request...");
      await CancelSpotInstanceRequest(ec2Client, requestId);

      // Terminate the Spot Instance that's running.
      Console.WriteLine("Terminating the running Spot Instance...");
      await TerminateSpotInstance(ec2Client, requestId);

      Console.WriteLine("Done. Press any key to exit...");
      Console.ReadKey(true);
    }


    //
    // Method to create a Spot Instance request
    private static async Task<SpotInstanceRequest> CreateSpotInstanceRequest(
      IAmazonEC2 ec2Client, string amiId, string securityGroupName,
      InstanceType instanceType, string spotPrice, int instanceCount)
    {
      var launchSpecification = new LaunchSpecification{
        ImageId = amiId,
        InstanceType = instanceType
      };
      launchSpecification.SecurityGroups.Add(securityGroupName);
      var request = new RequestSpotInstancesRequest{
        SpotPrice = spotPrice,
        InstanceCount = instanceCount,
        LaunchSpecification = launchSpecification
      };

      RequestSpotInstancesResponse result =
        await ec2Client.RequestSpotInstancesAsync(request);
      return result.SpotInstanceRequests[0];
    }


    //
    // Method to get information about a Spot Instance request, including the status,
    // instance ID, etc.
    // It gets the information for a specific request (as opposed to all requests).
    private static async Task<SpotInstanceRequest> GetSpotInstanceRequestInfo(
      IAmazonEC2 ec2Client, string requestId)
    {
      var describeRequest = new DescribeSpotInstanceRequestsRequest();
      describeRequest.SpotInstanceRequestIds.Add(requestId);

      DescribeSpotInstanceRequestsResponse describeResponse =
        await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest);
      return describeResponse.SpotInstanceRequests[0];
    }


    //
    // Method to cancel a Spot Instance request
    private static async Task CancelSpotInstanceRequest(
      IAmazonEC2 ec2Client, string requestId)
    {
      var cancelRequest = new CancelSpotInstanceRequestsRequest();
      cancelRequest.SpotInstanceRequestIds.Add(requestId);

      await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest);
    }


    //
    // Method to terminate a Spot Instance
    private static async Task TerminateSpotInstance(
      IAmazonEC2 ec2Client, string requestId)
    {
      var describeRequest = new DescribeSpotInstanceRequestsRequest();
      describeRequest.SpotInstanceRequestIds.Add(requestId);

      // Retrieve the Spot Instance request to check for running instances.
      DescribeSpotInstanceRequestsResponse describeResponse =
        await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest);

      // If there are any running instances, terminate them
      if(   (describeResponse.SpotInstanceRequests[0].Status.Code
              == "request-canceled-and-instance-running")
         || (describeResponse.SpotInstanceRequests[0].State == SpotInstanceState.Active))
      {
        TerminateInstancesResponse response =
          await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{
            InstanceIds = new List<string>(){
              describeResponse.SpotInstanceRequests[0].InstanceId } });
        foreach (InstanceStateChange item in response.TerminatingInstances)
        {
          Console.WriteLine($"\n  Terminated instance: {item.InstanceId}");
          Console.WriteLine($"  Instance state: {item.CurrentState.Name}\n");
        }
      }
    }
  }
}
```

## Considerações adicionais
<a name="tutor-spot-net-additional"></a>
+ Depois de executar o tutorial, é uma boa ideia fazer login no [console do Amazon EC2](https://console.aws.amazon.com/ec2/) para verificar se a [solicitação da Instância Spot](https://console.aws.amazon.com/ec2/home#SpotInstances:) foi cancelada e se a [Instância Spot](https://console.aws.amazon.com/ec2/v2/home#Instances) foi encerrada.

# Acessando AWS Identity and Access Management (IAM) com o AWS SDK para .NET
<a name="iam-apis-intro"></a>

O AWS SDK para .NET suporte [AWS Identity and Access Management](https://docs.aws.amazon.com/IAM/latest/UserGuide/), que é um serviço da web que permite AWS aos clientes gerenciar usuários e permissões de usuário em AWS.

Um *usuário AWS Identity and Access Management * (IAM) é uma entidade que você cria em AWS. A entidade representa uma pessoa ou aplicativo com AWS quem interage. Para obter mais informações sobre os usuários do IAM, consulte [Usuários do IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html) e [limites do IAM e do STS](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html) no Guia do usuário do IAM.

Conceder permissões a um usuário criando uma *política* do IAM. A política contém um *documento de política* que lista as ações que um usuário pode executar e os recursos que essas ações podem afetar. Para obter mais informações sobre as políticas do IAM, consulte [Permissões e políticas](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) no *Guia do usuário do IAM*.

**Atenção**  
Para evitar riscos de segurança, não use usuários do IAM para autenticação ao desenvolver software com propósito específico ou trabalhar com dados reais. Em vez disso, use federação com um provedor de identidade, como [Centro de Identidade do AWS IAM](https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html).

## APIs
<a name="w2aac19c15c23c13"></a>

Eles AWS SDK para .NET fornecem APIs para clientes do IAM. Eles APIs permitem que você trabalhe com recursos do IAM, como usuários, funções e chaves de acesso.

Esta seção contém um pequeno número de exemplos que mostram os padrões que você pode seguir ao trabalhar com eles APIs. Para ver o conjunto completo de APIs, consulte a [Referência da AWS SDK para .NET API](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/) (e vá até “Amazon. IdentityManagement“).

Esta seção também contém [um exemplo](net-dg-hosm.md) que mostra como anexar um perfil do IAM às instâncias do Amazon EC2 para facilitar o gerenciamento de credenciais.

O IAM APIs é fornecido pelo [AWSSDK. IdentityManagement](https://www.nuget.org/packages/AWSSDK.IdentityManagement) NuGetpacote.

## Pré-requisitos
<a name="w2aac19c15c23c15"></a>

Antes de começar, verifique se você [configurou seu ambiente](net-dg-config.md) e [configurou seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

## Tópicos
<a name="w2aac19c15c23c17"></a>

**Topics**
+ [APIs](#w2aac19c15c23c13)
+ [Pré-requisitos](#w2aac19c15c23c15)
+ [Tópicos](#w2aac19c15c23c17)
+ [Criar políticas gerenciadas a partir do JSON](iam-policies-create-json.md)
+ [Exibir documentos de políticas](iam-policies-display.md)
+ [Conceder acesso com um perfil](net-dg-hosm.md)

# Criar políticas gerenciadas pelo IAM a partir do JSON
<a name="iam-policies-create-json"></a>

Este exemplo mostra como usar o AWS SDK para .NET para criar uma [política gerenciada pelo IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies) a partir de um determinado documento de política em JSON. O aplicativo cria um objeto cliente do IAM, lê o documento de política de um arquivo e, em seguida, cria a política.

**nota**  
Para ver um exemplo de documento de política em JSON, consulte as [considerações adicionais](#iam-policies-create-json-additional) no final deste tópico.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#iam-policies-create-json-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Crie a política do](#iam-policies-create-json-create)
+ [Código completo](#iam-policies-create-json-complete-code)
+ [Considerações adicionais](#iam-policies-create-json-additional)

## Crie a política do
<a name="iam-policies-create-json-create"></a>

O trecho a seguir cria uma política gerenciada pelo IAM com o nome e o documento de política fornecidos.

O exemplo [no final deste tópico](#iam-policies-create-json-complete-code) mostra o snippet em uso.

```
    //
    // Method to create an IAM policy from a JSON file
    private static async Task<CreatePolicyResponse> CreateManagedPolicy(
      IAmazonIdentityManagementService iamClient, string policyName, string jsonFilename)
    {
      return await iamClient.CreatePolicyAsync(new CreatePolicyRequest{
        PolicyName = policyName,
        PolicyDocument = File.ReadAllText(jsonFilename)});
    }
```

## Código completo
<a name="iam-policies-create-json-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c23c21c17b5b1"></a>

NuGet pacotes:
+ [AWSSDK.IdentityManagement](https://www.nuget.org/packages/AWSSDK.IdentityManagement)

Elementos de programação:
+ [Namespace Amazon. IdentityManagement](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/NIAM.html)

  Classe [AmazonIdentityManagementServiceClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TIAMServiceClient.html)
+ [Namespace Amazon. IdentityManagement.Modelo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/NIAMModel.html)

  Classe [CreatePolicyRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TCreatePolicyRequest.html)

  Classe [CreatePolicyResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TCreatePolicyResponse.html)

### O código
<a name="w2aac19c15c23c21c17b7b1"></a>

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.IdentityManagement;
using Amazon.IdentityManagement.Model;

namespace IamCreatePolicyFromJson
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to create an IAM policy with a given policy document
  class Program
  {
    private const int MaxArgs = 2;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if((parsedArgs.Count == 0) || (parsedArgs.Count > MaxArgs))
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string policyName =
        CommandLine.GetArgument(parsedArgs, null, "-p", "--policy-name");
      string policyFilename =
        CommandLine.GetArgument(parsedArgs, null, "-j", "--json-filename");
      if(   string.IsNullOrEmpty(policyName)
         || (string.IsNullOrEmpty(policyFilename) || !policyFilename.EndsWith(".json")))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create an IAM service client
      var iamClient = new AmazonIdentityManagementServiceClient();

      // Create the new policy
      var response = await CreateManagedPolicy(iamClient, policyName, policyFilename);
      Console.WriteLine($"\nPolicy {response.Policy.PolicyName} has been created.");
      Console.WriteLine($"  Arn: {response.Policy.Arn}");
    }


    //
    // Method to create an IAM policy from a JSON file
    private static async Task<CreatePolicyResponse> CreateManagedPolicy(
      IAmazonIdentityManagementService iamClient, string policyName, string jsonFilename)
    {
      return await iamClient.CreatePolicyAsync(new CreatePolicyRequest{
        PolicyName = policyName,
        PolicyDocument = File.ReadAllText(jsonFilename)});
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: IamCreatePolicyFromJson -p <policy-name> -j <json-filename>" +
        "\n  -p, --policy-name: The name you want the new policy to have." +
        "\n  -j, --json-filename: The name of the JSON file with the policy document.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## Considerações adicionais
<a name="iam-policies-create-json-additional"></a>
+ Veja a seguir um exemplo de documento de política que você pode copiar em um arquivo JSON e usar como entrada para esse aplicativo:

------
#### [ JSON ]

****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Id"  : "DotnetTutorialPolicy",
    "Statement" : [
      {
        "Sid" : "DotnetTutorialPolicyS3",
        "Effect" : "Allow",
        "Action" : [
          "s3:Get*",
          "s3:List*"
        ],
        "Resource" : "*"
      },
      {
        "Sid" : "DotnetTutorialPolicyPolly",
        "Effect": "Allow",
        "Action": [
          "polly:DescribeVoices",
          "polly:SynthesizeSpeech"
        ],
        "Resource": "*"
      }
    ]
  }
  ```

------
+ Você pode verificar se a política foi criada consultando o [console do IAM](https://console.aws.amazon.com/iam/home#/policies). Usar a lista suspensa **Filtrar políticas** para selecionar **Gerenciado pelo cliente**. Excluir uma política quando não precisar mais dela.
+  Para obter mais informações sobre a criação de políticas, consulte [Criação de políticas do IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html) e a [referência da política JSON](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html) no [Guia do usuário do IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/)

# Exibir o documento da política gerenciada do IAM
<a name="iam-policies-display"></a>

Este exemplo mostra como usar o AWS SDK para .NET para exibir um documento de política. O aplicativo cria um objeto cliente do IAM, encontra a versão padrão da política gerenciada do IAM em questão e, em seguida, exibe o documento da política em formato JSON.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#iam-policies-display-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Encontrar a versão padrão](#iam-policies-display-version)
+ [Exibir o documento da política](#iam-policies-display-doc)
+ [Código completo](#iam-policies-display-complete-code)

## Encontrar a versão padrão
<a name="iam-policies-display-version"></a>

Os snippet a seguir encontram a versão padrão da política do IAM.

O exemplo [no final deste tópico](#iam-policies-display-complete-code) mostra o snippet em uso.

```
    //
    // Method to determine the default version of an IAM policy
    // Returns a string with the version
    private static async Task<string> GetDefaultVersion(
      IAmazonIdentityManagementService iamClient, string policyArn)
    {
      // Retrieve all the versions of this policy
      string defaultVersion = string.Empty;
      ListPolicyVersionsResponse reponseVersions =
        await iamClient.ListPolicyVersionsAsync(new ListPolicyVersionsRequest{
          PolicyArn = policyArn});

      // Find the default version
      foreach(PolicyVersion version in reponseVersions.Versions)
      {
        if(version.IsDefaultVersion)
        {
          defaultVersion = version.VersionId;
          break;
        }
      }

      return defaultVersion;
    }
```

## Exibir o documento da política
<a name="iam-policies-display-doc"></a>

O snippet a seguir exibe o documento de política JSON da política do IAM fornecida.

O exemplo [no final deste tópico](#iam-policies-display-complete-code) mostra o snippet em uso.

```
    //
    // Method to retrieve and display the policy document of an IAM policy
    private static async Task ShowPolicyDocument(
      IAmazonIdentityManagementService iamClient, string policyArn, string defaultVersion)
    {
      // Retrieve the policy document of the default version
      GetPolicyVersionResponse responsePolicy =
        await iamClient.GetPolicyVersionAsync(new GetPolicyVersionRequest{
          PolicyArn = policyArn,
          VersionId = defaultVersion});

      // Display the policy document (in JSON)
      Console.WriteLine($"Version {defaultVersion} of the policy (in JSON format):");
      Console.WriteLine(
        $"{HttpUtility.UrlDecode(responsePolicy.PolicyVersion.Document)}");
    }
```

## Código completo
<a name="iam-policies-display-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c23c23c19b5b1"></a>

NuGet pacotes:
+ [AWSSDK.IdentityManagement](https://www.nuget.org/packages/AWSSDK.IdentityManagement)

Elementos de programação:
+ [Namespace Amazon. IdentityManagement](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/NIAM.html)

  Classe [AmazonIdentityManagementServiceClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TIAMServiceClient.html)
+ [Namespace Amazon. IdentityManagement.Modelo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/NIAMModel.html)

  Classe [GetPolicyVersionRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TGetPolicyVersionRequest.html)

  Classe [GetPolicyVersionResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TGetPolicyVersionResponse.html)

  Classe [ListPolicyVersionsRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TListPolicyVersionsRequest.html)

  Classe [ListPolicyVersionsResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TListPolicyVersionsResponse.html)

  Classe [PolicyVersion](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/IAM/TPolicyVersion.html)

### O código
<a name="w2aac19c15c23c23c19b7b1"></a>

```
using System;
using System.Web;
using System.Threading.Tasks;
using Amazon.IdentityManagement;
using Amazon.IdentityManagement.Model;

namespace IamDisplayPolicyJson
{
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      if(args.Length != 1)
      {
        Console.WriteLine("\nUsage: IamDisplayPolicyJson policy-arn");
        Console.WriteLine("   policy-arn: The ARN of the policy to retrieve.");
        return;
      }
      if(!args[0].StartsWith("arn:"))
      {
        Console.WriteLine("\nCould not find policy ARN in the command-line arguments:");
        Console.WriteLine($"{args[0]}");
        return;
      }

      // Create an IAM service client
      var iamClient = new AmazonIdentityManagementServiceClient();

      // Retrieve and display the policy document of the given policy
      string defaultVersion = await GetDefaultVersion(iamClient, args[0]);
      if(string.IsNullOrEmpty(defaultVersion))
        Console.WriteLine($"Could not find the default version for policy {args[0]}.");
      else
        await ShowPolicyDocument(iamClient, args[0], defaultVersion);
    }


    //
    // Method to determine the default version of an IAM policy
    // Returns a string with the version
    private static async Task<string> GetDefaultVersion(
      IAmazonIdentityManagementService iamClient, string policyArn)
    {
      // Retrieve all the versions of this policy
      string defaultVersion = string.Empty;
      ListPolicyVersionsResponse reponseVersions =
        await iamClient.ListPolicyVersionsAsync(new ListPolicyVersionsRequest{
          PolicyArn = policyArn});

      // Find the default version
      foreach(PolicyVersion version in reponseVersions.Versions)
      {
        if(version.IsDefaultVersion)
        {
          defaultVersion = version.VersionId;
          break;
        }
      }

      return defaultVersion;
    }


    //
    // Method to retrieve and display the policy document of an IAM policy
    private static async Task ShowPolicyDocument(
      IAmazonIdentityManagementService iamClient, string policyArn, string defaultVersion)
    {
      // Retrieve the policy document of the default version
      GetPolicyVersionResponse responsePolicy =
        await iamClient.GetPolicyVersionAsync(new GetPolicyVersionRequest{
          PolicyArn = policyArn,
          VersionId = defaultVersion});

      // Display the policy document (in JSON)
      Console.WriteLine($"Version {defaultVersion} of the policy (in JSON format):");
      Console.WriteLine(
        $"{HttpUtility.UrlDecode(responsePolicy.PolicyVersion.Document)}");
    }
  }
}
```

# Conceder acesso utilizando um perfil do IAM
<a name="net-dg-hosm"></a>

Este tutorial mostra como usar o para AWS SDK para .NET habilitar funções do IAM em instâncias do Amazon EC2.

## Visão geral do
<a name="hosm-overview"></a>

Todas as solicitações AWS devem ser assinadas criptograficamente usando credenciais emitidas por. AWS Portanto, é necessária uma estratégia para gerenciar credenciais para aplicações executadas nas instâncias do Amazon EC2. É necessário distribuir, armazenar e girar essas credenciais com segurança, mas também mantendo-as acessíveis à aplicação.

Com os perfis do IAM, você pode gerenciar essas credenciais com eficiência. Você cria um perfil do IAM e a configura com as permissões que uma aplicação exige e, em seguida, anexa esse perfil a uma instância do EC2. Para ler mais sobre os benefícios de usar perfis do IAM, consulte [Perfis do IAM para o Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/). Consulte também as informações sobre [perfis do IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) no Guia do usuário do IAM.

Para um aplicativo criado usando o AWS SDK para .NET, quando o aplicativo constrói um objeto cliente para um AWS serviço, o objeto pesquisa credenciais de várias fontes potenciais. A ordem da pesquisa é mostrada em [Resolução de perfil e credenciais](creds-assign.md).

Se o objeto cliente não encontrar as credenciais em nenhuma outra fonte, ele recuperará as credenciais temporárias com as mesmas permissões que as associadas ao perfil do IAM pelos metadados da instância EC2. Essas credenciais são usadas para fazer chamadas a AWS partir do objeto cliente.

## Sobre este tutorial
<a name="about-hosm-tutorial"></a>

Ao seguir este tutorial, você usa a AWS SDK para .NET (e outras ferramentas) para iniciar uma instância do Amazon EC2 com uma função do IAM anexada e, em seguida, vê um aplicativo na instância usando as permissões da função do IAM.

**Topics**
+ [Visão geral do](#hosm-overview)
+ [Sobre este tutorial](#about-hosm-tutorial)
+ [Criar uma amostra da aplicação no Amazon S3](#net-dg-hosm-sample-s3-app)
+ [Criar um perfil do IAM](#net-dg-hosm-create-the-role)
+ [Iniciar uma instância do EC2 e anexar o perfil do IAM](#net-dg-hosm-launch-ec2-instance)
+ [Conectar-se à instância EC2](#net-dg-hosm-connect)
+ [Executar o exemplo da aplicação na instância do EC2](#net-dg-hosm-run-the-app)
+ [Limpeza](#net-dg-hosm-cleanup)

## Criar uma amostra da aplicação no Amazon S3
<a name="net-dg-hosm-sample-s3-app"></a>

Esta aplicação de exemplo recupera um objeto do Amazon S3. Para executar a aplicação, você precisa:
+ Um bucket do Amazon S3 que contém um arquivo de texto.
+ AWS credenciais em sua máquina de desenvolvimento que permitem acessar o bucket.

Para ter informações sobre como criar um bucket do Amazon S3 e fazer upload de um objeto, consulte o [Guia do usuário do Amazon Simple Storage Service](https://docs.aws.amazon.com/AmazonS3/latest/userguide/). Para obter informações sobre AWS credenciais, consulte[Autenticando o com AWS SDK para .NET AWS](creds-idc.md).

Criar um projeto .NET Core com o seguinte código. Em seguida, teste aplicação em sua máquina de desenvolvimento.

**nota**  
Em sua máquina de desenvolvimento, o domínio .NET Core Runtime está instalado, o que permite que você execute a aplicação sem publicá-la. Ao criar uma instância do EC2 mais adiante neste tutorial, é possível instalar o. NET Core Runtime na instância. Isso proporciona uma experiência semelhante e uma transferência de arquivos menor.  
 No entanto, é possível optar por não instalar o.NET Core Runtime na instância. Se você escolher esse curso de ação, deverá publicar a aplicação para que todas as dependências sejam incluídas ao transferi-la para a instância.

### Referências do SDK
<a name="w2aac19c15c23c25c17c13b1"></a>

NuGet pacotes:
+ [AWSSDK.S3](https://www.nuget.org/packages/AWSSDK.S3)

Elementos de programação:
+ Namespace [Amazon.S3](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/NS3.html)

  Classe [AmazonS3Client](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TS3Client.html)
+ Namespace [Amazon.S3.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/NS3Model.html)

  Classe [GetObjectResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectResponse.html)

### O código
<a name="w2aac19c15c23c25c17c15b1"></a>

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.S3;
using Amazon.S3.Model;

namespace S3GetTextItem
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to retrieve a text file from an S3 bucket and write it to a local file
  class Program
  {
    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string bucket =
        CommandLine.GetArgument(parsedArgs, null, "-b", "--bucket-name");
      string item =
        CommandLine.GetArgument(parsedArgs, null, "-t", "--text-object");
      string outFile =
        CommandLine.GetArgument(parsedArgs, null, "-o", "--output-filename");
      if(   string.IsNullOrEmpty(bucket)
         || string.IsNullOrEmpty(item)
         || string.IsNullOrEmpty(outFile))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");

      // Create the S3 client object and get the file object from the bucket.
      var response = await GetObject(new AmazonS3Client(), bucket, item);

      // Write the contents of the file object to the given output file.
      var reader = new StreamReader(response.ResponseStream);
      string contents = reader.ReadToEnd();
      using (var s = new FileStream(outFile, FileMode.Create))
      using (var writer = new StreamWriter(s))
        writer.WriteLine(contents);
    }


    //
    // Method to get an object from an S3 bucket.
    private static async Task<GetObjectResponse> GetObject(
      IAmazonS3 s3Client, string bucket, string item)
    {
        Console.WriteLine($"Retrieving {item} from bucket {bucket}.");
        return await s3Client.GetObjectAsync(bucket, item);
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: S3GetTextItem -b <bucket-name> -t <text-object> -o <output-filename>" +
        "\n  -b, --bucket-name: The name of the S3 bucket." +
        "\n  -t, --text-object: The name of the text object in the bucket." +
        "\n  -o, --output-filename: The name of the file to write the text to.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

Se quiser, você pode remover temporariamente as credenciais usadas na máquina de desenvolvimento para ver como a aplicação responde. (Mas não se esqueça de restaurar as credenciais quando concluir).

## Criar um perfil do IAM
<a name="net-dg-hosm-create-the-role"></a>

Criar um perfil do IAM com as permissões apropriadas para acessar o Amazon S3.

1. Abra o [console do IAM](https://console.aws.amazon.com/iam/).

1. No painel de navegação, escolha **Perfis** e depois escolha **Criar perfil**.

1. Selecionar **serviço da AWS **, escolher **EC2** e depois **Avançar: Permissões**.

1. Em **Anexar políticas de permissões**, encontre e selecione **ReadOnlyAccessAmazonS3**. Revise a política, se quiser, e escolha **Avançar: Tags**.

1. Adicione tags, se quiser, e escolha **Avançar: Revisão**.

1. Digite um nome e uma descrição para a função e, em seguida, escolha **Criar função**. Lembre-se desse nome, pois você precisará dele quando executar sua instância do EC2.

## Iniciar uma instância do EC2 e anexar o perfil do IAM
<a name="net-dg-hosm-launch-ec2-instance"></a>

Iniciar uma instância do EC2 com o perfil do IAM que foi criada. Você pode fazer isso das seguintes maneiras.
+ **Usar o console do EC2**

  Para executar uma instância usando o console do EC2, consulte [Iniciar uma instância usando o novo assistente de inicialização de instâncias](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-launch-instance-wizard.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

  Ao examinar a página de lançamento, você deve pelo menos expandir o painel **Detalhes avançados** para poder especificar o perfil do IAM que você criou anteriormente no **perfil da instância do IAM**.
+ **Usando o AWS SDK para .NET**

  Para obter informações sobre isso, consulte [Iniciar uma instância do Amazon EC2](run-instance.md), incluindo o [Considerações adicionais](run-instance.md#run-instance-additional) próximo ao final desse tópico.

Para iniciar uma instância do EC2 com um perfil do IAM anexado, uma configuração de um usuário do IAM deve incluir determinadas permissões. Para acessar mais informações sobre as permissões necessárias, consulte [Conceder permissão a um usuário para passar um perfil do IAM para uma instância](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#permission-to-pass-iam-roles) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

## Conectar-se à instância EC2
<a name="net-dg-hosm-connect"></a>

Conectar à instância do EC2 para que você possa transferir a amostra do aplicativo e, em seguida, executar o aplicativo. Você precisará do arquivo que contém a parte privada do par de chaves usado para executar a instância, ou seja, o arquivo PEM.

Para acessar informações sobre como se conectar à instância, consulte [Conectar-se à sua instância do Linux](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instance.html) ou [Conectar-se à instância do Windows](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/connecting_to_windows_instance.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/). Ao conectar-se, faça isso de maneira que possa transferir arquivos da sua máquina de desenvolvimento para sua instância.

Se estiver usando o Visual Studio no Windows, também poderá conectar-se à instância usando o Toolkit for Visual Studio. Para obter mais informações, consulte [Conectando-se a uma instância do Amazon EC2](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/tkv-ec2-ami.html#connect-ec2) no Guia do AWS Toolkit for Visual Studio usuário.

## Executar o exemplo da aplicação na instância do EC2
<a name="net-dg-hosm-run-the-app"></a>

1. Copiar as aplicações do aplicativo da sua unidade local para sua instância.

   Os arquivos transferidos dependem de como a aplicação foi criada e se sua instância tem o.NET Core Runtime instalado. Para acessar informações sobre como transferir arquivos para sua instância, consulte [Conecte-se à sua instância Linux](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instance.html) (consulte a subseção apropriada) ou [Transferir arquivos para instâncias do Windows](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/connect-to-linux-instanceWindowsFileTransfer.html) no [Guia do usuário do Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/).

1. Iniciar a aplicação e verificar se é executada com os mesmos resultados da sua máquina de desenvolvimento.

1. Verifique se a aplicação usa as credenciais fornecidas pelo perfil do IAM.

   1. Abra o [console do Amazon EC2](https://console.aws.amazon.com/ec2/).

   1. Selecione a instância e desanexe o perfil do IAM por meio de **Ações**, **Configurações da instância** e **Anexar/substituir perfil do IAM**.

   1. Execute o aplicativo novamente e veja se retorna um erro de autorização.

## Limpeza
<a name="net-dg-hosm-cleanup"></a>

Ao terminar este tutorial, se não desejar mais a instância do EC2 criada, certifique-se de encerrar a instância para evitar custos indesejados. Isso poderá ser feito no [console do Amazon EC2](https://console.aws.amazon.com/ec2/) ou programaticamente, conforme descrito em [Encerramento de uma instância Amazon EC2](terminate-instance.md). Se desejar, você também pode excluir outros recursos que tenha criado para este tutorial. Isso pode incluir um perfil do IAM, um par de chaves do EC2 e um arquivo PEM, um grupo de segurança etc.

# Usar o armazenamento para internet Amazon Simple Storage Service
<a name="s3-apis-intro"></a>

O AWS SDK para .NET suporta o [Amazon S3](https://aws.amazon.com/s3/), que é armazenamento para a Internet. Ele foi projetado para facilitar a computação de escala na web para os desenvolvedores.

## APIs
<a name="w2aac19c15c25b5"></a>

 AWS SDK para .NET Ele fornece APIs para clientes do Amazon S3. Eles APIs permitem que você trabalhe com recursos do Amazon S3, como buckets e itens. Para ver o conjunto completo de APIs para o Amazon S3, veja o seguinte:
+ [AWS SDK para .NET Referência da API](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/) (e vá até “Amazon.S3").
+ Documentação [Amazon.Extensions.S3.Encryption](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.html)

O Amazon S3 APIs é fornecido pelos seguintes pacotes: NuGet 
+ [AWSSDK.S3](https://www.nuget.org/packages/AWSSDK.S3)
+ [Amazon.Extensions.S3.Encryption](https://www.nuget.org/packages/Amazon.Extensions.S3.Encryption)

## Pré-requisitos
<a name="w2aac19c15c25b7"></a>

Antes de começar, verifique se você [configurou seu ambiente](net-dg-config.md) e [configurou seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

## Exemplos neste documento
<a name="s3-apis-examples"></a>

Os tópicos a seguir neste documento mostram como usar o AWS SDK para .NET para trabalhar com o Amazon S3.
+ [Usar chaves KMS para a criptografia do S3](kms-keys-s3-encryption.md)

## Exemplos em outros documentos
<a name="s3-apis-examples-other"></a>

Os links a seguir para o [Amazon S3 Developer Guide](https://docs.aws.amazon.com/AmazonS3/latest/userguide/) fornecem exemplos adicionais de como usar o AWS SDK para .NET para trabalhar com o Amazon S3.

**nota**  
Embora esses exemplos e considerações adicionais de programação tenham sido criados para a versão 3 do AWS SDK para .NET uso do.NET Framework, eles também são viáveis para versões posteriores do AWS SDK para .NET uso do.NET Core. Às vezes, pequenos ajustes no código são necessários.

**Exemplos de programação do Amazon S3**
+  [Gerenciando ACLs](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-using-dot-net-sdk.html) 
+  [Criação de um bucket](https://docs.aws.amazon.com/AmazonS3/latest/dev/create-bucket-get-location-example.html#create-bucket-get-location-dotnet) 
+  [Upload de um objeto](https://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjSingleOpNET.html) 
+  [https://docs.aws.amazon.com/AmazonS3/latest/dev/usingHLmpuDotNet.html](https://docs.aws.amazon.com/AmazonS3/latest/dev/usingHLmpuDotNet.html)) 
+  [Multipart Upload com a API de baixo nível](https://docs.aws.amazon.com/AmazonS3/latest/dev/usingLLmpuDotNet.html) 
+  [Listar objetos](https://docs.aws.amazon.com/AmazonS3/latest/dev/list-obj-version-enabled-bucket.html#list-obj-version-enabled-bucket-sdk-examples) 
+  [Chaves de listagem](https://docs.aws.amazon.com/AmazonS3/latest/dev/ListingObjectKeysUsingNetSDK.html) 
+  [Obter um objeto](https://docs.aws.amazon.com/AmazonS3/latest/dev/RetrievingObjectUsingNetSDK.html) 
+  [Copiar um objeto](https://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjectUsingNetSDK.html) 
+  [Copiar um objeto com a API do Multipart Upload](https://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjctsUsingLLNetMPUapi.html) 
+  [Exclusão de um objeto](https://docs.aws.amazon.com/AmazonS3/latest/dev/DeletingOneObjectUsingNetSDK.html) 
+  [Excluir de vários objetos](https://docs.aws.amazon.com/AmazonS3/latest/dev/DeletingMultipleObjectsUsingNetSDK.html) 
+  [Restaurar um objeto](https://docs.aws.amazon.com/AmazonS3/latest/dev/restore-object-dotnet.html) 
+  [Configurar um bucket para notificações](https://docs.aws.amazon.com/AmazonS3/latest/dev/ways-to-add-notification-config-to-bucket.html) 
+  [Gerenciar o ciclo de vida de um objeto](https://docs.aws.amazon.com/AmazonS3/latest/dev/manage-lifecycle-using-dot-net.html) 
+  [Gerenciar um URL de objeto pré-assinado](https://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURLDotNetSDK.html) 
+  [Gerenciamento de sites](https://docs.aws.amazon.com/AmazonS3/latest/dev/ConfigWebSiteDotNet.html) 
+  [Ativação do compartilhamento de recursos de origem cruzada (CORS)](https://docs.aws.amazon.com/AmazonS3/latest/dev/ManageCorsUsingDotNet.html) 

**Considerações adicionais sobre programação**
+  [Usar o AWS SDK para .NET para o Amazon S3 Programming](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingTheMPDotNetAPI.html) 
+  [Fazer solicitações usando as credenciais temporárias do usuário do IAM](https://docs.aws.amazon.com/AmazonS3/latest/dev/AuthUsingTempSessionTokenDotNet.html) 
+  [Fazer solicitações usando as credenciais temporárias de usuário federado](https://docs.aws.amazon.com/AmazonS3/latest/dev/AuthUsingTempFederationTokenDotNet.html) 
+  [Especificar a criptografia no lado do servidor](https://docs.aws.amazon.com/AmazonS3/latest/dev/SSEUsingDotNetSDK.html) 
+  [Especificar a criptografia do lado do servidor com chaves de criptografia fornecidas pelo cliente](https://docs.aws.amazon.com/AmazonS3/latest/dev/sse-c-using-dot-net-sdk.html) 

# Usando AWS KMS chaves para criptografia do Amazon S3 no AWS SDK para .NET
<a name="kms-keys-s3-encryption"></a>

Este exemplo mostra como usar AWS Key Management Service chaves para criptografar objetos do Amazon S3. O aplicativo cria uma chave mestra do cliente (CMK) e a usa para criar um objeto [AmazonS3 EncryptionClient V2](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.AmazonS3EncryptionClientV2.html) para criptografia do lado do cliente. O aplicativo usa esse cliente para criar um objeto criptografado a partir de um determinado arquivo de texto em um bucket existente do Amazon S3. Em seguida, ele descriptografa o objeto e exibe seu conteúdo.

**Atenção**  
Uma classe similar chamada `AmazonS3EncryptionClient` está obsoleta e é menos segura do que a classe `AmazonS3EncryptionClientV2`. Para migrar o código existente que usa `AmazonS3EncryptionClient`, consulte [Migração do cliente de criptografia S3 (V1 para V2)](s3-encryption-migration-v1-v2.md).

**Topics**
+ [Criar materiais de criptografia](#kms-s3-enc-mat)
+ [Criar e criptografar um objeto do Amazon S3](#kms-s3-create-ojbect)
+ [Código completo](#kms-s3-complete-code)
+ [Considerações adicionais](#kms-s3-additional)

## Criar materiais de criptografia
<a name="kms-s3-enc-mat"></a>

O trecho a seguir cria um objeto `EncryptionMaterials` que contém uma ID de chave KMS.

O exemplo [no final deste tópico](#kms-s3-complete-code) mostra o snippet em uso.

```
      // Create a customer master key (CMK) and store the result
      CreateKeyResponse createKeyResponse =
        await new AmazonKeyManagementServiceClient().CreateKeyAsync(new CreateKeyRequest());
      var kmsEncryptionContext = new Dictionary<string, string>();
      var kmsEncryptionMaterials = new EncryptionMaterialsV2(
        createKeyResponse.KeyMetadata.KeyId, KmsType.KmsContext, kmsEncryptionContext);
```

## Criar e criptografar um objeto do Amazon S3
<a name="kms-s3-create-ojbect"></a>

O snippet a seguir cria um objeto `AmazonS3EncryptionClientV2` que usa os materiais de criptografia criados anteriormente. Em seguida, ele usa o cliente para criar e criptografar um novo objeto do Amazon S3.

O exemplo [no final deste tópico](#kms-s3-complete-code) mostra o snippet em uso.

```
    //
    // Method to create and encrypt an object in an S3 bucket
    static async Task<GetObjectResponse> CreateAndRetrieveObjectAsync(
      EncryptionMaterialsV2 materials, string bucketName,
      string fileName, string itemName)
    {
      // CryptoStorageMode.ObjectMetadata is required for KMS EncryptionMaterials
      var config = new AmazonS3CryptoConfigurationV2(SecurityProfile.V2AndLegacy)
      {
        StorageMode = CryptoStorageMode.ObjectMetadata
      };
      var s3EncClient = new AmazonS3EncryptionClientV2(config, materials);

      // Create, encrypt, and put the object
      await s3EncClient.PutObjectAsync(new PutObjectRequest
      {
        BucketName = bucketName,
        Key = itemName,
        ContentBody = File.ReadAllText(fileName)
      });

      // Get, decrypt, and return the object
      return await s3EncClient.GetObjectAsync(new GetObjectRequest
      {
        BucketName = bucketName,
        Key = itemName
      });
    }
```

## Código completo
<a name="kms-s3-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c25c13c15b5b1"></a>

NuGet pacotes:
+ [Amazon.Extensions.S3.Encryption](https://www.nuget.org/packages/Amazon.Extensions.S3.Encryption)

Elementos de programação:
+ Namespace [Amazon.Extensions.S3.Encryption](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.html)

  Classe [EncryptionClientAmazonS3](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.AmazonS3EncryptionClientV2.html) V2

  Classe [CryptoConfigurationAmazonS3](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.AmazonS3CryptoConfigurationV2.html) V2

  Classe [CryptoStorageMode](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.CryptoStorageMode.html)

  Classe [EncryptionMaterialsV2](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.EncryptionMaterialsV2.html)
+ Namespace [Amazon.Extensions.S3.Encryption.Primitives](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.Primitives.html)

  Classe [KmsType](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.Primitives.KmsType.html)
+ Namespace [Amazon.S3.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/NS3Model.html)

  Classe [GetObjectRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectRequest.html)

  Classe [GetObjectResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectResponse.html)

  Classe [PutObjectRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TPutObjectRequest.html)
+ [Namespace Amazon. KeyManagementService](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/NKeyManagementService.html)

  Classe [AmazonKeyManagementServiceClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/TKeyManagementServiceClient.html)
+ [Namespace Amazon. KeyManagementService.Modelo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/NKeyManagementServiceModel.html)

  Classe [CreateKeyRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/TCreateKeyRequest.html)

  Classe [CreateKeyResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/KeyManagementService/TCreateKeyResponse.html)

### O código
<a name="w2aac19c15c25c13c15b7b1"></a>

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Amazon.Extensions.S3.Encryption;
using Amazon.Extensions.S3.Encryption.Primitives;
using Amazon.S3.Model;
using Amazon.KeyManagementService;
using Amazon.KeyManagementService.Model;

namespace KmsS3Encryption
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to store text in an encrypted S3 object.
  class Program
  {
    private const int MaxArgs = 3;

    public static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if((parsedArgs.Count == 0) || (parsedArgs.Count > MaxArgs))
      {
        PrintHelp();
        return;
      }

      // Get the application arguments from the parsed list
      string bucketName =
        CommandLine.GetArgument(parsedArgs, null, "-b", "--bucket-name");
      string fileName =
        CommandLine.GetArgument(parsedArgs, null, "-f", "--file-name");
      string itemName =
        CommandLine.GetArgument(parsedArgs, null, "-i", "--item-name");
      if(string.IsNullOrEmpty(bucketName) || (string.IsNullOrEmpty(fileName)))
        CommandLine.ErrorExit(
          "\nOne or more of the required arguments is missing or incorrect." +
          "\nRun the command with no arguments to see help.");
      if(!File.Exists(fileName))
        CommandLine.ErrorExit($"\nThe given file {fileName} doesn't exist.");
      if(string.IsNullOrEmpty(itemName))
        itemName = Path.GetFileName(fileName);

      // Create a customer master key (CMK) and store the result
      CreateKeyResponse createKeyResponse =
        await new AmazonKeyManagementServiceClient().CreateKeyAsync(new CreateKeyRequest());
      var kmsEncryptionContext = new Dictionary<string, string>();
      var kmsEncryptionMaterials = new EncryptionMaterialsV2(
        createKeyResponse.KeyMetadata.KeyId, KmsType.KmsContext, kmsEncryptionContext);

      // Create the object in the bucket, then display the content of the object
      var putObjectResponse =
        await CreateAndRetrieveObjectAsync(kmsEncryptionMaterials, bucketName, fileName, itemName);
      Stream stream = putObjectResponse.ResponseStream;
      StreamReader reader = new StreamReader(stream);
      Console.WriteLine(reader.ReadToEnd());
    }


    //
    // Method to create and encrypt an object in an S3 bucket
    static async Task<GetObjectResponse> CreateAndRetrieveObjectAsync(
      EncryptionMaterialsV2 materials, string bucketName,
      string fileName, string itemName)
    {
      // CryptoStorageMode.ObjectMetadata is required for KMS EncryptionMaterials
      var config = new AmazonS3CryptoConfigurationV2(SecurityProfile.V2AndLegacy)
      {
        StorageMode = CryptoStorageMode.ObjectMetadata
      };
      var s3EncClient = new AmazonS3EncryptionClientV2(config, materials);

      // Create, encrypt, and put the object
      await s3EncClient.PutObjectAsync(new PutObjectRequest
      {
        BucketName = bucketName,
        Key = itemName,
        ContentBody = File.ReadAllText(fileName)
      });

      // Get, decrypt, and return the object
      return await s3EncClient.GetObjectAsync(new GetObjectRequest
      {
        BucketName = bucketName,
        Key = itemName
      });
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
        "\nUsage: KmsS3Encryption -b <bucket-name> -f <file-name> [-i <item-name>]" +
        "\n  -b, --bucket-name: The name of an existing S3 bucket." +
        "\n  -f, --file-name: The name of a text file with content to encrypt and store in S3." +
        "\n  -i, --item-name: The name you want to use for the item." +
        "\n      If item-name isn't given, file-name will be used.");
    }

  }

  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## Considerações adicionais
<a name="kms-s3-additional"></a>
+ Você pode verificar os resultados desse exemplo. Para fazer isso, acesse o [console do Amazon S3](https://console.aws.amazon.com/s3) e abra o bucket que você forneceu à aplicação. Em seguida, encontre o novo objeto, baixe-o e abra-o em um editor de texto.
+ A classe [AmazonS3 EncryptionClient V2](https://aws.github.io/amazon-s3-encryption-client-dotnet/api/Amazon.Extensions.S3.Encryption.AmazonS3EncryptionClientV2.html) implementa a mesma interface da classe padrão. `AmazonS3Client` Isso facilita a portabilidade do código para a classe `AmazonS3EncryptionClientV2` de modo que a criptografia e a descriptografia ocorram automaticamente e de maneira transparente no cliente.
+ Uma vantagem de usar uma AWS KMS chave como chave mestra é que você não precisa armazenar e gerenciar suas próprias chaves mestras; isso é feito por AWS. Uma segunda vantagem é que a `AmazonS3EncryptionClientV2` classe do AWS SDK para .NET é interoperável com a `AmazonS3EncryptionClientV2` classe do. AWS SDK para Java Isso significa que você pode criptografar com o AWS SDK para Java e descriptografar com o AWS SDK para .NET e vice-versa.
**nota**  
A `AmazonS3EncryptionClientV2` classe do AWS SDK para .NET suporta chaves mestras do KMS somente quando executada no modo de metadados. O modo do arquivo de instruções da `AmazonS3EncryptionClientV2` classe do AWS SDK para .NET é incompatível com a `AmazonS3EncryptionClientV2` classe do AWS SDK para Java.
+ Para obter mais informações sobre a criptografia do lado do cliente com a `AmazonS3EncryptionClientV2` classe e como a criptografia de envelope funciona, consulte Criptografia de [dados do lado do cliente com o Amazon AWS SDK para .NET S3](https://aws.amazon.com/blogs/developer/client-side-data-encryption-with-aws-sdk-for-net-and-amazon-s3/).

# Enviar notificações da nuvem usando o Amazon Simple Notification Service
<a name="sns-apis-intro"></a>

**nota**  
As informações neste tópico são específicas para projetos baseados no.NET Framework e na AWS SDK para .NET versão 3.3 e anteriores.

O é AWS SDK para .NET compatível com o Amazon Simple Notification Service (Amazon SNS), que é um serviço web que permite que aplicativos, usuários finais e dispositivos enviem notificações instantaneamente da nuvem. Para obter mais informações, consulte [Amazon SNS](https://aws.amazon.com/sns/).

## Listar seus tópicos do Amazon SNS
<a name="sns-list-example"></a>

O exemplo a seguir mostra como listar os tópicos do Amazon SNS, as assinaturas de cada tópico e os atributos de cada tópico. Este exemplo usa o padrão [AmazonSimpleNotificationServiceClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SNS/TSNSClient.html).

```
// using Amazon.SimpleNotificationService;
// using Amazon.SimpleNotificationService.Model;

var client = new AmazonSimpleNotificationServiceClient();
var request = new ListTopicsRequest();
var response = new ListTopicsResponse();

do
{
  response = client.ListTopics(request);

  foreach (var topic in response.Topics)
  {
    Console.WriteLine("Topic: {0}", topic.TopicArn);

    var subs = client.ListSubscriptionsByTopic(
      new ListSubscriptionsByTopicRequest
      {
        TopicArn = topic.TopicArn
      });

    var ss = subs.Subscriptions;

    if (ss.Any())
    {
      Console.WriteLine("  Subscriptions:");

      foreach (var sub in ss)
      {
        Console.WriteLine("    {0}", sub.SubscriptionArn);
      }
    }

    var attrs = client.GetTopicAttributes(
      new GetTopicAttributesRequest
      {
        TopicArn = topic.TopicArn
      }).Attributes;

    if (attrs.Any())
    {
      Console.WriteLine("  Attributes:");

      foreach (var attr in attrs)
      {
        Console.WriteLine("    {0} = {1}", attr.Key, attr.Value);
      }
    }

    Console.WriteLine();
  }

  request.NextToken = response.NextToken;

} while (!string.IsNullOrEmpty(response.NextToken));
```

## Enviar uma mensagem para um tópico do Amazon SNS
<a name="sns-send-message-example"></a>

O exemplo a seguir mostra como enviar uma mensagem para um tópico do SNS. O exemplo usa um argumento, o ARN do tópico do Amazon SNS.

```
using System;
using System.Linq;
using System.Threading.Tasks;

using Amazon;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;

namespace SnsSendMessage
{
    class Program
    {
        static void Main(string[] args)
        {
            /* Topic ARNs must be in the correct format:
             *   arn:aws:sns:REGION:ACCOUNT_ID:NAME
             *
             *  where:
             *  REGION     is the region in which the topic is created, such as us-west-2
             *  ACCOUNT_ID is your (typically) 12-character account ID
             *  NAME       is the name of the topic
             */
            string topicArn = args[0];
            string message = "Hello at " + DateTime.Now.ToShortTimeString();

            var client = new AmazonSimpleNotificationServiceClient(region: Amazon.RegionEndpoint.USWest2);

            var request = new PublishRequest
            {
                Message = message,
                TopicArn = topicArn
            };

            try
            {
                var response = client.Publish(request);

                Console.WriteLine("Message sent to topic:");
                Console.WriteLine(message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught exception publishing request:");
                Console.WriteLine(ex.Message);
            }
        }
    }
}
```

Veja o [exemplo completo](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/.dotnet/example_code_legacy/SNS/SnsSendMessage.cs), incluindo informações sobre como criar e executar o exemplo na linha de comando, em GitHub.

## Enviar uma mensagem SMS para um número de telefone
<a name="sns-send-sms-example"></a>

O exemplo a seguir mostra como enviar uma mensagem SMS para um número de telefone. O exemplo usa um argumento, o número de telefone, que deve estar em um dos dois formatos descritos nos comentários.

```
using System;
using System.Linq;
using System.Threading.Tasks;
using Amazon;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;

namespace SnsPublish
{
    class Program
    {
        static void Main(string[] args)
        {
            // US phone numbers must be in the correct format:
            // +1 (nnn) nnn-nnnn OR +1nnnnnnnnnn
            string number = args[0];
            string message = "Hello at " + DateTime.Now.ToShortTimeString();

            var client = new AmazonSimpleNotificationServiceClient(region: Amazon.RegionEndpoint.USWest2);
            var request = new PublishRequest
            {
                Message = message,
                PhoneNumber = number
            };

            try
            {
                var response = client.Publish(request);

                Console.WriteLine("Message sent to " + number + ":");
                Console.WriteLine(message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught exception publishing request:");
                Console.WriteLine(ex.Message);
            }
        }
    }
}
```

Veja o [exemplo completo](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/.dotnet/example_code_legacy/SNS/SnsPublish.cs), incluindo informações sobre como criar e executar o exemplo na linha de comando, em GitHub.

# Enviar mensagens usando o Amazon SQS
<a name="sqs-apis-intro"></a>

O AWS SDK para .NET suporta o [Amazon Simple Queue Service (Amazon SQS), que é um serviço](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/) de enfileiramento de mensagens que manipula mensagens ou fluxos de trabalho entre componentes em um sistema.

As filas do Amazon SQS fornecem um mecanismo que permite enviar, armazenar e receber mensagens entre componentes de software, como microsserviços, sistemas distribuídos e aplicações sem servidor. Isso permite desacoplar esses componentes e você fica da necessidade de projetar e operar seu próprio sistema de mensagens. Para ter informações sobre como as filas e mensagens funcionam no Amazon SQS, consulte os [tutoriais do Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-other-tutorials.html) e [Arquitetura básica do Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-basic-architecture.html) no [Guia do desenvolvedor do Amazon Simple Queue Service](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/).

**Importante**  
Devido à natureza distribuída da fila, o Amazon SQS não garante que as mensagens serão recebidas na ordem exata de envio. Se for necessário manter a ordem de mensagens, use uma [fila FIFO do Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-fifo-queues.html).

## APIs
<a name="w2aac19c15c29b9"></a>

 AWS SDK para .NET Ele fornece APIs para clientes do Amazon SQS. Eles APIs permitem que você trabalhe com recursos do Amazon SQS, como filas e mensagens. Esta seção contém um pequeno número de exemplos que mostram os padrões que você pode seguir ao trabalhar com eles APIs. Para ver o conjunto completo de APIs, consulte a [Referência da AWS SDK para .NET API](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/) (e vá até “Amazon.sqs”).

O Amazon SQS é fornecido pelo APIs [AWSSDK NuGet pacote.SQS](https://www.nuget.org/packages/AWSSDK.SQS).

## Pré-requisitos
<a name="w2aac19c15c29c11"></a>

Antes de começar, verifique se você [configurou seu ambiente](net-dg-config.md) e [configurou seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

## Tópicos
<a name="w2aac19c15c29c13"></a>

**Topics**
+ [APIs](#w2aac19c15c29b9)
+ [Pré-requisitos](#w2aac19c15c29c11)
+ [Tópicos](#w2aac19c15c29c13)
+ [Criação de filas](CreateQueue.md)
+ [Atualizando filas](UpdateSqsQueue.md)
+ [Excluindo filas](DeleteSqsQueue.md)
+ [Enviar mensagens](SendMessage.md)
+ [Recebimento de mensagens](ReceiveMessage.md)

# Criação de fila no Amazon SQS
<a name="CreateQueue"></a>

Este exemplo mostra como usar o AWS SDK para .NET para criar uma fila do Amazon SQS. O aplicação cria uma [fila de mensagens não entregues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html) se você não fornecer o ARN para uma. Em seguida, ele cria uma fila de mensagens padrão, que inclui uma fila de mensagens não entregues (a que você forneceu ou a que foi criada).

Se você não fornecer nenhum argumento de linha de comando, a aplicação simplesmente mostrará informações sobre todas as filas existentes.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#CreateQueue-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Mostrar filas existentes](#CreateQueue-show-queues)
+ [Criação da fila](#CreateQueue-create-queue)
+ [Obtenha o ARN de uma fila](#CreateQueue-get-arn)
+ [Código completo](#CreateQueue-complete-code)
+ [Considerações adicionais](#CreateQueue-additional)

## Mostrar filas existentes
<a name="CreateQueue-show-queues"></a>

O trecho a seguir mostra uma lista das filas existentes na região do cliente SQS e os atributos de cada fila.

O exemplo [no final deste tópico](#CreateQueue-complete-code) mostra o snippet em uso.

```
    //
    // Method to show a list of the existing queues
    private static async Task ShowQueues(IAmazonSQS sqsClient)
    {
      ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
      Console.WriteLine();
      foreach(string qUrl in responseList.QueueUrls)
      {
        // Get and show all attributes. Could also get a subset.
        await ShowAllAttributes(sqsClient, qUrl);
      }
    }

    //
    // Method to show all attributes of a queue
    private static async Task ShowAllAttributes(IAmazonSQS sqsClient, string qUrl)
    {
      var attributes = new List<string>{ QueueAttributeName.All };
      GetQueueAttributesResponse responseGetAtt =
        await sqsClient.GetQueueAttributesAsync(qUrl, attributes);
      Console.WriteLine($"Queue: {qUrl}");
      foreach(var att in responseGetAtt.Attributes)
        Console.WriteLine($"\t{att.Key}: {att.Value}");
    }
```

## Criação da fila
<a name="CreateQueue-create-queue"></a>

O seguinte snippet cria uma fila. O trecho inclui o uso de uma fila de mensagens não entregues, mas uma fila de mensagens não entregues não é necessariamente necessária para suas filas.

O exemplo [no final deste tópico](#CreateQueue-complete-code) mostra o snippet em uso.

```
    //
    // Method to create a queue. Returns the queue URL.
    private static async Task<string> CreateQueue(
      IAmazonSQS sqsClient, string qName, string deadLetterQueueUrl=null,
      string maxReceiveCount=null, string receiveWaitTime=null)
    {
      var attrs = new Dictionary<string, string>();

      // If a dead-letter queue is given, create a message queue
      if(!string.IsNullOrEmpty(deadLetterQueueUrl))
      {
        attrs.Add(QueueAttributeName.ReceiveMessageWaitTimeSeconds, receiveWaitTime);
        attrs.Add(QueueAttributeName.RedrivePolicy,
          $"{{\"deadLetterTargetArn\":\"{await GetQueueArn(sqsClient, deadLetterQueueUrl)}\"," +
          $"\"maxReceiveCount\":\"{maxReceiveCount}\"}}");
        // Add other attributes for the message queue such as VisibilityTimeout
      }

      // If no dead-letter queue is given, create one of those instead
      //else
      //{
      //  // Add attributes for the dead-letter queue as needed
      //  attrs.Add();
      //}

      // Create the queue
      CreateQueueResponse responseCreate = await sqsClient.CreateQueueAsync(
          new CreateQueueRequest{QueueName = qName, Attributes = attrs});
      return responseCreate.QueueUrl;
    }
```

## Obtenha o ARN de uma fila
<a name="CreateQueue-get-arn"></a>

O snippet a seguir obtém o ARN da fila identificada pelo URL da fila em questão.

O exemplo [no final deste tópico](#CreateQueue-complete-code) mostra o snippet em uso.

```
    //
    // Method to get the ARN of a queue
    private static async Task<string> GetQueueArn(IAmazonSQS sqsClient, string qUrl)
    {
      GetQueueAttributesResponse responseGetAtt = await sqsClient.GetQueueAttributesAsync(
        qUrl, new List<string>{QueueAttributeName.QueueArn});
      return responseGetAtt.QueueARN;
    }
```

## Código completo
<a name="CreateQueue-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c29c17c25b5b1"></a>

NuGet pacotes:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

Elementos de programação:
+ Namespace [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  Classe [Amazon SQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)

  Classe [QueueAttributeName](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TQueueAttributeName.html)
+ Namespace [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  Classe [CreateQueueRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TCreateQueueRequest.html)

  Classe [CreateQueueResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TCreateQueueResponse.html)

  Classe [GetQueueAttributesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TGetQueueAttributesResponse.html)

  Classe [ListQueuesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TListQueuesResponse.html)

### O código
<a name="w2aac19c15c29c17c25b7b1"></a>

```
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSCreateQueue
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to create a queue
  class Program
  {
    private const string MaxReceiveCount = "10";
    private const string ReceiveMessageWaitTime = "2";
    private const int MaxArgs = 3;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count > MaxArgs)
        CommandLine.ErrorExit(
          "\nToo many command-line arguments.\nRun the command with no arguments to see help.");

      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // In the case of no command-line arguments, just show help and the existing queues
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        Console.WriteLine("\nNo arguments specified.");
        Console.Write("Do you want to see a list of the existing queues? ((y) or n): ");
        string response = Console.ReadLine();
        if((string.IsNullOrEmpty(response)) || (response.ToLower() == "y"))
          await ShowQueues(sqsClient);
        return;
      }

      // Get the application arguments from the parsed list
      string queueName =
        CommandLine.GetArgument(parsedArgs, null, "-q", "--queue-name");
      string deadLetterQueueUrl =
        CommandLine.GetArgument(parsedArgs, null, "-d", "--dead-letter-queue");
      string maxReceiveCount =
        CommandLine.GetArgument(parsedArgs, MaxReceiveCount, "-m", "--max-receive-count");
      string receiveWaitTime =
        CommandLine.GetArgument(parsedArgs, ReceiveMessageWaitTime, "-w", "--wait-time");

      if(string.IsNullOrEmpty(queueName))
        CommandLine.ErrorExit(
          "\nYou must supply a queue name.\nRun the command with no arguments to see help.");

      // If a dead-letter queue wasn't given, create one
      if(string.IsNullOrEmpty(deadLetterQueueUrl))
      {
        Console.WriteLine("\nNo dead-letter queue was specified. Creating one...");
        deadLetterQueueUrl = await CreateQueue(sqsClient, queueName + "__dlq");
        Console.WriteLine($"Your new dead-letter queue:");
        await ShowAllAttributes(sqsClient, deadLetterQueueUrl);
      }

      // Create the message queue
      string messageQueueUrl = await CreateQueue(
        sqsClient, queueName, deadLetterQueueUrl, maxReceiveCount, receiveWaitTime);
      Console.WriteLine($"Your new message queue:");
      await ShowAllAttributes(sqsClient, messageQueueUrl);
    }


    //
    // Method to show a list of the existing queues
    private static async Task ShowQueues(IAmazonSQS sqsClient)
    {
      ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
      Console.WriteLine();
      foreach(string qUrl in responseList.QueueUrls)
      {
        // Get and show all attributes. Could also get a subset.
        await ShowAllAttributes(sqsClient, qUrl);
      }
    }


    //
    // Method to create a queue. Returns the queue URL.
    private static async Task<string> CreateQueue(
      IAmazonSQS sqsClient, string qName, string deadLetterQueueUrl=null,
      string maxReceiveCount=null, string receiveWaitTime=null)
    {
      var attrs = new Dictionary<string, string>();

      // If a dead-letter queue is given, create a message queue
      if(!string.IsNullOrEmpty(deadLetterQueueUrl))
      {
        attrs.Add(QueueAttributeName.ReceiveMessageWaitTimeSeconds, receiveWaitTime);
        attrs.Add(QueueAttributeName.RedrivePolicy,
          $"{{\"deadLetterTargetArn\":\"{await GetQueueArn(sqsClient, deadLetterQueueUrl)}\"," +
          $"\"maxReceiveCount\":\"{maxReceiveCount}\"}}");
        // Add other attributes for the message queue such as VisibilityTimeout
      }

      // If no dead-letter queue is given, create one of those instead
      //else
      //{
      //  // Add attributes for the dead-letter queue as needed
      //  attrs.Add();
      //}

      // Create the queue
      CreateQueueResponse responseCreate = await sqsClient.CreateQueueAsync(
          new CreateQueueRequest{QueueName = qName, Attributes = attrs});
      return responseCreate.QueueUrl;
    }


    //
    // Method to get the ARN of a queue
    private static async Task<string> GetQueueArn(IAmazonSQS sqsClient, string qUrl)
    {
      GetQueueAttributesResponse responseGetAtt = await sqsClient.GetQueueAttributesAsync(
        qUrl, new List<string>{QueueAttributeName.QueueArn});
      return responseGetAtt.QueueARN;
    }


    //
    // Method to show all attributes of a queue
    private static async Task ShowAllAttributes(IAmazonSQS sqsClient, string qUrl)
    {
      var attributes = new List<string>{ QueueAttributeName.All };
      GetQueueAttributesResponse responseGetAtt =
        await sqsClient.GetQueueAttributesAsync(qUrl, attributes);
      Console.WriteLine($"Queue: {qUrl}");
      foreach(var att in responseGetAtt.Attributes)
        Console.WriteLine($"\t{att.Key}: {att.Value}");
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine(
      "\nUsage: SQSCreateQueue -q <queue-name> [-d <dead-letter-queue>]" +
        " [-m <max-receive-count>] [-w <wait-time>]" +
      "\n  -q, --queue-name: The name of the queue you want to create." +
      "\n  -d, --dead-letter-queue: The URL of an existing queue to be used as the dead-letter queue."+
      "\n      If this argument isn't supplied, a new dead-letter queue will be created." +
      "\n  -m, --max-receive-count: The value for maxReceiveCount in the RedrivePolicy of the queue." +
      $"\n      Default is {MaxReceiveCount}." +
      "\n  -w, --wait-time: The value for ReceiveMessageWaitTimeSeconds of the queue for long polling." +
      $"\n      Default is {ReceiveMessageWaitTime}.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## Considerações adicionais
<a name="CreateQueue-additional"></a>
+ O nome da fila deve ser composto de caracteres alfanuméricos, hifens e sublinhados.
+ Os nomes das filas e as filas diferenciam maiúsculas de URLs minúsculas
+ Se precisar do URL da fila, mas tiver apenas o nome da fila, use um dos `AmazonSQSClient.GetQueueUrlAsync` métodos.
+ Para obter informações sobre os vários atributos de fila que você pode definir, consulte [CreateQueueRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TCreateQueueRequest.html)na Referência da [AWS SDK para .NET API ou [SetQueueAttributes](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SetQueueAttributes.html)na Referência](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/) da [API do Amazon Simple Queue Service](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/).
+ Este exemplo especifica uma sondagem longa para todas as mensagens na fila que você cria. Isto é feito usando o atributo `ReceiveMessageWaitTimeSeconds`.

  Você também pode especificar uma sondagem longa durante uma chamada para os `ReceiveMessageAsync` métodos da SQSClient classe [Amazon](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html). Para obter mais informações, consulte [Recebimento de mensagens do Amazon SQS](ReceiveMessage.md).

  Para obter informações sobre sondagem curta versus sondagem longa, consulte [Sondagem curta e longa](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html) no *Guia do desenvolvedor do Amazon Simple Queue Service*.
+ Uma fila de mensagens não entregues é aquela fila que outras filas (de origem) podem direcionar para mensagens que não foram processadas com sucesso. Para obter mais informações, consulte [filas de mensagens não entregues do Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html) no Guia do desenvolvedor do Amazon Simple Queue Service.
+ Você também pode ver a lista de filas e os resultados desse exemplo no [console do Amazon SQS](https://console.aws.amazon.com/sqs).

# Atualizando filas do Amazon SQS
<a name="UpdateSqsQueue"></a>

Este exemplo mostra como usar o AWS SDK para .NET para atualizar uma fila do Amazon SQS. Depois de algumas verificações, a aplicação atualiza o atributo fornecido com o valor fornecido e, em seguida, mostra todos os atributos da fila.

Se somente o URL da fila estiver incluído nos argumentos da linha de comando, a aplicação simplesmente mostrará todos os atributos da fila.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#UpdateSqsQueue-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Mostrar atributos da fila](#UpdateSqsQueue-show-attributes)
+ [Validar nome do atributo](#UpdateSqsQueue-validate-attribute)
+ [Atualizar atributo de fila](#UpdateSqsQueue-update-attribute)
+ [Código completo](#UpdateSqsQueue-complete-code)
+ [Considerações adicionais](#UpdateSqsQueue-additional)

## Mostrar atributos da fila
<a name="UpdateSqsQueue-show-attributes"></a>

O snippet a seguir mostra os atributos da fila identificados pelo URL da fila em questão.

O exemplo [no final deste tópico](#UpdateSqsQueue-complete-code) mostra o snippet em uso.

```
    //
    // Method to show all attributes of a queue
    private static async Task ShowAllAttributes(IAmazonSQS sqsClient, string qUrl)
    {
      GetQueueAttributesResponse responseGetAtt =
        await sqsClient.GetQueueAttributesAsync(qUrl,
          new List<string>{ QueueAttributeName.All });
      Console.WriteLine($"Queue: {qUrl}");
      foreach(var att in responseGetAtt.Attributes)
        Console.WriteLine($"\t{att.Key}: {att.Value}");
    }
```

## Validar nome do atributo
<a name="UpdateSqsQueue-validate-attribute"></a>

O snippet a seguir valida o nome do atributo que está sendo atualizado.

O exemplo [no final deste tópico](#UpdateSqsQueue-complete-code) mostra o snippet em uso.

```
    //
    // Method to check the name of the attribute
    private static bool ValidAttribute(string attribute)
    {
      var attOk = false;
      var qAttNameType = typeof(QueueAttributeName);
      List<string> qAttNamefields = new List<string>();
      foreach(var field in qAttNameType.GetFields())
       qAttNamefields.Add(field.Name);
      foreach(var name in qAttNamefields)
        if(attribute == name) { attOk = true; break; }
      return attOk;
    }
```

## Atualizar atributo de fila
<a name="UpdateSqsQueue-update-attribute"></a>

O snippet a seguir atualiza um atributo da fila identificado pelo URL da fila em questão.

O exemplo [no final deste tópico](#UpdateSqsQueue-complete-code) mostra o snippet em uso.

```
    //
    // Method to update a queue attribute
    private static async Task UpdateAttribute(
      IAmazonSQS sqsClient, string qUrl, string attribute, string value)
    {
      await sqsClient.SetQueueAttributesAsync(qUrl,
        new Dictionary<string, string>{{attribute, value}});
    }
```

## Código completo
<a name="UpdateSqsQueue-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c29c19c25b5b1"></a>

NuGet pacotes:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

Elementos de programação:
+ Namespace [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  Classe [Amazon SQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)

  Classe [QueueAttributeName](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TQueueAttributeName.html)
+ Namespace [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  Classe [GetQueueAttributesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TGetQueueAttributesResponse.html)

### O código
<a name="w2aac19c15c29c19c25b7b1"></a>

```
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSUpdateQueue
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to update a queue
  class Program
  {
    private const int MaxArgs = 3;
    private const int InvalidArgCount = 2;

    static async Task Main(string[] args)
    {
      // Parse the command line and show help if necessary
      var parsedArgs = CommandLine.Parse(args);
      if(parsedArgs.Count == 0)
      {
        PrintHelp();
        return;
      }
      if((parsedArgs.Count > MaxArgs) || (parsedArgs.Count == InvalidArgCount))
        CommandLine.ErrorExit("\nThe number of command-line arguments is incorrect." +
          "\nRun the command with no arguments to see help.");

      // Get the application arguments from the parsed list
      var qUrl = CommandLine.GetArgument(parsedArgs, null, "-q");
      var attribute = CommandLine.GetArgument(parsedArgs, null, "-a");
      var value = CommandLine.GetArgument(parsedArgs, null, "-v", "--value");

      if(string.IsNullOrEmpty(qUrl))
        CommandLine.ErrorExit("\nYou must supply at least a queue URL." +
          "\nRun the command with no arguments to see help.");

      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // In the case of one command-line argument, just show the attributes for the queue
      if(parsedArgs.Count == 1)
        await ShowAllAttributes(sqsClient, qUrl);

      // Otherwise, attempt to update the given queue attribute with the given value
      else
      {
        // Check to see if the attribute is valid
        if(ValidAttribute(attribute))
        {
          // Perform the update and then show all the attributes of the queue
          await UpdateAttribute(sqsClient, qUrl, attribute, value);
          await ShowAllAttributes(sqsClient, qUrl);
        }
        else
        {
          Console.WriteLine($"\nThe given attribute name, {attribute}, isn't valid.");
        }
      }
    }


    //
    // Method to show all attributes of a queue
    private static async Task ShowAllAttributes(IAmazonSQS sqsClient, string qUrl)
    {
      GetQueueAttributesResponse responseGetAtt =
        await sqsClient.GetQueueAttributesAsync(qUrl,
          new List<string>{ QueueAttributeName.All });
      Console.WriteLine($"Queue: {qUrl}");
      foreach(var att in responseGetAtt.Attributes)
        Console.WriteLine($"\t{att.Key}: {att.Value}");
    }


    //
    // Method to check the name of the attribute
    private static bool ValidAttribute(string attribute)
    {
      var attOk = false;
      var qAttNameType = typeof(QueueAttributeName);
      List<string> qAttNamefields = new List<string>();
      foreach(var field in qAttNameType.GetFields())
       qAttNamefields.Add(field.Name);
      foreach(var name in qAttNamefields)
        if(attribute == name) { attOk = true; break; }
      return attOk;
    }


    //
    // Method to update a queue attribute
    private static async Task UpdateAttribute(
      IAmazonSQS sqsClient, string qUrl, string attribute, string value)
    {
      await sqsClient.SetQueueAttributesAsync(qUrl,
        new Dictionary<string, string>{{attribute, value}});
    }


    //
    // Command-line help
    private static void PrintHelp()
    {
      Console.WriteLine("\nUsage: SQSUpdateQueue -q queue_url [-a attribute -v value]");
      Console.WriteLine("  -q: The URL of the queue you want to update.");
      Console.WriteLine("  -a: The name of the attribute to update.");
      Console.WriteLine("  -v, --value: The value to assign to the attribute.");
    }
  }


  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class that represents a command line on the console or terminal.
  // (This is the same for all examples. When you have seen it once, you can ignore it.)
  static class CommandLine
  {
    //
    // Method to parse a command line of the form: "--key value" or "-k value".
    //
    // Parameters:
    // - args: The command-line arguments passed into the application by the system.
    //
    // Returns:
    // A Dictionary with string Keys and Values.
    //
    // If a key is found without a matching value, Dictionary.Value is set to the key
    //  (including the dashes).
    // If a value is found without a matching key, Dictionary.Key is set to "--NoKeyN",
    //  where "N" represents sequential numbers.
    public static Dictionary<string,string> Parse(string[] args)
    {
      var parsedArgs = new Dictionary<string,string>();
      int i = 0, n = 0;
      while(i < args.Length)
      {
        // If the first argument in this iteration starts with a dash it's an option.
        if(args[i].StartsWith("-"))
        {
          var key = args[i++];
          var value = key;

          // Check to see if there's a value that goes with this option?
          if((i < args.Length) && (!args[i].StartsWith("-"))) value = args[i++];
          parsedArgs.Add(key, value);
        }

        // If the first argument in this iteration doesn't start with a dash, it's a value
        else
        {
          parsedArgs.Add("--NoKey" + n.ToString(), args[i++]);
          n++;
        }
      }

      return parsedArgs;
    }

    //
    // Method to get an argument from the parsed command-line arguments
    //
    // Parameters:
    // - parsedArgs: The Dictionary object returned from the Parse() method (shown above).
    // - defaultValue: The default string to return if the specified key isn't in parsedArgs.
    // - keys: An array of keys to look for in parsedArgs.
    public static string GetArgument(
      Dictionary<string,string> parsedArgs, string defaultReturn, params string[] keys)
    {
      string retval = null;
      foreach(var key in keys)
        if(parsedArgs.TryGetValue(key, out retval)) break;
      return retval ?? defaultReturn;
    }

    //
    // Method to exit the application with an error.
    public static void ErrorExit(string msg, int code=1)
    {
      Console.WriteLine("\nError");
      Console.WriteLine(msg);
      Environment.Exit(code);
    }
  }

}
```

## Considerações adicionais
<a name="UpdateSqsQueue-additional"></a>
+ Para atualizar o `RedrivePolicy` atributo, você deve cotar o valor inteiro e escapar das aspas dos key/value pares, conforme apropriado para seu sistema operacional.

  No Windows, por exemplo, o valor é construído de forma semelhante ao seguinte:

  ```
  "{\"deadLetterTargetArn\":\"DEAD_LETTER-QUEUE-ARN\",\"maxReceiveCount\":\"10\"}"
  ```

# Excluindo filas do Amazon SQS
<a name="DeleteSqsQueue"></a>

Este exemplo mostra como usar o AWS SDK para .NET para excluir uma fila do Amazon SQS. A explicação exclui a fila, espera até um determinado período de tempo até que a fila seja excluída e, em seguida, mostra uma lista de filas restantes.

Se você não fornecer nenhum argumento de linha de comando, a aplicação simplesmente mostrará uma lista de filas existentes.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#DeleteSqsQueue-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Excluir a fila](#DeleteSqsQueue-delete-queue)
+ [Aguardar até a fila ser removida](#DeleteSqsQueue-wait)
+ [Mostrar uma lista de filas existentes](#DeleteSqsQueue-list-queues)
+ [Código completo](#DeleteSqsQueue-complete-code)
+ [Considerações adicionais](#DeleteSqsQueue-additional)

## Excluir a fila
<a name="DeleteSqsQueue-delete-queue"></a>

O snippet a seguir exclui a fila identificada pelo URL da fila em questão.

O exemplo [no final deste tópico](#DeleteSqsQueue-complete-code) mostra o snippet em uso.

```
    //
    // Method to delete an SQS queue
    private static async Task DeleteQueue(IAmazonSQS sqsClient, string qUrl)
    {
      Console.WriteLine($"Deleting queue {qUrl}...");
      await sqsClient.DeleteQueueAsync(qUrl);
      Console.WriteLine($"Queue {qUrl} has been deleted.");
    }
```

## Aguardar até a fila ser removida
<a name="DeleteSqsQueue-wait"></a>

O snippet a seguir aguarda a conclusão do processo de exclusão, o que pode levar até 60 segundos.

O exemplo [no final deste tópico](#DeleteSqsQueue-complete-code) mostra o snippet em uso.

```
    //
    // Method to wait up to a given number of seconds
    private static async Task Wait(
      IAmazonSQS sqsClient, int numSeconds, string qUrl)
    {
      Console.WriteLine($"Waiting for up to {numSeconds} seconds.");
      Console.WriteLine("Press any key to stop waiting. (Response might be slightly delayed.)");
      for(int i=0; i<numSeconds; i++)
      {
        Console.Write(".");
        Thread.Sleep(1000);
        if(Console.KeyAvailable) break;

        // Check to see if the queue is gone yet
        var found = false;
        ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
        foreach(var url in responseList.QueueUrls)
        {
          if(url == qUrl)
          {
            found = true;
            break;
          }
        }
        if(!found) break;
      }
    }
```

## Mostrar uma lista de filas existentes
<a name="DeleteSqsQueue-list-queues"></a>

O trecho a seguir mostra uma lista das filas existentes na região do cliente SQS.

O exemplo [no final deste tópico](#DeleteSqsQueue-complete-code) mostra o snippet em uso.

```
    //
    // Method to show a list of the existing queues
    private static async Task ListQueues(IAmazonSQS sqsClient)
    {
      ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
      Console.WriteLine("\nList of queues:");
      foreach(var qUrl in responseList.QueueUrls)
        Console.WriteLine($"- {qUrl}");
    }
```

## Código completo
<a name="DeleteSqsQueue-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c29c21c25b5b1"></a>

NuGet pacotes:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

Elementos de programação:
+ Namespace [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  Classe [Amazon SQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)
+ Namespace [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  Classe [ListQueuesResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TListQueuesResponse.html)

### O código
<a name="w2aac19c15c29c21c25b7b1"></a>

```
using System;
using System.Threading;
using System.Threading.Tasks;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSDeleteQueue
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to update a queue
  class Program
  {
    private const int TimeToWait = 60;

    static async Task Main(string[] args)
    {
      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // If no command-line arguments, just show a list of the queues
      if(args.Length == 0)
      {
        Console.WriteLine("\nUsage: SQSCreateQueue queue_url");
        Console.WriteLine("   queue_url - The URL of the queue you want to delete.");
        Console.WriteLine("\nNo arguments specified.");
        Console.Write("Do you want to see a list of the existing queues? ((y) or n): ");
        var response = Console.ReadLine();
        if((string.IsNullOrEmpty(response)) || (response.ToLower() == "y"))
          await ListQueues(sqsClient);
        return;
      }

      // If given a queue URL, delete that queue
      if(args[0].StartsWith("https://sqs."))
      {
        // Delete the queue
        await DeleteQueue(sqsClient, args[0]);
        // Wait for a little while because it takes a while for the queue to disappear
        await Wait(sqsClient, TimeToWait, args[0]);
        // Show a list of the remaining queues
        await ListQueues(sqsClient);
      }
      else
      {
        Console.WriteLine("The command-line argument isn't a queue URL:");
        Console.WriteLine($"{args[0]}");
      }
    }


    //
    // Method to delete an SQS queue
    private static async Task DeleteQueue(IAmazonSQS sqsClient, string qUrl)
    {
      Console.WriteLine($"Deleting queue {qUrl}...");
      await sqsClient.DeleteQueueAsync(qUrl);
      Console.WriteLine($"Queue {qUrl} has been deleted.");
    }


    //
    // Method to wait up to a given number of seconds
    private static async Task Wait(
      IAmazonSQS sqsClient, int numSeconds, string qUrl)
    {
      Console.WriteLine($"Waiting for up to {numSeconds} seconds.");
      Console.WriteLine("Press any key to stop waiting. (Response might be slightly delayed.)");
      for(int i=0; i<numSeconds; i++)
      {
        Console.Write(".");
        Thread.Sleep(1000);
        if(Console.KeyAvailable) break;

        // Check to see if the queue is gone yet
        var found = false;
        ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
        foreach(var url in responseList.QueueUrls)
        {
          if(url == qUrl)
          {
            found = true;
            break;
          }
        }
        if(!found) break;
      }
    }


    //
    // Method to show a list of the existing queues
    private static async Task ListQueues(IAmazonSQS sqsClient)
    {
      ListQueuesResponse responseList = await sqsClient.ListQueuesAsync("");
      Console.WriteLine("\nList of queues:");
      foreach(var qUrl in responseList.QueueUrls)
        Console.WriteLine($"- {qUrl}");
    }
  }
}
```

## Considerações adicionais
<a name="DeleteSqsQueue-additional"></a>
+ A chamada de API `DeleteQueueAsync` não verifica se a fila que você está excluindo está sendo usada como uma fila de mensagens não entregues. Um procedimento mais sofisticado poderia verificar isso.
+ Você também pode ver a lista de filas e os resultados desse exemplo no [console do Amazon SQS](https://console.aws.amazon.com/sqs).

# Enviando mensagens SMS do Amazon
<a name="SendMessage"></a>

[Este exemplo mostra como usar o para enviar mensagens AWS SDK para .NET para uma fila do Amazon SQS, que você pode criar [programaticamente](CreateQueue.md) ou usando o console do Amazon SQS.](https://console.aws.amazon.com/sqs) A aplicação envia uma única mensagem para a fila e, em seguida, um lote de mensagens. Em seguida, a aplicação aguarda a entrada do usuário, que pode ser mensagens adicionais para enviar para a fila ou uma solicitação para sair da aplicação.

Este exemplo e o [próximo exemplo sobre o recebimento de mensagens](ReceiveMessage.md) podem ser usados juntos para ver o fluxo de mensagens no Amazon SQS.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#SendMessage-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Enviar uma mensagem](#SendMessage-send-message)
+ [Enviar um lote de mensagens](#SendMessage-send-batch)
+ [Excluir todas as mensagens da fila](#SendMessage-purge-messages)
+ [Código completo](#SendMessage-complete-code)
+ [Considerações adicionais](#SendMessage-additional)

## Enviar uma mensagem
<a name="SendMessage-send-message"></a>

O snippet a seguir envia uma mensagem para a fila identificada pelo URL da fila em questão.

O exemplo [no final deste tópico](#SendMessage-complete-code) mostra o snippet em uso.

```
    //
    // Method to put a message on a queue
    // Could be expanded to include message attributes, etc., in a SendMessageRequest
    private static async Task SendMessage(
      IAmazonSQS sqsClient, string qUrl, string messageBody)
    {
      SendMessageResponse responseSendMsg =
        await sqsClient.SendMessageAsync(qUrl, messageBody);
      Console.WriteLine($"Message added to queue\n  {qUrl}");
      Console.WriteLine($"HttpStatusCode: {responseSendMsg.HttpStatusCode}");
    }
```

## Enviar um lote de mensagens
<a name="SendMessage-send-batch"></a>

O snippet a seguir envia um lote de mensagens para a fila identificada pelo URL da fila em questão.

O exemplo [no final deste tópico](#SendMessage-complete-code) mostra o snippet em uso.

```
    //
    // Method to put a batch of messages on a queue
    // Could be expanded to include message attributes, etc.,
    // in the SendMessageBatchRequestEntry objects
    private static async Task SendMessageBatch(
      IAmazonSQS sqsClient, string qUrl, List<SendMessageBatchRequestEntry> messages)
    {
      Console.WriteLine($"\nSending a batch of messages to queue\n  {qUrl}");
      SendMessageBatchResponse responseSendBatch =
        await sqsClient.SendMessageBatchAsync(qUrl, messages);
      // Could test responseSendBatch.Failed here
      foreach(SendMessageBatchResultEntry entry in responseSendBatch.Successful)
        Console.WriteLine($"Message {entry.Id} successfully queued.");
    }
```

## Excluir todas as mensagens da fila
<a name="SendMessage-purge-messages"></a>

O snippet a seguir exclui todas as mensagens da fila identificada pelo URL da fila em questão. Isso também é conhecido como *limpando a fila*.

O exemplo [no final deste tópico](#SendMessage-complete-code) mostra o snippet em uso.

```
    //
    // Method to delete all messages from the queue
    private static async Task DeleteAllMessages(IAmazonSQS sqsClient, string qUrl)
    {
      Console.WriteLine($"\nPurging messages from queue\n  {qUrl}...");
      PurgeQueueResponse responsePurge = await sqsClient.PurgeQueueAsync(qUrl);
      Console.WriteLine($"HttpStatusCode: {responsePurge.HttpStatusCode}");
    }
```

## Código completo
<a name="SendMessage-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c29c23c25b5b1"></a>

NuGet pacotes:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

Elementos de programação:
+ Namespace [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  Classe [Amazon SQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)
+ Namespace [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  Classe [PurgeQueueResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TPurgeQueueResponse.html)

  Classe [SendMessageBatchResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSendMessageBatchResponse.html)

  Classe [SendMessageResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSendMessageResponse.html)

  Classe [SendMessageBatchRequestEntry](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSendMessageBatchRequestEntry.html)

  Classe [SendMessageBatchResultEntry](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSendMessageBatchResultEntry.html)

### O código
<a name="w2aac19c15c29c23c25b7b1"></a>

```
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSSendMessages
{
  // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
  // Class to send messages to a queue
  class Program
  {
    // Some example messages to send to the queue
    private const string JsonMessage = "{\"product\":[{\"name\":\"Product A\",\"price\": \"32\"},{\"name\": \"Product B\",\"price\": \"27\"}]}";
    private const string XmlMessage = "<products><product name=\"Product A\" price=\"32\" /><product name=\"Product B\" price=\"27\" /></products>";
    private const string CustomMessage = "||product|Product A|32||product|Product B|27||";
    private const string TextMessage = "Just a plain text message.";

    static async Task Main(string[] args)
    {
      // Do some checks on the command-line
      if(args.Length == 0)
      {
        Console.WriteLine("\nUsage: SQSSendMessages queue_url");
        Console.WriteLine("   queue_url - The URL of an existing SQS queue.");
        return;
      }
      if(!args[0].StartsWith("https://sqs."))
      {
        Console.WriteLine("\nThe command-line argument isn't a queue URL:");
        Console.WriteLine($"{args[0]}");
        return;
      }

      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // (could verify that the queue exists)
      // Send some example messages to the given queue
      // A single message
      await SendMessage(sqsClient, args[0], JsonMessage);

      // A batch of messages
      var batchMessages = new List<SendMessageBatchRequestEntry>{
        new SendMessageBatchRequestEntry("xmlMsg", XmlMessage),
        new SendMessageBatchRequestEntry("customeMsg", CustomMessage),
        new SendMessageBatchRequestEntry("textMsg", TextMessage)};
      await SendMessageBatch(sqsClient, args[0], batchMessages);

      // Let the user send their own messages or quit
      await InteractWithUser(sqsClient, args[0]);

      // Delete all messages that are still in the queue
      await DeleteAllMessages(sqsClient, args[0]);
    }


    //
    // Method to put a message on a queue
    // Could be expanded to include message attributes, etc., in a SendMessageRequest
    private static async Task SendMessage(
      IAmazonSQS sqsClient, string qUrl, string messageBody)
    {
      SendMessageResponse responseSendMsg =
        await sqsClient.SendMessageAsync(qUrl, messageBody);
      Console.WriteLine($"Message added to queue\n  {qUrl}");
      Console.WriteLine($"HttpStatusCode: {responseSendMsg.HttpStatusCode}");
    }


    //
    // Method to put a batch of messages on a queue
    // Could be expanded to include message attributes, etc.,
    // in the SendMessageBatchRequestEntry objects
    private static async Task SendMessageBatch(
      IAmazonSQS sqsClient, string qUrl, List<SendMessageBatchRequestEntry> messages)
    {
      Console.WriteLine($"\nSending a batch of messages to queue\n  {qUrl}");
      SendMessageBatchResponse responseSendBatch =
        await sqsClient.SendMessageBatchAsync(qUrl, messages);
      // Could test responseSendBatch.Failed here
      foreach(SendMessageBatchResultEntry entry in responseSendBatch.Successful)
        Console.WriteLine($"Message {entry.Id} successfully queued.");
    }


    //
    // Method to get input from the user
    // They can provide messages to put in the queue or exit the application
    private static async Task InteractWithUser(IAmazonSQS sqsClient, string qUrl)
    {
      string response;
      while (true)
      {
        // Get the user's input
        Console.WriteLine("\nType a message for the queue or \"exit\" to quit:");
        response = Console.ReadLine();
        if(response.ToLower() == "exit") break;

        // Put the user's message in the queue
        await SendMessage(sqsClient, qUrl, response);
      }
    }


    //
    // Method to delete all messages from the queue
    private static async Task DeleteAllMessages(IAmazonSQS sqsClient, string qUrl)
    {
      Console.WriteLine($"\nPurging messages from queue\n  {qUrl}...");
      PurgeQueueResponse responsePurge = await sqsClient.PurgeQueueAsync(qUrl);
      Console.WriteLine($"HttpStatusCode: {responsePurge.HttpStatusCode}");
    }
  }
}
```

## Considerações adicionais
<a name="SendMessage-additional"></a>
+ Para obter informações sobre várias limitações nas mensagens, incluindo os caracteres permitidos, consulte [Cotas relacionadas às mensagens](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-quotas.html#quotas-messages) no Guia do [desenvolvedor do Amazon Simple Queue Service](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/).
+ As mensagens permanecem nas filas até serem excluídas ou a fila ser removida. Quando uma mensagem for recebida por uma aplicação, ela não ficará visível na fila, mesmo que ainda exista na fila. Para obter mais informações sobre tempos limite de visibilidade, consulte [Tempo limite de visibilidade do Amazon SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/AboutVT.html).
+ Além do corpo da mensagem, você também pode adicionar atributos às mensagens. Para obter mais informações, consulte [Mensagem de metadados](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html).

# Recebimento de mensagens do Amazon SQS
<a name="ReceiveMessage"></a>

[Este exemplo mostra como usar o AWS SDK para .NET para receber mensagens de uma fila do Amazon SQS, que você pode criar [programaticamente](CreateQueue.md) ou usando o console do Amazon SQS.](https://console.aws.amazon.com/sqs) A aplicação lê uma única mensagem da fila, processa a mensagem (nesse caso, exibe o corpo da mensagem no console) e, em seguida, exclui a mensagem da fila. A aplicação repete essas etapas até que o usuário digite uma tecla no teclado.

Este exemplo e o [exemplo anterior sobre envio de mensagens](SendMessage.md), podem ser usados juntos para ver o fluxo de mensagens no Amazon SQS.

As seções a seguir fornecem snippets desse exemplo. O [código completo do exemplo](#ReceiveMessage-complete-code) é mostrado depois e pode ser criado e executado como está.

**Topics**
+ [Recebimento de uma mensagem](#ReceiveMessage-receive)
+ [Excluir uma mensagem](#ReceiveMessage-delete)
+ [Código completo](#ReceiveMessage-complete-code)
+ [Considerações adicionais](#ReceiveMessage-additional)

## Recebimento de uma mensagem
<a name="ReceiveMessage-receive"></a>

O trecho a seguir recebe uma mensagem da fila identificada pelo URL da fila em questão.

O exemplo [no final deste tópico](#ReceiveMessage-complete-code) mostra o snippet em uso.

```
    //
    // Method to read a message from the given queue
    // In this example, it gets one message at a time
    private static async Task<ReceiveMessageResponse> GetMessage(
      IAmazonSQS sqsClient, string qUrl, int waitTime=0)
    {
      return await sqsClient.ReceiveMessageAsync(new ReceiveMessageRequest{
        QueueUrl=qUrl,
        MaxNumberOfMessages=MaxMessages,
        WaitTimeSeconds=waitTime
        // (Could also request attributes, set visibility timeout, etc.)
      });
    }
```

## Excluir uma mensagem
<a name="ReceiveMessage-delete"></a>

O snippet a seguir exclui uma mensagem da fila identificada pelo URL da fila em questão.

O exemplo [no final deste tópico](#ReceiveMessage-complete-code) mostra o snippet em uso.

```
    //
    // Method to delete a message from a queue
    private static async Task DeleteMessage(
      IAmazonSQS sqsClient, Message message, string qUrl)
    {
      Console.WriteLine($"\nDeleting message {message.MessageId} from queue...");
      await sqsClient.DeleteMessageAsync(qUrl, message.ReceiptHandle);
    }
```

## Código completo
<a name="ReceiveMessage-complete-code"></a>

Esta seção mostra as referências relevantes e o código completo desse exemplo.

### Referências do SDK
<a name="w2aac19c15c29c25c21b5b1"></a>

NuGet pacotes:
+ [AWSSDK.SQS](https://www.nuget.org/packages/AWSSDK.SQS)

Elementos de programação:
+ Namespace [Amazon.SQS](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQS.html)

  Classe [Amazon SQSClient](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html)
+ Namespace [Amazon.SQS.Model](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/NSQSModel.html)

  Classe [ReceiveMessageRequest](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TReceiveMessageRequest.html)

  Classe [ReceiveMessageResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TReceiveMessageResponse.html)

### O código
<a name="w2aac19c15c29c25c21b7b1"></a>

```
using System;
using System.Threading.Tasks;
using Amazon.SQS;
using Amazon.SQS.Model;

namespace SQSReceiveMessages
{
  class Program
  {
    private const int MaxMessages = 1;
    private const int WaitTime = 2;
    static async Task Main(string[] args)
    {
      // Do some checks on the command-line
      if(args.Length == 0)
      {
        Console.WriteLine("\nUsage: SQSReceiveMessages queue_url");
        Console.WriteLine("   queue_url - The URL of an existing SQS queue.");
        return;
      }
      if(!args[0].StartsWith("https://sqs."))
      {
        Console.WriteLine("\nThe command-line argument isn't a queue URL:");
        Console.WriteLine($"{args[0]}");
        return;
      }

      // Create the Amazon SQS client
      var sqsClient = new AmazonSQSClient();

      // (could verify that the queue exists)
      // Read messages from the queue and perform appropriate actions
      Console.WriteLine($"Reading messages from queue\n  {args[0]}");
      Console.WriteLine("Press any key to stop. (Response might be slightly delayed.)");
      do
      {
        var msg = await GetMessage(sqsClient, args[0], WaitTime);
        if(msg.Messages.Count != 0)
        {
          if(ProcessMessage(msg.Messages[0]))
            await DeleteMessage(sqsClient, msg.Messages[0], args[0]);
        }
      } while(!Console.KeyAvailable);
    }


    //
    // Method to read a message from the given queue
    // In this example, it gets one message at a time
    private static async Task<ReceiveMessageResponse> GetMessage(
      IAmazonSQS sqsClient, string qUrl, int waitTime=0)
    {
      return await sqsClient.ReceiveMessageAsync(new ReceiveMessageRequest{
        QueueUrl=qUrl,
        MaxNumberOfMessages=MaxMessages,
        WaitTimeSeconds=waitTime
        // (Could also request attributes, set visibility timeout, etc.)
      });
    }


    //
    // Method to process a message
    // In this example, it simply prints the message
    private static bool ProcessMessage(Message message)
    {
      Console.WriteLine($"\nMessage body of {message.MessageId}:");
      Console.WriteLine($"{message.Body}");
      return true;
    }


    //
    // Method to delete a message from a queue
    private static async Task DeleteMessage(
      IAmazonSQS sqsClient, Message message, string qUrl)
    {
      Console.WriteLine($"\nDeleting message {message.MessageId} from queue...");
      await sqsClient.DeleteMessageAsync(qUrl, message.ReceiptHandle);
    }
  }
}
```

## Considerações adicionais
<a name="ReceiveMessage-additional"></a>
+ Para especificar uma sondagem longa, este exemplo usa a propriedade `WaitTimeSeconds` de cada chamada ao método `ReceiveMessageAsync`.

  Você também pode especificar uma sondagem longa para todas as mensagens em uma fila usando o atributo `ReceiveMessageWaitTimeSeconds` ao [criar](CreateQueue.md) ou [atualizar](UpdateSqsQueue.md) a fila.

  Para obter informações sobre sondagem curta versus sondagem longa, consulte [Sondagem curta e longa](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html) no *Guia do desenvolvedor do Amazon Simple Queue Service*.
+ Durante o processamento da mensagem, você pode usar o identificador de recebimento para alterar o tempo limite de visibilidade da mensagem. Para obter informações sobre como fazer isso, consulte os `ChangeMessageVisibilityAsync` métodos da SQSClient classe [Amazon](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/SQS/TSQSClient.html).
+ Chamar o método `DeleteMessageAsync` remove a mensagem da fila incondicionalmente, qualquer que seja a configuração do tempo limite de visibilidade.

# Usando AWS Lambda para serviço de computação
<a name="aws-lambda"></a>

O AWS SDK para .NET suporte AWS Lambda, que permite executar código sem provisionar ou gerenciar servidores. Para obter mais informações, consulte a [página do produto AWS Lambda](https://aws.amazon.com/lambda/) e o [Guia do desenvolvedor do AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/), especialmente a seção [Trabalhando com C\$1](https://docs.aws.amazon.com/lambda/latest/dg/lambda-csharp.html).

## APIs
<a name="w2aac19c17b5"></a>

Os AWS SDK para .NET suprimentos APIs para AWS Lambda. [Eles APIs permitem que você trabalhe com recursos do Lambda, como [funções](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-concepts.html#gettingstarted-concepts-function), [acionadores](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-concepts.html#gettingstarted-concepts-trigger) e eventos.](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-concepts.html#gettingstarted-concepts-event) Para ver o conjunto completo de APIs, consulte [Lambda na Referência da AWS SDK para .NET](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Lambda/NLambda.html) [API](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/).

[Os Lambda APIs são fornecidos por NuGet pacotes.](https://www.nuget.org/packages?page=2&q=aws%20lambda&sortBy=relevance)

## Pré-requisitos
<a name="w2aac19c17b7"></a>

Antes de começar, certifique-se de ter [configurado seu ambiente](net-dg-config.md) [e seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

## Mais informações
<a name="w2aac19c17b9"></a>

Consulte [Integração AWS com o.NET Aspire](aspire-integrations.md) para obter informações sobre como desenvolver com AWS Lambda o.NET Aspire.

## Tópicos
<a name="w2aac19c17c11"></a>

**Topics**
+ [APIs](#w2aac19c17b5)
+ [Pré-requisitos](#w2aac19c17b7)
+ [Mais informações](#w2aac19c17b9)
+ [Tópicos](#w2aac19c17c11)
+ [Lambda Annotations](aws-lambda-annotations.md)

# Usando anotações para escrever funções AWS Lambda
<a name="aws-lambda-annotations"></a>

Ao escrever funções do Lambda, às vezes é necessário escrever uma grande quantidade de código de manipulador e atualizar modelos do AWS CloudFormation , entre outras tarefas. Lambda Annotations é uma estrutura para ajudar a aliviar essas cargas para funções do Lambda do .NET 6, tornando assim a experiência de escrever Lambda em C\$1 mais natural.

Como exemplo do benefício de usar a estrutura do Lambda Annotations, considere os seguintes trechos de código que adicionam dois números.

**Sem Lambda Annotations**

```
public class Functions
{
    public APIGatewayProxyResponse LambdaMathPlus(APIGatewayProxyRequest request, ILambdaContext context)
    {
        if (!request.PathParameters.TryGetValue("x", out var xs))
        {
            return new APIGatewayProxyResponse
            {
                StatusCode = (int)HttpStatusCode.BadRequest
            };
        }
        if (!request.PathParameters.TryGetValue("y", out var ys))
        {
            return new APIGatewayProxyResponse
            {
                StatusCode = (int)HttpStatusCode.BadRequest
            };
        }

        var x = int.Parse(xs);
        var y = int.Parse(ys);

        return new APIGatewayProxyResponse
        {
            StatusCode = (int)HttpStatusCode.OK,
            Body = (x + y).ToString(),
            Headers = new Dictionary<string, string> { { "Content-Type", "text/plain" } }
        };
    } 
}
```

**Com Lambda Annotations**

```
public class Functions
{
    [LambdaFunction]
    [RestApi("/plus/{x}/{y}")]
    public int Plus(int x, int y)
    {
        return x + y;
    }
}
```

Conforme mostrado no exemplo, o Lambda Annotations pode eliminar a necessidade de um determinado código clichê.

Para obter detalhes sobre como usar a estrutura, bem como informações adicionais, consulte os seguintes recursos:
+ O [GitHub README](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.Annotations/README.md) para documentação sobre os atributos APIs e as anotações do Lambda.
+ A [publicação no blog](https://aws.amazon.com/blogs/developer/net-lambda-annotations-framework/) do Lambda Annotations.
+ O pacote [https://www.nuget.org/packages/Amazon.Lambda.Annotations](https://www.nuget.org/packages/Amazon.Lambda.Annotations) NuGet .
+ O [projeto Photo Asset Management](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/cross-service/PhotoAssetManager) começou GitHub. [Especificamente, consulte a [PamApiAnnotations](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/cross-service/PhotoAssetManager/PamApiAnnotations)pasta e as referências às anotações do Lambda no README do projeto.](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/dotnetv3/cross-service/PhotoAssetManager/README.md)
**nota**  
O exemplo anterior é específico para a V3 do. AWS SDK para .NET Se você usar o exemplo com a V4 do SDK (a versão mais recente), talvez seja necessário fazer ajustes de acordo com as informações em. [Migrando para a versão 4](net-dg-v4.md)

# Bibliotecas e estruturas de alto nível para o AWS SDK para .NET
<a name="high-level-libraries"></a>

As seções a seguir contêm informações sobre bibliotecas e estruturas de alto nível que não fazem parte da funcionalidade principal do SDK. Essas bibliotecas e estruturas usam a funcionalidade principal do SDK para criar recursos que facilitam determinadas tarefas.

Se você é novo no AWS SDK para .NET, talvez queira conferir o [Criando um aplicativo simples](quick-start.md) tópico primeiro. Ele fornece uma introdução ao SDK.

Antes de começar, certifique-se de ter [configurado seu ambiente](net-dg-config.md) [e seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

**Topics**
+ [Estrutura de processamento de mensagens](msg-proc-fw.md)
+ [Integração AWS com o.NET Aspire](aspire-integrations.md)

# AWS Estrutura de processamento de mensagens para.NET
<a name="msg-proc-fw"></a>

A Estrutura de Processamento de AWS Mensagens para.NET é uma estrutura AWS nativa que simplifica o desenvolvimento de aplicativos de processamento de mensagens.NET que usam AWS serviços como Amazon Simple Queue Service (SQS), Amazon Simple Notification Service (SNS) e Amazon. EventBridge A estrutura reduz a quantidade de código padronizado que os desenvolvedores precisam escrever, permitindo que você se concentre na lógica empresarial ao publicar e consumir mensagens. Para obter detalhes sobre como a estrutura pode simplificar seu desenvolvimento, consulte a postagem do blog [Apresentando a estrutura de processamento de AWS mensagens para.NET (versão prévia)](https://aws.amazon.com/blogs/developer/introducing-the-aws-message-processing-framework-for-net-preview/). A primeira parte, em particular, fornece uma demonstração que mostra a diferença entre usar chamadas de API de baixo nível e usar a estrutura.

O Message Processing Framework oferece suporte às seguintes atividades e recursos:
+ Enviando mensagens para o SQS e publicando eventos no SNS e. EventBridge
+ Receber e manipular mensagens do SQS usando um poller de longa duração, que normalmente é usado em serviços em segundo plano. Isso inclui gerenciar o tempo limite de visibilidade enquanto uma mensagem está sendo processada para evitar que outros clientes a processem.
+ Manipulação de mensagens em AWS Lambda funções.
+ Filas SQS FIFO (first-in-first-out) e tópicos de SNS.
+ OpenTelemetry para registro.

Para obter detalhes sobre essas atividades e recursos, consulte a seção **Recursos** da [postagem do blog](https://aws.amazon.com/blogs/developer/introducing-the-aws-message-processing-framework-for-net-preview/) e os tópicos listados abaixo.

Antes de começar, verifique se você [configurou seu ambiente](net-dg-config.md) e [configurou seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

**Recursos adicionais**
+ O [https://www.nuget.org/packages/AWS.Messaging/](https://www.nuget.org/packages/AWS.Messaging/)pacote em [NuGet.org](https://www.nuget.org/).
+ A [referência da API](https://aws.github.io/aws-dotnet-messaging/).
+ O `README` arquivo no GitHub repositório em [https://github.com/aws/aws-dotnet-messaging/](https://github.com/aws/aws-dotnet-messaging/)
+ [Injeção de dependência.NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection) da Microsoft.
+ [Host genérico.NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host) da Microsoft.

**Topics**
+ [Conceitos básicos](msg-proc-fw-get-started.md)
+ [Publicar mensagens](msg-proc-fw-publish.md)
+ [Consumir mensagens](msg-proc-fw-consume.md)
+ [FIFO](msg-proc-fw-fifo.md)
+ [Registro e telemetria aberta](msg-proc-fw-telemetry.md)
+ [Personalização](msg-proc-fw-customize.md)
+ [Segurança](msg-proc-fw-security.md)

# Comece a usar o AWS Message Processing Framework para.NET
<a name="msg-proc-fw-get-started"></a>

Antes de começar, certifique-se de ter [configurado seu ambiente](net-dg-config.md) [e seu projeto](configuring-the-sdk.md). Revise também as informações em [Uso da SDK](net-dg-sdk-features.md).

Este tópico fornece informações que ajudarão você a começar a usar o Message Processing Framework. Além das informações de pré-requisitos e configuração, é fornecido um tutorial que mostra como implementar um cenário comum.

## Pré-requisitos e configuração
<a name="mpf-get-started-prereq"></a>
+ As credenciais que você fornece para seu aplicativo devem ter as permissões apropriadas para o serviço de mensagens e as operações que ele usa. Para obter mais informações, consulte os tópicos de segurança para [SQS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-authentication-and-access-control.html), [SNS](https://docs.aws.amazon.com/sns/latest/dg/security-iam.html) e [EventBridge](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-iam.html)em seus respectivos guias do desenvolvedor. [Veja também a parte do arquivo [README](https://github.com/aws/aws-dotnet-messaging/) GitHub que discute permissões específicas.](https://github.com/aws/aws-dotnet-messaging/blob/main/README.md#permissions)
+ Para usar o AWS Message Processing Framework para.NET, você deve adicionar o [https://www.nuget.org/packages/AWS.Messaging](https://www.nuget.org/packages/AWS.Messaging) NuGetpacote ao seu projeto. Por exemplo:

  ```
  dotnet add package AWS.Messaging
  ```
+ A estrutura se integra ao contêiner de [serviço de injeção de dependência (DI)](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection) do.NET. Você pode configurar a estrutura durante a inicialização do seu aplicativo ligando `AddAWSMessageBus` para adicioná-la ao contêiner de DI.

  ```
  var builder = WebApplication.CreateBuilder(args);
  
  // Register the AWS Message Processing Framework for .NET
  builder.Services.AddAWSMessageBus(builder =>
  {
      // Register that you'll publish messages of type ChatMessage to an existing queue
      builder.AddSQSPublisher<ChatMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");
  });
  ```

## Tutorial
<a name="mpf-get-started-tutorial"></a>

Este tutorial demonstra como usar o AWS Message Processing Framework para.NET. Ele cria dois aplicativos: uma API ASP.NET Core Minimal que envia mensagens para uma fila do Amazon SQS quando recebe uma solicitação em um endpoint da API e um aplicativo de console de longa execução que pesquisa essas mensagens e as processa. 
+ As instruções neste tutorial favorecem a CLI do.NET, mas você pode realizar esse tutorial usando ferramentas multiplataforma, como a CLI do.NET ou o Microsoft Visual Studio. Para obter informações sobre ferramentas, consulte[Instalando e configurando seu conjunto de ferramentas para o AWS SDK para .NET](net-dg-dev-env.md).
+ Este tutorial pressupõe que você esteja usando seu `[default]` perfil para obter credenciais. Também pressupõe que credenciais de curto prazo estejam disponíveis com as permissões apropriadas para enviar e receber mensagens do Amazon SQS. Para obter mais informações, consulte [Autenticando o com AWS SDK para .NET AWS](creds-idc.md) os tópicos de segurança do [SQS.](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-authentication-and-access-control.html)

**nota**  
Ao executar este tutorial, você pode incorrer em custos com mensagens SQS.

### Etapas
<a name="mpf-tutorial-steps"></a>
+ [Criar uma fila SQS](#mpf-tutorial-queue)
+ [Crie e execute o aplicativo de publicação](#mpf-tutorial-publish)
+ [Crie e execute o aplicativo de manipulação](#mpf-tutorial-handle)
+ [Limpeza](#mpf-tutorial-cleanup)

### Criar uma fila SQS
<a name="mpf-tutorial-queue"></a>

Este tutorial requer uma fila SQS para enviar e receber mensagens. Uma fila pode ser criada usando um dos seguintes comandos para o AWS CLI ou o. Ferramentas da AWS para PowerShell Anote a URL da fila que é retornada para que você possa especificá-la na configuração da estrutura a seguir.

------
#### [ AWS CLI ]

```
aws sqs create-queue --queue-name DemoQueue
```

------
#### [ Ferramentas da AWS para PowerShell ]

```
New-SQSQueue -QueueName DemoQueue
```

------

### Crie e execute o aplicativo de publicação
<a name="mpf-tutorial-publish"></a>

Use o procedimento a seguir para criar e executar o aplicativo de publicação.

1. Abra um prompt de comando ou terminal. Localize ou crie uma pasta do sistema operacional na qual você pode criar um projeto .NET.

1. Nessa pasta, execute o comando a seguir para criar o projeto .NET.

   ```
   dotnet new webapi --name Publisher
   ```

1. Navegue até a pasta do novo projeto. Adicione uma dependência na estrutura de processamento de AWS mensagens para.NET.

   ```
   cd Publisher
   dotnet add package AWS.Messaging
   ```
**nota**  
Se você estiver usando Centro de Identidade do AWS IAM para autenticação, não se esqueça de também adicionar `AWSSDK.SSO` `AWSSDK.SSOOIDC` e.

1. Substitua o código em `Program.cs` pelo código a seguir.

   ```
   using AWS.Messaging;
   using Microsoft.AspNetCore.Mvc;
   using Publisher;
   
   var builder = WebApplication.CreateBuilder(args);
   
   // Add services to the container.
   // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle.
   builder.Services.AddEndpointsApiExplorer();
   builder.Services.AddSwaggerGen();
   
   
   // Configure the AWS Message Processing Framework for .NET.
   builder.Services.AddAWSMessageBus(builder =>
   {
       // Check for input SQS URL.
       // The SQS URL should be passed as a command line argument or set in the Debug launch profile.
       if ((args.Length == 1) && (args[0].Contains("https://sqs.")))
       {
           // Register that you'll publish messages of type GreetingMessage:
           // 1. To a specified queue.
           // 2. Using the message identifier "greetingMessage", which will be used
           //    by handlers to route the message to the appropriate handler.
           builder.AddSQSPublisher<GreetingMessage>(args[0], "greetingMessage");
       }
       // You can map additional message types to queues or topics here as well.
   });
   var app = builder.Build();
   
   
   // Configure the HTTP request pipeline.
   if (app.Environment.IsDevelopment())
   {
       app.UseSwagger();
       app.UseSwaggerUI();
   }
   
   app.UseHttpsRedirection();
   
   // Create an API Endpoint that receives GreetingMessage objects
   // from the caller and then sends them as an SQS message.
   app.MapPost("/greeting", async ([FromServices] IMessagePublisher publisher, Publisher.GreetingMessage message) =>
       {
           return await PostGreeting(message, publisher);
       })
   .WithName("SendGreeting")
   .WithOpenApi();
   
   app.Run();
   
   public partial class Program
   {
       /// <summary>
       /// Endpoint for posting a greeting message.
       /// </summary>
       /// <param name="greetingMessage">The greeting message.</param>
       /// <param name="messagePublisher">The message publisher.</param>
       /// <returns>Async task result.</returns>
       public static async Task<IResult> PostGreeting(GreetingMessage greetingMessage,
           IMessagePublisher messagePublisher)
       {
           if (greetingMessage.SenderName == null || greetingMessage.Greeting == null)
           {
               return Results.BadRequest();
           }
   
           // Publish the message to the queue configured above.
           await messagePublisher.PublishAsync(greetingMessage);
   
           return Results.Ok();
       }
   }
   
   namespace Publisher
   {
       /// <summary>
       /// This class represents the message contents.
       /// </summary>
       public class GreetingMessage
       {
           public string? SenderName { get; set; }
           public string? Greeting { get; set; }
       }
   }
   ```

1. Execute o seguinte comando: Isso deve abrir uma janela do navegador com a interface do usuário do Swagger, que permite explorar e testar sua API.

   ```
   dotnet watch run <queue URL created earlier>
   ```

1. Abra o `/greeting` endpoint e escolha **Testar.**

1. Especifique `senderName` os `greeting` valores da mensagem e escolha **Executar**. Isso invoca sua API, que envia a mensagem SQS.

### Crie e execute o aplicativo de manipulação
<a name="mpf-tutorial-handle"></a>

Use o procedimento a seguir para criar e executar o aplicativo de manipulação.

1. Abra um prompt de comando ou terminal. Localize ou crie uma pasta do sistema operacional na qual você pode criar um projeto .NET.

1. Nessa pasta, execute o comando a seguir para criar o projeto .NET.

   ```
   dotnet new console --name Handler
   ```

1. Navegue até a pasta do novo projeto. Adicione uma dependência na estrutura de processamento de AWS mensagens para.NET. Adicione também o `Microsoft.Extensions.Hosting` pacote, que permite configurar a estrutura por meio do [host genérico do.NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host).

   ```
   cd Handler
   dotnet add package AWS.Messaging
   dotnet add package Microsoft.Extensions.Hosting
   ```
**nota**  
Se você estiver usando Centro de Identidade do AWS IAM para autenticação, não se esqueça de também adicionar `AWSSDK.SSO` `AWSSDK.SSOOIDC` e.

1. Substitua o código em `Program.cs` pelo código a seguir.

   ```
   using AWS.Messaging;
   using Handler;
   using Microsoft.Extensions.DependencyInjection;
   using Microsoft.Extensions.Hosting;
   
   var builder = Host.CreateDefaultBuilder(args);
   
   builder.ConfigureServices(services =>
   {
       // Register the AWS Message Processing Framework for .NET.
       services.AddAWSMessageBus(builder =>
       {
           // Check for input SQS URL.
           // The SQS URL should be passed as a command line argument or set in the Debug launch profile.
           if ((args.Length == 1) && (args[0].Contains("https://sqs.")))
           {
               // Register you'll poll the following queue.
               builder.AddSQSPoller(args[0]);
   
               // And that messages of type "greetingMessage" should be:
               // 1. Deserialized as GreetingMessage objects.
               // 2. Which are then passed to GreetingMessageHandler.
               builder.AddMessageHandler<GreetingMessageHandler, GreetingMessage>("greetingMessage");
   
           }
           // You can add additional message handlers here, using different message types. 
       });
   });
   
   var host = builder.Build();
   await host.RunAsync();
   
   namespace Handler
   {
       /// <summary>
       /// This class represents the message contents.
       /// </summary>
       public class GreetingMessage
       {
           public string? SenderName { get; set; }
           public string? Greeting { get; set; }
       }
   
       /// <summary>
       /// This handler is invoked each time you receive the message.
       /// </summary>
       public class GreetingMessageHandler : IMessageHandler<GreetingMessage>
       {
           public Task<MessageProcessStatus> HandleAsync(
               MessageEnvelope<GreetingMessage> messageEnvelope,
               CancellationToken token = default)
           {
               Console.WriteLine(
                   $"Received message {messageEnvelope.Message.Greeting} from {messageEnvelope.Message.SenderName}");
               return Task.FromResult(MessageProcessStatus.Success());
           }
       }
   }
   ```

1. Execute o seguinte comando: Isso inicia uma pesquisa de longa duração.

   ```
   dotnet run <queue URL created earlier>
   ```

   Logo após a inicialização, o aplicativo receberá a mensagem que foi enviada na primeira parte deste tutorial e registrará a seguinte mensagem:

   ```
   Received message {greeting} from {senderName}
   ```

1. Pressione `Ctrl+C` para parar o poller.

### Limpeza
<a name="mpf-tutorial-cleanup"></a>

Use um dos comandos a seguir para o AWS CLI ou Ferramentas da AWS para PowerShell para excluir a fila.

------
#### [ AWS CLI ]

```
aws sqs delete-queue --queue-url "<queue URL created earlier>"
```

------
#### [ Ferramentas da AWS para PowerShell ]

```
Remove-SQSQueue -QueueUrl "<queue URL created earlier>"
```

------

# Publique mensagens com o AWS Message Processing Framework para.NET
<a name="msg-proc-fw-publish"></a>

O AWS Message Processing Framework para.NET oferece suporte à publicação de um ou mais tipos de mensagens, ao processamento de um ou mais tipos de mensagens ou à realização de ambos no mesmo aplicativo. 

O código a seguir mostra a configuração de um aplicativo que está publicando diferentes tipos de mensagens em diferentes AWS serviços. 

```
var builder = WebApplication.CreateBuilder(args);

// Register the AWS Message Processing Framework for .NET
builder.Services.AddAWSMessageBus(builder =>
{
    // Register that you'll send messages of type ChatMessage to an existing queue
    builder.AddSQSPublisher<ChatMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");

    // Register that you'll publish messages of type OrderInfo to an existing SNS topic
    builder.AddSNSPublisher<OrderInfo>("arn:aws:sns:us-west-2:012345678910:MyAppProd");

    // Register that you'll publish messages of type FoodItem to an existing EventBridge bus
    builder.AddEventBridgePublisher<FoodItem>("arn:aws:events:us-west-2:012345678910:event-bus/default");
});
```

Depois de registrar a estrutura durante a inicialização, injete o genérico `IMessagePublisher` em seu código. Chame seu `PublishAsync` método para publicar qualquer um dos tipos de mensagem que foram configurados acima. O editor genérico determinará o destino para o qual rotear a mensagem com base em seu tipo. 

 No exemplo a seguir, um controlador ASP.NET MVC recebe `ChatMessage` mensagens e `OrderInfo` eventos dos usuários e os publica no Amazon SQS e no Amazon SNS, respectivamente. Ambos os tipos de mensagem podem ser publicados usando o editor genérico que foi configurado acima.

```
[ApiController]
[Route("[controller]")]
public class PublisherController : ControllerBase
{
    private readonly IMessagePublisher _messagePublisher;

    public PublisherController(IMessagePublisher messagePublisher)
    {
        _messagePublisher = messagePublisher;
    }

    [HttpPost("chatmessage", Name = "Chat Message")]
    public async Task<IActionResult> PublishChatMessage([FromBody] ChatMessage message)
    {
        // Perform business and validation logic on the ChatMessage here.
        if (message == null)
        {
            return BadRequest("A chat message was not submitted. Unable to forward to the message queue.");
        }
        if (string.IsNullOrEmpty(message.MessageDescription))
        {
            return BadRequest("The MessageDescription cannot be null or empty.");
        }

        // Send the ChatMessage to SQS, using the generic publisher.
        await _messagePublisher.PublishAsync(message);

        return Ok();
    }

    [HttpPost("order", Name = "Order")]
    public async Task<IActionResult> PublishOrder([FromBody] OrderInfo message)
    {
        if (message == null)
        {
            return BadRequest("An order was not submitted.");
        }

        // Publish the OrderInfo to SNS, using the generic publisher.
        await _messagePublisher.PublishAsync(message);

        return Ok();
    }
}
```

Para rotear uma mensagem para a lógica de tratamento apropriada, a estrutura usa metadados chamados *identificador do tipo de mensagem*. Por padrão, esse é o nome completo do tipo.NET da mensagem, incluindo seu nome de montagem. Se você estiver enviando e manipulando mensagens, esse mecanismo funciona bem se você compartilhar a definição dos objetos de mensagem entre projetos. No entanto, se as mensagens forem redefinidas em namespaces diferentes ou se você estiver trocando mensagens com outras estruturas ou linguagens de programação, talvez seja necessário substituir o identificador do tipo de mensagem.

```
var builder = Host.CreateDefaultBuilder(args);

builder.ConfigureServices(services =>
{
    // Register the AWS Message Processing Framework for .NET
    services.AddAWSMessageBus(builder =>
    {
        // Register that you'll publish messages of type GreetingMessage to an existing queue
        builder.AddSQSPublisher<GreetingMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd", "greetingMessage");
    });
});
```

## Editores específicos de serviços
<a name="service-specific-publishers"></a>

O exemplo mostrado acima usa o genérico`IMessagePublisher`, que pode ser publicado em qualquer AWS serviço compatível com base no tipo de mensagem configurado. A estrutura também fornece editores específicos de serviços para Amazon SQS, Amazon SNS e Amazon. EventBridge Esses editores específicos expõem opções que se aplicam somente a esse serviço e podem ser injetadas usando os tipos`ISQSPublisher`, e. `ISNSPublisher` `IEventBridgePublisher`

Por exemplo, ao enviar mensagens para uma fila FIFO do SQS, você deve definir o ID do grupo de [mensagens](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-key-terms.html) apropriado. O código a seguir mostra o `ChatMessage` exemplo novamente, mas agora usando an `ISQSPublisher` para definir opções específicas do SQS.

```
public class PublisherController : ControllerBase
{
    private readonly ISQSPublisher _sqsPublisher;

    public PublisherController(ISQSPublisher sqsPublisher)
    {
        _sqsPublisher = sqsPublisher;
    }

    [HttpPost("chatmessage", Name = "Chat Message")]
    public async Task<IActionResult> PublishChatMessage([FromBody] ChatMessage message)
    {
        // Perform business and validation logic on the ChatMessage here
        if (message == null)
        {
            return BadRequest("A chat message was not submitted. Unable to forward to the message queue.");
        }
        if (string.IsNullOrEmpty(message.MessageDescription))
        {
            return BadRequest("The MessageDescription cannot be null or empty.");
        }

        // Send the ChatMessage to SQS using the injected ISQSPublisher, with SQS-specific options
        await _sqsPublisher.SendAsync(message, new SQSOptions
        {
            DelaySeconds = <delay-in-seconds>,
            MessageAttributes = <message-attributes>,
            MessageDeduplicationId = <message-deduplication-id>,
            MessageGroupId = <message-group-id>
        });

        return Ok();
    }
}
```

O mesmo pode ser feito para o SNS e EventBridge, usando `ISNSPublisher` e, `IEventBridgePublisher` respectivamente.

```
await _snsPublisher.PublishAsync(message, new SNSOptions
{
    Subject = <subject>,
    MessageAttributes = <message-attributes>,
    MessageDeduplicationId = <message-deduplication-id>,
    MessageGroupId = <message-group-id>
});
```

```
await _eventBridgePublisher.PublishAsync(message, new EventBridgeOptions
{
    DetailType = <detail-type>,
    Resources = <resources>,
    Source = <source>,
    Time = <time>,
    TraceHeader = <trace-header>
});
```

Por padrão, as mensagens de um determinado tipo são enviadas para o destino configurado com antecedência. No entanto, você pode substituir o destino de uma única mensagem usando os editores específicos da mensagem. Você também pode substituir o AWS SDK para .NET cliente subjacente usado para publicar a mensagem, o que pode ser útil em aplicativos multilocatários nos quais você precisa alterar funções ou credenciais, dependendo do destino.

```
await _sqsPublisher.SendAsync(message, new SQSOptions
{
    OverrideClient = <override IAmazonSQS client>,
    QueueUrl = <override queue URL>
});
```

# Consuma mensagens com o AWS Message Processing Framework para.NET
<a name="msg-proc-fw-consume"></a>

A Estrutura de Processamento de AWS Mensagens para.NET permite que você consuma mensagens que foram [publicadas](msg-proc-fw-publish.md) usando a estrutura ou um dos serviços de mensagens. As mensagens podem ser consumidas de várias maneiras, algumas das quais estão descritas abaixo.

## Manipuladores de mensagens
<a name="handle-a-message"></a>

Para consumir mensagens, implemente um manipulador de mensagens usando a `IMessageHandler` interface para cada tipo de mensagem que você deseja processar. O mapeamento entre tipos de mensagens e manipuladores de mensagens é configurado na inicialização do projeto.

```
await Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        // Register the AWS Message Processing Framework for .NET
        services.AddAWSMessageBus(builder =>
        {
            // Register an SQS Queue that the framework will poll for messages.
            // NOTE: The URL given below is an example. Use the appropriate URL for your SQS Queue.
            builder.AddSQSPoller("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");

            // Register all IMessageHandler implementations with the message type they should process. 
            // Here messages that match our ChatMessage .NET type will be handled by our ChatMessageHandler
            builder.AddMessageHandler<ChatMessageHandler, ChatMessage>();
        });
    })
    .Build()
    .RunAsync();
```

O código a seguir mostra um exemplo de manipulador de mensagens para uma `ChatMessage` mensagem. 

```
public class ChatMessageHandler : IMessageHandler<ChatMessage>
{
    public Task<MessageProcessStatus> HandleAsync(MessageEnvelope<ChatMessage> messageEnvelope, CancellationToken token = default)
    {
        // Add business and validation logic here.
        if (messageEnvelope == null)
        {
            return Task.FromResult(MessageProcessStatus.Failed());
        }

        if (messageEnvelope.Message == null)
        {
            return Task.FromResult(MessageProcessStatus.Failed());
        }

        ChatMessage message = messageEnvelope.Message;

        Console.WriteLine($"Message Description: {message.MessageDescription}");

        // Return success so the framework will delete the message from the queue.
        return Task.FromResult(MessageProcessStatus.Success());
    }
}
```

O externo `MessageEnvelope` contém metadados usados pela estrutura. Sua `message` propriedade é o tipo de mensagem (nesse caso`ChatMessage`).

Você pode retornar `MessageProcessStatus.Success()` para indicar que a mensagem foi processada com sucesso e que a estrutura excluirá a mensagem da fila do Amazon SQS. Ao retornar`MessageProcessStatus.Failed()`, a mensagem permanecerá na fila, onde poderá ser processada novamente ou movida para uma [fila de mensagens mortas, se configurada](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html).

## Tratamento de mensagens em um processo de longa duração
<a name="long-running-process"></a>

Você pode chamar `AddSQSPoller` com uma URL de fila SQS para iniciar uma longa execução [https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.backgroundservice](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.backgroundservice)que pesquisará continuamente a fila e processará mensagens.

```
await Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        // Register the AWS Message Processing Framework for .NET
        services.AddAWSMessageBus(builder =>
        {
            // Register an SQS Queue that the framework will poll for messages.
            // NOTE: The URL given below is an example. Use the appropriate URL for your SQS Queue.
            builder.AddSQSPoller("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd", options => 
            {
                // The maximum number of messages from this queue that the framework will process concurrently on this client.
                options.MaxNumberOfConcurrentMessages = 10;

                // The duration each call to SQS will wait for new messages.
                options.WaitTimeSeconds = 20; 
            });

            // Register all IMessageHandler implementations with the message type they should process.
            builder.AddMessageHandler<ChatMessageHandler, ChatMessage>();
        });
    })
    .Build()
    .RunAsync();
```

### Configurando o SQS Message Poller
<a name="config-msg-poller"></a>

O poller de mensagens do SQS pode ser configurado pelo `SQSMessagePollerOptions` durante a chamada. `AddSQSPoller`
+ `MaxNumberOfConcurrentMessages`- O número máximo de mensagens da fila a serem processadas simultaneamente. O valor padrão é 10.
+ `WaitTimeSeconds`- A duração (em segundos) pela qual a chamada do `ReceiveMessage` SQS espera que uma mensagem chegue na fila antes de retornar. Se uma mensagem estiver disponível, a chamada retornará antes de`WaitTimeSeconds`. O valor padrão é 20.

**Tratamento do tempo limite de visibilidade da mensagem**

As mensagens do SQS têm um período de [tempo limite de visibilidade](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html). Quando um consumidor começa a lidar com uma determinada mensagem, ela permanece na fila, mas fica oculta dos outros consumidores para evitar processá-la mais de uma vez. Se a mensagem não for tratada e excluída antes de se tornar visível novamente, outro consumidor poderá tentar lidar com a mesma mensagem.

A estrutura rastreará e tentará estender o tempo limite de visibilidade das mensagens que está manipulando atualmente. Você pode configurar esse comportamento no `SQSMessagePollerOptions` ao ligar`AddSQSPoller`.
+ `VisibilityTimeout`- A duração em segundos em que as mensagens recebidas são ocultadas das solicitações de recuperação subsequentes. O valor padrão é 30.
+ `VisibilityTimeoutExtensionThreshold`- Quando o tempo limite de visibilidade de uma mensagem estiver dentro de alguns segundos após a expiração, a estrutura estenderá o tempo limite de visibilidade (em mais `VisibilityTimeout` alguns segundos). O valor padrão é 5.
+ `VisibilityTimeoutExtensionHeartbeatInterval`- Com que frequência, em segundos, a estrutura verificará as mensagens que estão prestes a expirar e, em `VisibilityTimeoutExtensionThreshold` seguida, estenderá o tempo limite de visibilidade. O valor padrão é 1.

 No exemplo a seguir, a estrutura verificará a cada 1 segundo as mensagens que ainda estão sendo tratadas. Para essas mensagens dentro de 5 segundos após se tornarem visíveis novamente, a estrutura estenderá automaticamente o tempo limite de visibilidade de cada mensagem em mais 30 segundos.

```
// NOTE: The URL given below is an example. Use the appropriate URL for your SQS Queue.
builder.AddSQSPoller("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd", options => 
{
    options.VisibilityTimeout = 30;
    options.VisibilityTimeoutExtensionThreshold = 5;
    VisibilityTimeoutExtensionHeartbeatInterval = 1;
});
```

## Manipulação de mensagens em AWS Lambda funções
<a name="lambda-functions"></a>

Você pode usar o AWS Message Processing Framework para.NET com a [integração do SQS com o Lambda](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html). Isso é fornecido pelo `AWS.Messaging.Lambda` pacote. Consulte seu [README](https://github.com/aws/aws-dotnet-messaging/blob/main/src/AWS.Messaging.Lambda/README.md) para começar.

# Usando o FIFO com a estrutura de processamento de AWS mensagens para.NET
<a name="msg-proc-fw-fifo"></a>

[Para casos de uso em que a ordenação e a desduplicação de mensagens são essenciais, o AWS Message Processing Framework para.NET oferece suporte first-in-first-out (FIFO) às [filas do Amazon SQS e aos tópicos do Amazon SNS](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-fifo-queues.html).](https://docs.aws.amazon.com/sns/latest/dg/sns-fifo-topics.html)

## Publicação
<a name="mpf-fifo-publish"></a>

Ao publicar mensagens em uma fila ou tópico FIFO, você deve definir a ID do grupo de mensagens, que especifica o grupo ao qual a mensagem pertence. As mensagens dentro de um grupo são processadas em ordem. Você pode definir isso nos editores de mensagens específicos do SQS e do SNS.

```
await _sqsPublisher.PublishAsync(message, new SQSOptions
{
    MessageDeduplicationId = <message-deduplication-id>,
    MessageGroupId = <message-group-id>
});
```

## Assinatura
<a name="mpf-fifo-subscribe"></a>

Ao lidar com mensagens de uma fila FIFO, a estrutura manipula as mensagens dentro de um determinado grupo de mensagens na ordem em que foram recebidas para cada `ReceiveMessages` chamada. A estrutura entra nesse modo de operação automaticamente quando configurada com uma fila terminando em`.fifo`.

```
await Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        // Register the AWS Message Processing Framework for .NET.
        services.AddAWSMessageBus(builder =>
        {
            // Because this is a FIFO queue, the framework automatically handles these messages in order.
            builder.AddSQSPoller("https://sqs.us-west-2.amazonaws.com/012345678910/MPF.fifo");
            builder.AddMessageHandler<OrderMessageHandler, OrderMessage>();
        });
    })
    .Build()
    .RunAsync();
```

# Registro e telemetria aberta para a estrutura de processamento de AWS mensagens para.NET
<a name="msg-proc-fw-telemetry"></a>

A Estrutura de Processamento de AWS Mensagens para.NET é instrumentada OpenTelemetry para registrar [rastreamentos](https://opentelemetry.io/docs/concepts/signals/traces/) para cada mensagem publicada ou tratada pela estrutura. Isso é fornecido pelo [https://www.nuget.org/packages/AWS.Messaging.Telemetry.OpenTelemetry](https://www.nuget.org/packages/AWS.Messaging.Telemetry.OpenTelemetry)pacote. Consulte seu [README](https://github.com/aws/aws-dotnet-messaging/blob/main/src/AWS.Messaging.Telemetry.OpenTelemetry/README.md) para começar.

**nota**  
Para obter informações de segurança relacionadas ao registro, consulte[Segurança para a estrutura de processamento de AWS mensagens para.NET](msg-proc-fw-security.md).

# Personalize a estrutura de processamento de AWS mensagens para.NET
<a name="msg-proc-fw-customize"></a>

O AWS Message Processing Framework para.NET cria, envia e manipula mensagens em três “camadas” diferentes:

1. Na camada mais externa, a estrutura cria a solicitação ou resposta AWS-nativa específica para um serviço. Com o Amazon SQS, por exemplo, ele cria [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)solicitações e trabalha com os [https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Message.html](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_Message.html)objetos definidos pelo serviço.

1. [Dentro da solicitação e resposta do SQS, a estrutura define o `MessageBody` elemento (ou `Message` para o Amazon SNS `Detail` ou para a EventBridge Amazon) como um formato JSON. CloudEvent](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md) Ele contém metadados definidos pela estrutura que podem ser acessados no `MessageEnvelope` objeto ao manipular uma mensagem.

1. Na camada mais interna, o `data` atributo dentro do objeto CloudEvent JSON contém uma serialização JSON do objeto.NET que foi enviado ou recebido como mensagem.

   ```
   {
       "id":"b02f156b-0f02-48cf-ae54-4fbbe05cffba",
       "source":"/aws/messaging",
       "specversion":"1.0",
       "type":"Publisher.Models.ChatMessage",
       "time":"2023-11-21T16:36:02.8957126+00:00",
       "data":"<the ChatMessage object serialized as JSON>"
   }
   ```

Você pode personalizar a forma como o envelope da mensagem é configurado e lido:
+ `"id"`identifica a mensagem de forma exclusiva. Por padrão, ele é definido como um novo GUID, mas isso pode ser substituído implementando o seu próprio `IMessageIdGenerator` e injetando-o no contêiner de DI. 
+ `"type"`controla como a mensagem é roteada para os manipuladores. Por padrão, isso usa o nome completo do tipo.NET que corresponde à mensagem. Você pode substituir isso por meio do `messageTypeIdentifier` parâmetro ao mapear o tipo de mensagem para o destino via`AddSQSPublisher`,`AddSNSPublisher`, ou`AddEventBridgePublisher`.
+ `"source"`indica qual sistema ou servidor enviou a mensagem.
  + Esse será o nome da função se estiver publicando AWS Lambda, o nome do cluster e o ARN da tarefa se estiver no Amazon ECS, o ID da instância se estiver na Amazon, caso contrário EC2, um valor alternativo de. `/aws/messaging` 
  + Você pode substituir isso por meio de `AddMessageSource` ou `AddMessageSourceSuffix` no`MessageBusBuilder`.
+ `"time"`definido para o atual DateTime em UTC. Isso pode ser substituído implementando o seu próprio `IDateTimeHandler` e injetando-o no contêiner DI.
+ `"data"`contém uma representação JSON do objeto.NET que foi enviado ou recebido como mensagem:
  + `ConfigureSerializationOptions`on `MessageBusBuilder` permite que você configure o [https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions)que será usado ao serializar e desserializar a mensagem.
  + Para injetar atributos adicionais ou transformar o envelope da mensagem depois que a estrutura o cria, você pode implementar `ISerializationCallback` e registrar isso por meio de on. `AddSerializationCallback` `MessageBusBuilder`

# Segurança para a estrutura de processamento de AWS mensagens para.NET
<a name="msg-proc-fw-security"></a>

A Estrutura de Processamento de AWS Mensagens para.NET depende do AWS SDK para .NET para se comunicar com. AWS Para obter mais informações sobre segurança no AWS SDK para .NET, consulte[Segurança para este AWS produto ou serviço](security.md).

Por motivos de segurança, a estrutura não registra mensagens de dados enviadas pelo usuário. Se quiser habilitar essa funcionalidade para fins de depuração, você precisa chamar o Message Bus da seguinte `EnableDataMessageLogging()` forma:

```
builder.Services.AddAWSMessageBus(bus =>
{
    builder.EnableDataMessageLogging();
});
```

Se você descobrir um possível problema de segurança, consulte a [política de segurança](https://github.com/aws/aws-dotnet-messaging/security/policy) para relatar informações.

# Integração AWS com o.NET Aspire no AWS SDK para .NET
<a name="aspire-integrations"></a>

O.NET Aspire é uma nova forma de criar aplicativos prontos para a nuvem. Em particular, ele fornece uma orquestração para ambientes locais nos quais executar, conectar e depurar os componentes de aplicativos distribuídos. Para melhorar o ciclo interno de desenvolvimento de aplicativos prontos para a nuvem, foram criadas integrações com o.NET Aspire para conectar seus aplicativos.NET aos recursos. AWS Essas integrações estão disponíveis por meio do pacote [Aspire.Hosting.AWS](https://www.nuget.org/packages/Aspire.Hosting.AWS) NuGet .

As seguintes integrações do.NET Aspire estão disponíveis:
+ A capacidade de provisionar seus AWS recursos por meio de [CloudFormation](https://aws.amazon.com/cloudformation/). Essa integração é utilizada no projeto.NET Aspire AppHost .

  Para obter mais informações, consulte a postagem do blog [Integrando AWS com o.NET Aspire](https://aws.amazon.com/blogs/developer/integrating-aws-with-net-aspire/).
+ Instalando, configurando e conectando o AWS SDK para .NET ao [Amazon DynamoDB local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocalHistory.html). Essa integração é utilizada no projeto.NET Aspire AppHost .

  Para obter mais informações, consulte a postagem do blog [Integrando AWS com o.NET Aspire](https://aws.amazon.com/blogs/developer/integrating-aws-with-net-aspire/).
+ Habilite um ambiente de desenvolvimento local para [AWS Lambda](https://aws.amazon.com/lambda/)funções. Essa integração é utilizada no projeto.NET Aspire AppHost .

  Para obter mais informações, consulte as postagens do blog [Criando e depurando aplicativos.NET Lambda com o.NET Aspire (Parte 1) e Criando e depurando aplicativos.NET](https://aws.amazon.com/blogs/developer/building-lambda-with-aspire-part-1/) [Lambda com o.NET](https://aws.amazon.com/blogs/developer/building-lambda-with-aspire-part-2/) Aspire (Parte 2).
**nota**  
Esta é uma documentação de pré-lançamento de um recurso em versão de pré-visualização. Está sujeita a alteração.

  Como esse recurso está em pré-visualização, você precisará optar pelos recursos de pré-visualização. Para obter informações adicionais sobre esse recurso de visualização e como se inscrever, consulte o [problema do rastreador de desenvolvimento](https://github.com/aws/integrations-on-dotnet-aspire-for-aws/issues/17) em. GitHub

## Mais informações
<a name="aspire-integrations-additional"></a>

Para obter informações adicionais e detalhes sobre como você pode usar as integrações que estão disponíveis no [Aspire.Hosting.AWS](https://www.nuget.org/packages/Aspire.Hosting.AWS), consulte os seguintes recursos.
+ Postagem no blog [Integração AWS com o.NET Aspire](https://aws.amazon.com/blogs/developer/integrating-aws-with-net-aspire/).
+ Publicações no blog [Criação e depuração de aplicativos.NET Lambda com o.NET Aspire (Parte 1) e Criação e depuração de aplicativos.NET](https://aws.amazon.com/blogs/developer/building-lambda-with-aspire-part-1/) [Lambda com o.NET](https://aws.amazon.com/blogs/developer/building-lambda-with-aspire-part-2/) Aspire (Parte 2).
+ O [integrations-on-dotnet-aspirerepositório -for-aws ativado](https://github.com/aws/integrations-on-dotnet-aspire-for-aws). GitHub
+ O [README](https://github.com/aws/integrations-on-dotnet-aspire-for-aws/blob/main/src/Aspire.Hosting.AWS/README.md) detalhado do pacote [Aspire.Hosting.AWS](https://www.nuget.org/packages/Aspire.Hosting.AWS) NuGet .

# Support para outros AWS serviços e configuração
<a name="other-apis-intro"></a>

Os AWS serviços de AWS SDK para .NET suporte, além dos descritos nas seções anteriores. Para obter informações sobre todos os serviços compatíveis, consulte a [Referência AWS SDK para .NET da API](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/). APIs 

Além dos namespaces para AWS serviços individuais, o AWS SDK para .NET também fornece o seguinte: APIs


****  

| Área | Descrição | Recursos | 
| --- | --- | --- | 
|  AWS Support  |  Acesso programático aos casos de AWS suporte e aos recursos do Trusted Advisor.  |  Veja a [Amazon. AWSSupport](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/AWSSupport/NAWSSupport.html)e [Amazon. AWSSupport.Modelo](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/AWSSupport/NAWSSupportModel.html).  | 
|  Geral  |  Classes auxiliares e enumerações.  |  Consulte [Amazon](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Amazon/N.html) e [Amazon.Util](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Util/NUtil.html).  | 