Deploy .NET Core 6 Application no Azure Web App com GitHub Actions

Olá, pessoal, tudo bem?

Nesse post vou mostrar como publicar um aplicação feita em .NET Core 6 no Azure Web App utilizando GitHub Actions.

A aplicação que faremos deploy pode ser encontrada nesse link e ela consiste em calcular o Fatorial de um número utilizando Recursão como solução para o problema. Aproveitando, vou deixar abaixo uma citação muito interessante sobre recursão.

“Os loops podem melhorar o desempenho do seu programa. A recursão melhorar o desempenho do seu programador. Escolha o que for mais importante para a sua situação.”

Leigh Coldwell (Retirado do livro: Entendendo Algoritmos)

Sem mais delongas, vamos para o passo a passo.

Primeiramente, vamos acessar o portal do Azure e criar um Web App.

  1. Clique em Create a Resource e na barra de pesquisa digite Web App em seguida clique em Create.
  2. Agora vamos preencher os dados necessários para criar nosso Web App:
    1. Selecione ou crie um Resource Group;
    2. Digite um nome para sua Web App (lembrando que esse nome precisa ser único);
    3. No Runtime stack, selecione .NET 6 (LTS);
    4. Em Operating System, selecione Linux;
    5. Em Region, selecione a região que mais lhe agrada;
    6. Em SKU and Size selecione o plano que deseja (existe um plano Free);
    7. E finalize clicando em Next:Deployment;
  3. Nesse momento começa a configuração do Deploy contínuo utilizando GitHub Actions.
    1. Em Continuous deployment, marque Enable;
    2. Faça o login da sua conta GitHub;
    3. Na sequência, selecione a Organização, o Repositório e a Branch que deseja que ocorra o deploy;
  4. Agora clique em Review + Create (Poderíamos customizar mais configurações no nosso Web App, entretanto como o propósito desse artigo é demonstrar como fazer o deploy, ja vamos finalizar nossa customização aqui).

Assim que terminar o deploy, podemos clicar no link (https://<nome_do_seu_webapp>.azurewebsites.net) para acessar a nossa aplicação. Feito isso observe que ocorre um HTTP ERROR 404, entretanto veja que nossa aplicação esta funcionando, e para confirmar isso basta fazer um curl na API, conforme exemplo abaixo:

curl -X 'GET' \                                                                                 127 ✘  15:53:27 
  'https://web-factorial.azurewebsites.net/Factorial?number=5' \
  -H 'accept: */*'
The factorial of the number 5 is 120.%

Para deixarmos algo mais amigável, note que o deploy esta considerando o environment como Produção e no nosso código por padrão (e principalmente, por segurança), o Swagger só esta habilitado para ambiente de desenvolvimento, então se voltamos ao nosso código no arquivo Program.cs e comentar o seguinte trecho de código:

//if (app.Environment.IsDevelopment())
//{
    app.UseSwagger();
    app.UseSwaggerUI();
//}

E na sequência, comitarmos, observe que automaticamente o Deploy sera executado, e ao seu término o Swagger estará disponível, conforme figura abaixo:

Figura 1

E assim encerramos esse artigo. Espero que tenham gostado e até a próxima.

Muito Obrigado!

Azure Weekend 2022 – Piracicaba

Olá pessoal,

No sábado 02/07 participei do Azure Weekend 2022 em Piracicaba, evento em que palestrei sobre os Principais Serviços que todo desenvolvedor precisa conhecer no Azure. Tivemos um publico participante de aproximadamente 40 pessoas.

Os slides utilizados na minha palestra, você confere logo abaixo:

Abaixo algumas imagens do evento:

Azure Weekend 2022 - Piracicaba
Azure Weekend 2022 – Piracicaba
Azure Weekend 2022 - Piracicaba
Azure Weekend 2022 – Piracicaba

Deixo aqui meus agradecimentos a todos que puderam participar.

Até a próxima!

Criando um CRUD Serverless com Azure Functions – Parte 4

Olá pessoal, tudo bem? Neste post derradeiro sobre como criar um CRUD Serverless com Azure Functions, vamos aprender como orquestrar nossas API’s utilizando o Azure API Management. O intuito desse post não é explicar em detalhes esse serviço, mas sim em focar como podemos deixar nossas API’s mais seguras.

Primeiramente, acesse o https://portal.azure.com e clique em Create a Resource, e logo na sequência na barra de busca pesquise por API Management.

Preencha as informações necessárias e aguarde a criação do serviço terminar (isso leva em média 20 minutos). Agora nosso próximo passo será importar nossas API’s e para isso na barra esquerda clique em API’s e em seguida selecione Function App. No modal que aparecer clique em Browse, depois em Function App e então selecione a aplicação Serverless que publicamos na parte 3 do artigo, e após o preenchimento dos dados clique em Create.

Observe que você pode criar um sufixo para a chamada das API’s editando o campo API URL suffix. Outro ponto interessante é que ele nos mostra todas as nossas API’s (HttpTriggers) e quais desejamos importar (por padrão todas vem selecionadas).

Dessa forma, terminada a importação, vamos adicionar um “Produto” para a nossa API. Por padrão temos duas opções: Starter e Unlimited, tendo a possibilidade criarmos um customizado também caso necessário.

Após selecionado o produto, vamos clicar em Developer portal e logo abaixo do nome de login (provavelmente ADMINISTRATOR), selecione a opção Profile. Note que clicando nessa opção apareceram os dois produtos disponíveis (Starter e Unlimited) como duas Keys para cada um. Essas keys serão fundamentais para que nossas API’s funcionem pois sem elas, se tentarmos acessa-las aparecerá o seguinte erro:

{
  "statusCode": 401,
  "message": "Access denied due to invalid subscription key. Make sure to provide a valid key for an active subscription."
}

Então nosso próximo passo será autorizar a chamada das nossas API’s e para isso será necessário passar um Header da requisição chamado Ocp-Apim-Subscription-Key e como valor a Key do produto em questão. Note que se você fizer a chamada de alguma API ela vai funcionar perfeitamente.

Agora vamos implementar algumas Policies para nossa aplicação. Habilitaremos o CORS, na sequência as chamadas para um determinado range de IP’s e por fim restringir um numero abusivo de chamadas as nossas API’s em um pequeno espaço de tempo.

Para isso selecione nosso conjunto de API’s e clique em base nas opções de Inbound processing e em seguida adicione o código abaixo para habilitar o CORS (lembre-se que todo o código deve ser colocado dentro da tag de inbound):

<cors>
    <allowed-origins>
        <origin>{SUA_URL}</origin>
    </allowed-origins>
    <allowed-methods>
        <method>*</method>
    </allowed-methods>
    <allowed-headers>
        <header>*</header>
    </allowed-headers>
    <expose-headers>
        <header>*</header>
    </expose-headers>
</cors>

Agora vamos liberar apenas um range de IP:

<ip-filter action="allow">
    <address-range from="<IP_INICIO>" to="<IP_FIM>" />
</ip-filter>

Por último, com o código abaixo, restringiremos por 15 segundos o acesso as nossas API’s caso alguém acesse alguma delas 3 vezes seguidas em sequência.

<rate-limit-by-key calls="3" renewal-period="15" counter-key="@(context.Request.IpAddress)" increment-condition="@(context.Response.StatusCode == 200)" />

Bom pessoal e assim finalizamos nossa série Criando um CRUD Serverless com Azure Functions.

E para finalizar deixo aqui um convite.

Que tal aprender mais sobre Docker, Kubernetes e a implementação de soluções baseadas em containers utilizando o Microsoft Azure, em um workshop que acontecerá durante um sábado todo (dia 04/04) em São Paulo Capital e implementando um case na prática?

Acesse então o link a seguir para efetuar sua inscrição (já incluso camiseta, emissão de certificado e almoço para os participantes) com o desconto: http://bit.ly/anp-docker-blog-ericson

Espero que tenham gostado e até a próxima.

Obrigado!

Criando um CRUD Serverless com Azure Functions – Parte 3

Olá pessoal, tudo bem?

Seguindo a nossa série em que vamos criar um CRUD Serverless com Azure Functions, hoje desenvolveremos a listagem dos nossos registros, a publicação da nossa Function App no Azure e por fim a publicação de um site estático consumindo nossas API’s no Azure Storage.

Primeiramente vamos trabalhar na listagem dos registros, e portanto, começaremos criando nossa Function através do comando abaixo:

func new

Feito isso, como já é sabido, aparecerão diversas opções de Azure Functions, cada uma para um propósito diferente, e no nosso caso escolheremos o tipo HttpTrigger e então nós daremos a ela o nome de ListPeople.

Abra o arquivo criado (ListPeople.cs) e vamos altera-lo com o código abaixo:

public static async Task<IEnumerable<Person>> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
    [Table("Person")]CloudTable cloudTable,
    ILogger log)
{
    log.LogInformation("ListPeople function started a request.");

    var tableQuery = new TableQuery<Person>();
    TableContinuationToken continuationToken = null;

    TableQuerySegment<Person> tableQueryResult;
    do
    {
        tableQueryResult = await cloudTable.ExecuteQuerySegmentedAsync(tableQuery, continuationToken);
        continuationToken = tableQueryResult.ContinuationToken;
    } while (continuationToken != null);

    log.LogInformation("ListPeople function finished a request.");

    return tableQueryResult.Results;
}

Observe que o código mudou levemente em relação as HttpTriggers anteriores. Nesse código mudamos o retorno da Função, sendo que agora ela retorna um IEnumerable de Person e para que isso seja possível utilizamos o comando TableQuerySegment para trazer todos os registros da nossa tabela.

Vamos agora executar nosso Function App utilizando o comando abaixo:

func start

Agora vamos testar nossa função de listagem de registros (para isso recomendo utilizar um Client REST da sua preferência) acessando o novo endpoint criado: ListPeople: [GET] http://localhost:7071/api/ListPeople, e observe ele retornou todos os registros cadastrados.

Ao contrário do que vimos na parte 1 e parte 2 do artigo, não criaremos nenhuma QueueTrigger, pois não iremos enfileirar nenhuma consulta, ao invés disso, vamos criar mais uma HttpTrigger e dessa vez será para trazer um único registro ao invés da listagem toda.

Novamente vamos utilizar o comando abaixo:

func new

Feito escolheremos novamente o tipo HttpTrigger e para essa função daremos o nome de GetPerson.

Abra o arquivo criado (GetPerson.cs) e vamos altera-lo com o código abaixo:

public static async Task<Person> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
    [Table("Person")]CloudTable cloudTable,
    ILogger log)
{
    log.LogInformation("GetPerson function started a request.");

    var partitionKey = "Person";
    var rowKey = req.Query["id"];

    TableOperation person = TableOperation.Retrieve<Person>(partitionKey, rowKey);
    TableResult result = await cloudTable.ExecuteAsync(person);

    log.LogInformation("GetPerson function finished a request.");

    return (Person)result.Result;
}

Note que o código acima não é bem semelhante ao que já produzimos nas Funções anteriores e então vamos mais uma vez testar a nossa aplicação, utilizando o comando:

func start

Mais uma vez vamos acessar o novo endpoint criado: GetPerson: [GET] http://localhost:7071/api/GetPerson, (lembre-se de passar o RowKey via QueryString sob o parâmetro de nome id ), e observe ele retornou o registro cadastrado.

Agora finalmente vamos publicar tudo isso no Azure, e para isso (caso ainda não tenha instalado), vamos instalar a extensão do Azure Functions no VsCode e com ela instalada, você irá clicar na opção Deploy to Function App…, e em seguida selecione sua Subscription no Azure (caso possua mais de uma), nosso próximo passo será selecionar Create a New Function App in Azure, feito isso ele irá lhe pedir um nome (necessita ser único globalmente), e por fim selecione a Region em que deseja fazer o deploy.

Agora é so aguardar alguns minutos para que o deploy seja finalizado no Azure.

Bônus

Para deixarmos nosso CRUD mais profissional podemos criar uma Single Page Application utilizando Angular e publicar isso no Azure, gastando apenas o custo de armazenamento, sem que seja cobrado qualquer custo de computação. Para realizarmos esse próximo passo, deixo abaixo um vídeo que eu publiquei no canal Azure na Prática fazendo um passo a passo de como fazer isso.

Por sim para quem tiver interesse todo o código da nossa Function App encontra-se no meu GitHub, inclusive contendo uma Single Page Application feita em Angular, pronta para ser publicada. Lembrando que no próximo e último artigo da série de posts, vou demonstrar como utilizarmos o Azure API Management pra a orquestração das nossas API’s criadas na nossa Function App.

E para finalizar deixo aqui um convite.

Que tal aprender mais sobre Docker, Kubernetes e a implementação de soluções baseadas em containers utilizando o Microsoft Azure, em um workshop que acontecerá durante um sábado todo (dia 04/04) em São Paulo Capital e implementando um case na prática?

Acesse então o link a seguir para efetuar sua inscrição (já incluso camiseta, emissão de certificado e almoço para os participantes) com o desconto: http://bit.ly/anp-docker-blog-ericson

Até mais pessoal.

Abraços e Obrigado!

Criando um CRUD Serverless com Azure Functions – Parte 2

Olá pessoal, tudo bem?

Seguindo a nossa série em que vamos criar um CRUD Serverless com Azure Functions, hoje desenvolveremos a parte de edição e de exclusão do nosso registro.

Primeiramente vamos trabalhar na edição, e portanto, começaremos criando nossa Function através do comando abaixo:

func new

Feito isso, como já é sabido, aparecerão diversas opções de Azure Functions, cada uma para um propósito diferente, e no nosso caso escolheremos o tipo HttpTrigger e então nós daremos a ela o nome de EditPerson.

Abra o arquivo criado (EditPerson.cs) e vamos altera-lo com o código abaixo:

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "put", Route = null)]HttpRequest req,
    [Queue("EditPerson", Connection = "AzureWebJobsStorage")]IAsyncCollector<string> queueItem,
    ILogger log)
{
    log.LogInformation("EditPerson function started a request.");

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    await queueItem.AddAsync(requestBody);

    log.LogInformation("EditPerson function finished a request.");

    return new OkObjectResult($"Obrigado! Seu registro já esta sendo processado.");
}

Observe que o código não é muito diferente do código da nossa HttpTrigger que criamos na parte 1 do nosso post.

Dica: Observe que na chamada da nossa HttpTrigger existe uma propriedade chamada Route, ela serve para customizarmos a rota da nossa Function caso você queira, do contrário o padrão será sempre o nome da sua HttpTrigger.

Vamos agora executar nosso Function App utilizando o comando abaixo:

func start

Note que agora nós temos dois endpointsCreatePerson: [POST] http://localhost:7071/api/CreatePerson e EditPerson: [PUT] http://localhost:7071/api/EditPerson e com isso já é possível testar nossa função de edição (para isso recomendo utilizar um Client REST da sua preferência), porém dessa vez precisaremos passar além das propriedades Name e Email as propriedades para encontrar o registro em si e elas são a PartitionKey e o RowKey. Com isso seu body deve ficar muito parecido com que se encontra logo abaixo:

{
	"name": "Blog do Ericson - Edit",
	"email": "ericson@email.com",
        "partitionKey": "Person",
        "rowKey": "<GUID_DO_REGISTRO>"
}

Feito isso abra a ferramenta Microsoft Azure Storage Explorer e localize dentro de Storage Account o serviços de Queues e abrindo-o note que foi criada uma Queue chamada EditPerson. Abra a mesma e note que o body que passamos para o nosso endpoint estará armazenado na fila.

Agora nosso próximo passo, assim como na parte 1 do nosso post, será o de desenfileirar a mensagem e salva-la no nosso banco de dados e para isso vamos criar nossa próxima Azure Function, e para isso, novamente vamos utilizar o comando abaixo:

func new

Dessa vez escolheremos o tipo QueueTrigger e colocaremos o nome dela de EditPersonQueue e em seguida, vamos altera-la com o código abaixo:

public static void Run(
    [QueueTrigger("EditPerson", Connection = "AzureWebJobsStorage")]string queueItem,
    [Table("Person")]CloudTable cloudTable,
    ILogger log)
{
    log.LogInformation($"EditPersonQueue trigger function started.");

    var data = JsonConvert.DeserializeObject<Person>(queueItem);

    var tableOperation = TableOperation.InsertOrReplace(data);
    cloudTable.ExecuteAsync(tableOperation);

    log.LogInformation($"EditPersonQueue trigger function finished.");
}

Note que novamente não há muita mudança em relação nossa Queue Trigger criada no post anterior.

Com isso vamos executar nosso Function App novamente através do comando:

func start

E então abra novamente o Microsoft Azure Storage Explorer e note que a mensagem sumiu da fila EditPerson, e agora o registro encontra-se editado na nossa tabela Person.

Agora que a edição esta finalizada e funcionando perfeitamente, vamos para o próximo passo que é o de excluir o nosso registro, e para isso vamos novamente criar mais uma função através do comando abaixo:

func new

Novamente, escolha o tipo HttpTrigger e então nós daremos a ela o nome de DeletePerson.

Abra o arquivo criado (DeletePerson.cs) e vamos altera-lo com o código abaixo:

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "delete", Route = null)]HttpRequest req,
    [Queue("DeletePerson", Connection = "AzureWebJobsStorage")]IAsyncCollector<string> queueItem,
    ILogger log)
{
    log.LogInformation("DeletPerson function started a request.");

    await queueItem.AddAsync(
        JsonConvert.SerializeObject(
            new Person
            {
                PartitionKey = "Person",
                RowKey = req.Query["id"]
            }
        )
    );

    log.LogInformation("DeletePerson function finished a request.");

    return new OkObjectResult($"Obrigado! Seu registro já esta sendo processado.");
}

Observe que agora nossa HttpTrigger, ao contrario das criadas anteriormente, espera como body apenas o Partition Key (coloquei ele já direto no código, mas você pode passa-lo como parâmetro caso queira) e o RowKey que será passado via QueryString sob o parâmetro de nome id.

Vamos agora executar nosso Function App utilizando o comando abaixo:

func start

Note que agora nós temos três endpointsDeletePerson: [DELETE] http://localhost:7071/api/DeletePerson, CreatePerson: [POST] http://localhost:7071/api/CreatePerson e EditPerson: [PUT] http://localhost:7071/api/EditPerson e com isso já é possível testar nossa função de exclusão (para isso recomendo utilizar um Client REST da sua preferência), porém dessa vez conforme precisaremos apenas do RowKey e com isso sua QueryString deve ficar muito parecido com que se encontra logo abaixo:

http://localhost:7071/api/DeletePerson?id=<GUID_DO_REGISTRO>

Feito isso abra a ferramenta Microsoft Azure Storage Explorer e localize dentro de Storage Account o serviços de Queues e abrindo-o note que foi criada uma Queue chamada DeletePerson. Abra a mesma e note que o body que passamos para o nosso endpoint estará armazenado na fila.

Agora nosso próximo passo, assim como na parte 1 do nosso post, será o de desenfileirar a mensagem e salva-la no nosso banco de dados e para isso vamos criar nossa próxima Azure Function, e para isso, novamente vamos utilizar o comando abaixo:

func new

Dessa vez escolheremos o tipo QueueTrigger e colocaremos o nome dela de DeletePersonQueue e em seguida, vamos altera-la com o código abaixo:

public static void Run(
    [QueueTrigger("DeletePerson", Connection = "AzureWebJobsStorage")]string queueItem,
    [Table("Person")]CloudTable cloudTable,
    ILogger log)
{
    log.LogInformation($"DeletePersonQueue trigger function started.");

    var data = JsonConvert.DeserializeObject<Person>(queueItem);

    var person = new DynamicTableEntity(data?.PartitionKey, data?.RowKey);
    person.ETag = "*";

    var tableOperation = TableOperation.Delete(person);
    cloudTable.ExecuteAsync(tableOperation);

    log.LogInformation($"DeletePersonQueue trigger function finished.");
}

Note que dessa vez houve uma certa mudança em relação nossa Queue Trigger criada no post anterior.

Aqui nos primeiros temos que recuperar o registro da nossa Table Person, baseando-se na PartitionKey e no RowKey antes de mais nada e na sequência setar a propriedade ETag. Falando rapidamente sobre essa propriedade, ela consegue atuar no caso de concorrência de alterações de um registro, como aqui eu quero excluir o mesmo eu estou setando com o * e isso significa que eu estou dizendo para o Tables não se preocupar em monitorar essa exclusão.

Com isso vamos executar nosso Function App novamente através do comando:

func start

E então abra novamente o Microsoft Azure Storage Explorer e note que a mensagem sumiu da fila DeletePerson, e agora o registro também não existe mais na nossa tabela Person.

Bom pessoal, e com isso finalizamos a segunda parte do nosso CRUD Serverless em que editamos e excluímos o nosso registro. No nosso próximo post vamos trabalhar na exibição dos registros já cadastrados e na publicação do nosso Function App no Azure.

E para finalizar deixo aqui um convite.

Que tal aprender mais sobre Docker, Kubernetes e a implementação de soluções baseadas em containers utilizando o Microsoft Azure, em um workshop que acontecerá durante um sábado todo (dia 04/04) em São Paulo Capital e implementando um case na prática?

Acesse então o link a seguir para efetuar sua inscrição (já incluso camiseta, emissão de certificado e almoço para os participantes) com o desconto: http://bit.ly/anp-docker-blog-ericson

Até mais pessoal.

Abraços e Obrigado!

Criando um CRUD Serverless com Azure Functions – Parte 1

Olá pessoal tudo bem?

Iniciaremos através deste post uma série sobre como montar um CRUD completo utilizando a última versão (3) do Azure Functions.

Importante: Para concluirmos o CRUD de maneira satisfatória, vamos precisar instalar as seguintes ferramentas:

No Visual Studio Code recomendo fortemente instalar a extensão do Azure Functions, pois ela vai nos ajudar bastante.

Assim que todas as instalações forem concluídas, vamos executar o Azure Storage Emulator (caso o mesmo já não esteja em execução), e então na sequência, vamos criar nosso projeto no Visual Studio Code, abrindo seu Terminal (Ctrl + ‘) e em seguida digitando o seguinte comando:

func init

Feito vão aparecer 4 opções de seleção, nesse caso, selecione a primeira opção “dotnet”, e então, espere que termine a criação do nosso Function App.

Nosso próximo passo será o de criar nossa primeira Azure Function, e para isso digite o comando abaixo:

func new

Feito isso apareceram diversas opções de Azure Functions, cada uma para um propósito diferente, e no nosso caso escolheremos o tipo HttpTrigger e daremos a ela o nome de CreatePerson.

Abra o arquivo criado (CreatePerson.cs) e observe que ele já veio com um código padrão. Esse código nada mais faz, do que esperar um parâmetro chamado name e no fim exibirá uma mensagem de boas vindas.

Note que a função possui um cabeçalho, e ele e de extrema importância, pois é através dele que “injetaremos” os serviços que desejamos consumir na nossa Function.

Dica 1: Por boas práticas inclusive recomendadas no livro Clean Code do Robert C. Martin (Cap. 3 – Functions), uma Função deve ser extremamente pequena e no caso das Azure Functions isso não é excessão, lembre sempre que se uma Função tiver mais de um propósito, faça uma refatoração da mesma.

Dica 2: Quando suas Azure Functions estiverem publicadas no Azure, caso o plano escolhido seja o Consumption (mais barato), uma função tem tempo limite de 10 minutos para executar, logo já é mais que um bom motivo para suas funções serem “pequenas”.

Voltando para a nossa função CreatePreson vamos substitui o código padrão pelo código abaixo:

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequest req, 
    [Queue("CreatePerson", Connection = "AzureWebJobsStorage")]IAsyncCollector<string> queueItem, 
    ILogger log)
{
    log.LogInformation("CreatePerson function started a request.");

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    await queueItem.AddAsync(requestBody);

    log.LogInformation("CreatePerson function finished a request.");

    return new OkObjectResult($"Obrigado! Seu registro já esta sendo processado.");
}

Observe que o Visual Studio Code vai indicar um erro, na palavra Queue e na propriedade Connection. Isso deve ao fato de que ele não encontrou as mesmas e portanto precisamos importar o SDK do Azure Storage na nossa aplicação, e para fazer isso, abra o arquivo .csproj do seu projeto e logo abaixo da linha em que ele adiciona a referência do SDK das Azure Functions, adicione a seguinte referência:

<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="3.0.10" />

Com isso ele vai pedir para fazer o Restore do seu projeto e em seguida os erros deixarão de existir.

Comentando sobre o código da nossa Function, nós basicamente “injetamos” a possibilidade de lidar com as Queues do Azure Storage, e então através da nossa HttpTrigger receberemos o conteúdo contido no body da nossa requisição e então, enfileiraremos esse conteúdo no serviço de mensageria do Azure Storage. Note também, que na propriedade Connection eu passo um valor chamado “AzureWebJobsStorage”, nesse caso, vamos abrir o arquivo local.settings.json e localizar a propriedade “AzureWebJobsStorage” e então, substituir o conteúdo dela para a String de Conexão do nosso Azure Storage Emulator. Caso você possua Mac ou Linux você pode indicar nesse local a String de Conexão do seu Azure Storage no Azure.

Como desejamos fazer um CRUD completo, vou utilizar a classe abaixo (Person.cs) como referência para o nosso cadastro.

using Microsoft.WindowsAzure.Storage.Table;

namespace AzureFunctions
{
    public class Person : TableEntity
    {
        public string Name { get; set; }
        public string Email { get; set; }

        public Person() { }
    }
}

Observe que na classe Person eu já herdo a classe TableEntity para já facilitar a inserção dos nosso dados em um outro serviço do Azure Storage chamado Azure Tables.

Feito isso, vamos testar nosso Function App, e para isso digite o seguinte comando:

func start

Note que ele criou o seguinte endpoint para nós: CreatePerson: [POST] http://localhost:7071/api/CreatePerson e com isso já é possível testar nossa função (para isso recomendo utilizar um Client REST da sua preferência) passando o seguinte body:

{
	"name": "Blog do Ericson",
	"email": "ericson@email.com"
}

Feito isso abra a ferramenta Microsoft Azure Storage Explorer (instalada previamente no inicio do post) e localize dentro de Storage Account o serviços de Queues e abrindo-o note que foi criada uma Queue chamada CreatePerson. Abra a mesma e note que o body que passamos para o nosso endpoint estará armazenado na fila.

Agora nosso próximo passo será desenfileirar a mensagem e salva-la em um banco de dados, e seguindo nosso exemplo esse banco de dados sera o serviço de Tables (banco de dados NoSQL de chave-valor) do Azure Storage.

Vamos então criar uma nova Azure Function, digitando o novamente o comando abaixo:

func new

Feito isso, novamente aparecerão diversas opções de Azure Functions, e dessa vez escolheremos o tipo QueueTrigger e nós daremos a ela o nome de CreatePersonQueue. Após a criação da mesma substitua o código gerado pelo template pelo código abaixo:

public static void Run(
    [QueueTrigger("CreatePerson", Connection = "AzureWebJobsStorage")]string queueItem, 
    [Table("Person")]CloudTable cloudTable, 
    ILogger log)
{
    log.LogInformation($"CreatePersonQueue trigger function started.");

    var data = JsonConvert.DeserializeObject<Person>(queueItem);
    data.PartitionKey = "Person";
    data.RowKey = Guid.NewGuid().ToString();

    var tableOperation = TableOperation.Insert(data);
    cloudTable.ExecuteAsync(tableOperation);

    log.LogInformation($"CreatePersonQueue trigger function finished.");
}

No código acima, vamos deserializar a mensagem para o tipo Person e em seguida precisamos criar duas propriedades obrigatórias para que se possa utilizar o serviço de Tables do Azure Storage. Explicando de maneira bem resumida, a RowKey teria uma função similar ao de um ID de um banco de dados relacional e a PartitionKey teria a função de ajustar o particionamento automático do serviço de Tables do Azure Storage.

Com isso vamos executar nosso Function App novamente através do comando:

func start

E então abra novamente o Microsoft Azure Storage Explorer e note que a mensagem sumiu da fila, e agora a mesma encontra-se salva na tabela Person (criada automaticamente) dentro do serviço de Tables.

Bom pessoal, e com isso finalizamos a primeira parte do nosso CRUD Serverless em que criamos nosso registro. No nosso próximo post vamos trabalhar na edição e exclusão dele.

E para finalizar deixo aqui um convite.

Que tal aprender mais sobre Docker, Kubernetes e a implementação de soluções baseadas em containers utilizando o Microsoft Azure, em um workshop que acontecerá durante um sábado todo (dia 04/04) em São Paulo Capital e implementando um case na prática?

Acesse então o link a seguir para efetuar sua inscrição (já incluso camiseta, emissão de certificado e almoço para os participantes) com o desconto: http://bit.ly/anp-docker-blog-ericson

Até mais pessoal.

Abraços e Obrigado!

Global Azure Bootcamp 2019 – Campinas

Olá pessoal,

No último sábado dia 27/04 participei do Global Azure Bootcamp 2019 – Campinas, evento no qual ajudei na organização, palestrando e também ministrando um workshop (este último em parceria com o Robson Rocha). As incrições do evento foram efetuadas pelo Sympla e tivemos um publico de 70 pessoas.

Os slides utilizados na minha palestra, sobre como Desenvolver “offline” no Azure você confere logo abaixo:

E para quem quiser o código utilizado, é só baixar através desse link

Já sobre o Workshop dos 5 Serviços do Azure que todo o Desenvolvedor precisa conhecer, os slides você confere logo abaixo e o código utilizado através desse link

Abaixo algumas fotos do evento.

Global Azure Bootcamp 2019
Global Azure Bootcamp 2019

MVP Conf Latam 2019

Olá pessoal,

Na última sexta-feira dia 12/04 participei do MVP Conf Latam 2019 palestrando sobre os Cinco Serviços do Azure que todo desenvolvedor precisa conhecer.

Este evento contou com mais de 2.000 pessoas inscritas e todo o valor arrecadado na venda dos ingressos foi destinado a intituições de caridade, uma em cada região do Brasil.

Os slides utilizados na palestra você confere logo abaixo:

Deixo aqui também o código fonte utilizado através desse link.

Algumas fotos da minha palestra e do evento:

MVP Conf
MVP Conf Latam 2019
MVP Conf
MVP Conf Latam 2019
MVP Conf
MVP Conf Latam 2019

Open Source Roadshow 2019 – Mogi das Cruzes-SP

Olá pessoal,

No último sábado dia 09/03 participei do Open Source Roadshow 2019 – Mogi das Cruzes-SP, evento no qual ajudei tanto na organização quanto palestrando sobre como Hospedar sua aplicação na nuvem com o Azure App Service.

Os slides utilizados na palestra você confere logo abaixo:

E para quem quiser o container utilizado no exemplo é só baixar através desse link.

Deixo aqui também dois artigos que já publiquei como referência ao conteúdo apresentado.

Também gostaria de deixar aqui, meu muito obrigado para o pessoal do Caqui Coders pelo apoio em todo o evento.

Abaixo, fotos do evento.

Open Source Roadshow 2019 – Mogi das Cruzes-SP
Open Source Roadshow 2019 – Mogi das Cruzes-SP
Open Source Roadshow 2019 – Mogi das Cruzes-SP

Microsoft Connect(); 2019

Olá pessoal,

No último sábado dia 19/01 participei do Microsoft Connect(); 2019 tanto na organização do evento quanto na palestra que fiz juntamente com o Robson Rocha, falando sobre os 5 serviços do Microsoft Azure que todo desenvolvedor .NET precisa conhecer.

Os slides utilizados na palestra você confere logo abaixo:

Também deixo aqui meu muito obrigado para o prof. João Cunha pelo apoio no local do evento.

Abaixo, fotos do evento

Microsoft Connect 2019 01
Microsoft Connect 2019
Microsoft Connect 2019 02
Microsoft Connect 2019
Microsoft Connect 2019 03
Microsoft Connect 2019