# Programação em C# - Na API de integração (POST)

As informações descritas abaixo referem-se as APIs de <span style="text-decoration: underline;">**POST**</span>

<p class="callout danger">IMPORTANTE: as variáveis e métodos descritos aqui só funcionarão na programação C# na **API de integração**. Para a programação C# nas Regras de Negócio de um formulário [clique aqui](https://wiki.agilityflow.io/books/manual-de-customiza%C3%A7%C3%A3o/page/programa%C3%A7%C3%A3o-em-c---na-regra-de-neg%C3%B3cio "Programação em C# - Na Regra de Negócio")</p>

O agilityflow permite a customização da API em C#, além de já disponibilizar diversas bibliotecas e funções para facilitar sua programação, incluindo acesso a dados, validações, envio de e-mail, notificação, entre outras.

<p class="callout info">Para cada requisição na API é criada uma transação de banco de dados, essa transação é única em toda execução da API e é gerenciada automaticamente pelo Agilityflow, caso você prefira, você pode fazer esse gerenciamento seguindo esses passos, [veja mais detalhes aqui](https://wiki.agilityflow.io/link/90#bkmrk-%E2%A0-15)</p>

Abaixo mostramos alguns exemplos, se o material abaixo não for suficiente , entre em contato com nossa equipe.

#### Variáveis disponíveis

<table border="1" id="bkmrk-vari%E3%A1vel-tipo-%E2%A0-fo" style="border-collapse: collapse; width: 147.516%; height: 41px;"><tbody><tr style="height: 31px;"><td style="width: 22.4663%; height: 31px;">**Variável**</td><td style="width: 26.6063%; height: 31px;">**Tipo**</td><td style="width: 127.347%; height: 31px;"> </td></tr><tr style="height: 400px;"><td style="width: 22.4663%; height: 10px;">content</td><td style="width: 26.6063%; height: 10px;">string</td><td style="width: 127.347%; height: 10px;">Conteúdo enviado no Body da API

No caso se ser enviado uma string com o JSON, por exemplo no formato:

 <span style="background-color: #f8f8f8; font-family: 'Lucida Console', 'DejaVu Sans Mono', 'Ubunto Mono', Monaco, monospace; font-size: 0.8em; white-space: pre;">{ nome: 'José', email: 'jose@xxxx.com'}</span>

<div></div>Você pode converter essa string para JSON e utilizá-la como object

`var json = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(content);`

</td></tr></tbody></table>

#### Classe JsonHelper e outras para auxiliar o tratamento de JSON

Para utilizar execute `JsonHelper.NomeDoMetodo(....)`

<table border="1" id="bkmrk-op%E3%A7%E3%A3o-retorno-%E2%A0-g" style="border-collapse: collapse; width: 121.652%; height: 303px;"><tbody><tr style="height: 31px;"><td style="width: 48.7627%; height: 31px;">**Método**</td><td style="width: 16.6063%; height: 31px;">**Retorno**</td><td style="width: 54.3841%; height: 31px;"> </td></tr><tr style="height: 31px;"><td style="width: 48.7627%; height: 31px;">**HasProperty**(dynamic json, string nomePropriedade)</td><td style="width: 16.6063%; height: 31px;">bool

(true or false)

</td><td style="width: 54.3841%; height: 31px;">Testa se o JSON tem uma determinada propriedade.

Por exemplo, a sua API espera receber o JSON

no formato:

 <span style="background-color: #f8f8f8; font-family: 'Lucida Console', 'DejaVu Sans Mono', 'Ubunto Mono', Monaco, monospace; font-size: 0.8em; white-space: pre;">{ <span style="color: #0000ff;">nome</span>: 'José', <span style="color: #0000ff;">email</span>: 'jose@xxxx.com'}</span>

Porém recebe o JSON formato:

 <span style="background-color: #f8f8f8; font-family: 'Lucida Console', 'DejaVu Sans Mono', 'Ubunto Mono', Monaco, monospace; font-size: 0.8em; white-space: pre;">{ <span style="color: #ff0000;">nomecompleto</span>: 'José da Silva', <span style="color: #ff0000;">idade</span>: '21'}</span>

Como a propriedade NOME e EMAIL não existem no JSON recebido, o seu programa pode dar erro. Para evitar o erro, utilize o método <span style="color: #0000ff;">HasProperty</span>(...)

Como no exemplo abaixo:

`if (json != null)`  
`{`  
  
`if (JsonHelper.HasProperty(json, "nome") && JsonHelper.HasProperty(json, "email") ){`  
  
`var nome =  json["nome"].ToString();`

`var email=  json["email"].ToString();`  
  
`}`  
  
`}`

</td></tr><tr><td style="width: 48.7627%;">`Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(content);`  
</td><td style="width: 16.6063%;">dynamic

</td><td style="width: 54.3841%;">converte o conteúdo string para json

`var content = "{ nome: 'José', email: 'jose@xxxx.com'}";`

`var json = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(content);`

`var nome =  json["nome"].ToString();`

</td></tr></tbody></table>

#### Métodos Disponíveis no contexto da API

<table border="1" id="bkmrk-m%E3%A9todo-retorno-%E2%A0-s" style="border-collapse: collapse; width: 119.753%; height: 599px;"><tbody><tr style="height: 31px;"><td style="width: 56.0466%; height: 31px;">**Método**</td><td style="width: 17.1002%; height: 31px;">**Retorno**</td><td style="width: 49.6927%; height: 31px;"> </td></tr><tr style="height: 82px;"><td style="width: 56.0466%; height: 82px;">**await ApiContext.GetDataTableAsync**(string sql, params DbParameter\[\] parameters)</td><td style="width: 17.1002%; height: 82px;">DataTable</td><td style="width: 49.6927%; height: 82px;">Recuperar informações dos bancos de dados através de uma query sql.

[Veja exemplo](https://wiki.agilityflow.io/link/90#bkmrk-recuperando-dados-do "Veja exemplo")

</td></tr><tr style="height: 31px;"><td style="width: 56.0466%; height: 31px;">**await ApiContext.SaveEntityAsync**(Guid estruturaformularioid\_ASerCriadoOuAtualizado, DataDictionary campos\_e\_valores)</td><td style="width: 17.1002%; height: 31px;">Guid</td><td style="width: 49.6927%; height: 31px;">Salva as informações de um formulário no bancos de dados.

Obs: Para cadastrar valores numéricos, o números devem estar no formato com ponto no separador decimal: 999999.99 sem utilização de virgulas. Caso seja necessário, utilizar o .ToString() para formatar um campo decimal, não use. Utilize a conversão usando o string.Format, como no exemplo abaixo:

`string.Format(new System.Globalization.CultureInfo("en-gb"), "{0:F2}", json["valor"]);`

[Veja exemplo](https://wiki.agilityflow.io/link/90#bkmrk-salvando-os-dados-re "Veja exemplo")

</td></tr><tr style="height: 31px;"><td style="width: 56.0466%; height: 31px;">**await ApiContext.ApproveEntityAsync**(Guid estruturaformularioid\_ASerAprovado, DataDictionary campos\_e\_valores)</td><td style="width: 17.1002%; height: 31px;">Guid</td><td style="width: 49.6927%; height: 31px;">Avança uma etapa em um formulário com Workflow.

As regras de usuário aprovador, permissão de aprovação e responsabilidade por uma etapa devem ser validadas antes desse método ser executado.

Obs: Para cadastrar valores numéricos, o números devem estar no formato com ponto no separador decimal: 999999.99 sem utilização de virgulas. Caso seja necessário, utilizar o .ToString() para formatar um campo decimal, não use. Utilize a conversão usando o string.Format, como no exemplo abaixo:

`string.Format(new System.Globalization.CultureInfo("en-gb"), "{0:F2}", json["valor"]);`

[Veja exemplo](https://wiki.agilityflow.io/link/90#bkmrk-aprovando-uma-etapa-)

</td></tr><tr><td style="width: 56.0466%;">**await ApiContext.DeleteEntityAsync(Guid formularioId)**</td><td style="width: 17.1002%;">void</td><td style="width: 49.6927%;">deletar um formulario

</td></tr><tr style="height: 130px;"><td style="width: 56.0466%; height: 130px;">**ApiContext.GetEnvironmentVariable**(string nomeVariavel)

ou

**ApiContext.GetEnvironmentVariable\_Text**(string nomeVariavel) \*\*

</td><td style="width: 17.1002%; height: 130px;">string</td><td style="width: 49.6927%; height: 130px;">Recupera o Valor de uma variável de ambiente.

\*\* Recupera a Descrição (texto), no caso de variáveis do Tipo "Que

</td></tr><tr style="height: 224px;"><td style="width: 56.0466%; height: 224px;">**await ApiContext.LogAsync(string log, string logTipo)**

</td><td style="width: 17.1002%; height: 224px;">void</td><td style="width: 49.6927%; height: 224px;">Cria um log na tabela de log geral, o log pode ser consultado entrando na Área de Customização e clicando na opção "Log Geral &gt;&gt; consultar Log"

\*\* Além do Log Padrão da API que o sistema gera, você pode gerar esses Logs customizados para o seu próprio controle.

</td></tr><tr style="height: 35px;"><td style="width: 56.0466%; height: 35px;">**await ApiContext.DbTransaction\_BeginTransactionAsync()**

**await ApiContext.DbTransaction\_CommitAsync()**

**await ApiContext.DbTransaction\_RollbackAsync()**

</td><td style="width: 17.1002%; height: 35px;">void</td><td style="width: 49.6927%; height: 35px;">Para gerenciar a transação de banco de dados manualmente. Leia os detalhes [aqui mais abaixo ](https://wiki.agilityflow.io/link/90#bkmrk-%E2%A0-15)

</td></tr><tr style="height: 35px;"><td style="width: 56.0466%; height: 35px;">**ApiContext.GetUrlBase()**

</td><td style="width: 17.1002%; height: 35px;">void</td><td style="width: 49.6927%; height: 35px;">Retorna a URL base da sua aplicação

exemplo:

[https://suaempresa.agilityflow.io/](https://suaempresa.agilityflow.io/)

\*A url sempre virá com uma barra no final **/**

</td></tr></tbody></table>

##### Recuperando dados do banco de dados através de uma query SQL

```C#
//parametros da query
var paramsQuery = new List<SqlParameter>();
paramsQuery.Add(new SqlParameter("@param1", "xxx"));
paramsQuery.Add(new SqlParameter("@param2", "yyy"));
paramsQuery.Add(new SqlParameter("@param3", "zzz"));

//query usando (nolock) nas tabelas para evitar problema com a transação que está ativa
var sql = "select column1,column2,column3 from table (nolock) where column1 = @param1 or  column2 = @param2 or  column3 = @param3 ";

//executar no banco de dados
var dt = await ApiContext.GetDataTableAsync(sql, paramsQuery.ToArray());

//percorrendo as linhas de retorno da tabela
foreach (DataRow dr in dt.Rows)
{
  if (dr["column1"] != DBNull.Value){
  	var xx = dr["column1"].ToString();
  }
}
```

##### Salvando os dados recebidos através do método SaveEntityAsync

\* Para cadastrar valores numéricos, o números devem estar no formato com ponto no separador decimal: 999999.99 sem utilização de virgulas.

```C#
public void Execute(){
        
  //opcional para registrar no log de controle
  await ApiContext.LogAsync("Entrou da API", "log_api_xpto");
  
            //converte o conteúdo enviado no body da API para JSON
            var json = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(content);
      
            //guarda em uma variável o ID da  E S T R U T U R A  do formulário de pessoa
            var idEstruturaFormulario_PESSOA = Guid.Parse("0b56b66a-4f6f-4ded-ad04-016d7c0724e1");
    
    
            if (json != null)
            {
    
                    //verifica se o JSON recebido contém a propriedade "nome", "email" e "cel" que são necessários p cadastro
                    if (JsonHelper.HasProperty(json, "nome") && JsonHelper.HasProperty(json, "email") && JsonHelper.HasProperty(json, "perfil")){
           
                        var values = new DataDictionary();
                        values.Add("nome", json["nome"].ToString());
                        values.Add("email", json["email"].ToString());
                      
                        //no caso do campo do formulário ser uma tabela associativa (tabela relacional N:N)
                        var idCampoTabelaAssociativa = "70b6f362-2587-4fd2-a2fb-148bd0caf437";
                        if (json["perfil"].ToString() == "todos_os_perfis" ) {
                          
                          var idPerfilAdmin = "51cf02f1-3787-4dca-8a2c-e219a5ce1298";
                          var idPerfilColaborador = "f999f103-c775-4245-92d3-034cb3ded5e4";                          
                          var idPerfisConcatenadosComVirgula = idPerfilAdmin + "," + idPerfilColaborador + ",";
                          
                          //adiciona os perfis
                          values.Add(idCampoTabelaAssociativa, idPerfilAdmin); //adiciona perfil de admin
                          values.Add(idCampoTabelaAssociativa, idPerfilColaborador); //adiciona perfil de colaborador
                          values.Add("tabela_associativa_added-"+idCampoTabelaAssociativa,idPerfisConcatenadosComVirgula);// perfis concatenados com virgula
                          values.Add("tabela_associativa_removed-"+idCampoTabelaAssociativa,"");//em branco, se fosse pra remover, era só colocar os perfis concatenados com virgula
                          //---------------------------------------

                        }
                        else if (json["perfil"].ToString() == "apenas_colaborador" ) {
                          
                          
                          var idPerfilColaborador = "f999f103-c775-4245-92d3-034cb3ded5e4";                        
                          var idPerfilConcatenadoComVirgula = idPerfilColaborador + ",";
                          
                          //adiciona o perfil
                          values.Add(idCampoTabelaAssociativa, idPerfilColaborador); //adiciona perfil de colaborador
                          values.Add("tabela_associativa_added-"+idCampoTabelaAssociativa,idPerfilConcatenadoComVirgula);// perfis concatenados com virgula
                           values.Add("tabela_associativa_removed-"+idCampoTabelaAssociativa,"");//em branco, se fosse pra remover, era só colocar os perfis concatenados com virgula
                          //---------------------------------------
                          
                          
                        }
                      
                        //salva a informação no banco de dados
                        await ApiContext.SaveEntityAsync(idEstruturaFormulario_PESSOA, values);
                        
                    }
                
            }
//opcional para registrar no log de controle
  await ApiContext.LogAsync("Saiu da API", "log_api_xpto");
    
    }
```

##### Aprovando uma etapa através do método ApproveEntityAsync

```C#
public void Execute(){

  //opcional para registrar no log de controle
  await ApiContext.LogAsync("Entrou da API", "log_api_xpto");
  
            //converte o conteúdo enviado no body da API para JSON
            var json = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(content);
      
            //guarda em uma variável o ID da  E S T R U T U R A  do formulário de pessoa
            var idEstruturaFormulario_PESSOA = Guid.Parse("0b56b66a-4f6f-4ded-ad04-016d7c0724e1");
    
    
            if (json != null)
            {
    
                    //verifica se o JSON recebido contém a propriedade "nome", "email" e "cel" que são necessários p cadastro
                    if (JsonHelper.HasProperty(json, "nome") && JsonHelper.HasProperty(json, "email") && JsonHelper.HasProperty(json, "perfil")){
           
                        var values = new DataDictionary();
                        values.Add("nome", json["nome"].ToString());
                        values.Add("email", json["email"].ToString());
                      	values.Add("id", json["id"].ToString());
                      
                        //no caso do campo do formulário ser uma tabela associativa (tabela relacional N:N)
                        var idCampoTabelaAssociativa = "70b6f362-2587-4fd2-a2fb-148bd0caf437";
                        if (json["perfil"].ToString() == "todos_os_perfis" ) {
                          
                          var idPerfilAdmin = "51cf02f1-3787-4dca-8a2c-e219a5ce1298";
                          var idPerfilColaborador = "f999f103-c775-4245-92d3-034cb3ded5e4";                          
                          var idPerfisConcatenadosComVirgula = idPerfilAdmin + "," + idPerfilColaborador + ",";
                          
                          //adiciona os perfis
                          values.Add(idCampoTabelaAssociativa, idPerfilAdmin); //adiciona perfil de admin
                          values.Add(idCampoTabelaAssociativa, idPerfilColaborador); //adiciona perfil de colaborador
                          values.Add("tabela_associativa_added-"+idCampoTabelaAssociativa,idPerfisConcatenadosComVirgula);// perfis concatenados com virgula
                          values.Add("tabela_associativa_removed-"+idCampoTabelaAssociativa,"");//em branco, se fosse pra remover, era só colocar os perfis concatenados com virgula
                          //---------------------------------------

                        }
                        else if (json["perfil"].ToString() == "apenas_colaborador" ) {
                          
                          
                          var idPerfilColaborador = "f999f103-c775-4245-92d3-034cb3ded5e4";                        
                          var idPerfilConcatenadoComVirgula = idPerfilColaborador + ",";
                          
                          //adiciona o perfil
                          values.Add(idCampoTabelaAssociativa, idPerfilColaborador); //adiciona perfil de colaborador
                          values.Add("tabela_associativa_added-"+idCampoTabelaAssociativa,idPerfilConcatenadoComVirgula);// perfis concatenados com virgula
                          values.Add("tabela_associativa_removed-"+idCampoTabelaAssociativa,"");//em branco, se fosse pra remover, era só colocar os perfis concatenados com virgula
                          //---------------------------------------
                          
                          
                        }
                      
                        //salva a informação no banco de dados
                        await ApiContext.ApproveEntityAsync(idEstruturaFormulario_PESSOA, values);
                        
                    }
                
            }
//opcional para registrar no log de controle
    await ApiContext.LogAsync("saiu da API", "log_api_xpto");
    
    }
```

##### Recuperar os valores das "Variáveis de Ambiente"

Para saber mais sobre variáveis de ambiente entre em [Variáveis de ambiente](https://wiki.agilityflow.io/link/88#bkmrk-page-title)

```JavaScript
var valorDaVariavel = ApiContext.GetEnvironmentVariable("var_nomeDaVariavel");
```

Recuperar a Descrição (texto), no caso de variáveis do Tipo "Query com Id + Descrição":

```JavaScript
var textDaVariavel = ApiContext.GetEnvironmentVariable_Text("var_nomeDaVariavel");
```

#### Envio de e-mail

Responsável pelo envio de e-mail

<table border="1" id="bkmrk-op%E3%A7%E3%A3o-retorno-%E2%A0-s" style="border-collapse: collapse; width: 121.652%; height: 303px;"><tbody><tr style="height: 31px;"><td style="width: 70.1206%; height: 31px;">**Método**</td><td style="width: 14.0139%; height: 31px;">**Retorno**</td><td style="width: 35.6186%; height: 31px;"> </td></tr><tr style="height: 31px;"><td style="width: 70.1206%; height: 31px;">**EmailSender.SendToGrupoUsuario**(Guid grupoUsuarioId, string subject, string htmlContent)</td><td style="width: 14.0139%; height: 31px;">void</td><td style="width: 35.6186%; height: 31px;">Enviar um e-mail para um determinado Grupo de Usuario</td></tr><tr><td style="width: 70.1206%;">**EmailSender.SendEmail**(string toEmail, string subject, string htmlContent)</td><td style="width: 14.0139%;">void</td><td style="width: 35.6186%;">Enviar um e-mail </td></tr><tr><td style="width: 70.1206%;">**EmailSender.SendEmail(**string toEmail, string subject, string htmlContent, string ccEmail)</td><td style="width: 14.0139%;">void</td><td style="width: 35.6186%;">Enviar um e-mail, com copia (CC)</td></tr></tbody></table>

##### Enviar e-mail para um Grupo de Usuário

Antes de iniciar, crie um "Grupo de Usuário" no menu "Segurança e Acesso". Depois de criado, associe os usuários que receberão e-mail ao novo grupo de usuário que você acabou de criar.

Pegue o ID desse novo Grupo de usuário. Você vai precisar dele para enviar o e-mail.

```C#
var grupoUsuarioId = Guid.Parse("af7c9275-0e23-4b64-a433-f238bb457005"); //substitua o ID "af7c9275-0e23-4b64-a433-f238bb457005" pelo Id do grupo de usuario que você deseja enviar o e-mail
var assunto = "Novo E-mail para um Grupo de usuario ";

var html = "Olá Grupo, <BR><BR> Teste para envio de e-mail para um Grupo de Usuário no AgilityFlow!";

EmailSender.SendToGrupoUsuario(grupoUsuarioId, assunto, html);
```

##### Enviar e-mail 

```C#
var htmlContent = "<strong>Olá,</strong> teste envio de e-mail.";
var emailTo = "john@email.com";
var subject = "Subject do E-mail";

EmailSender.SendEmail(emailTo, subject, htmlContent);
```

#### Método principal para utilização da Programação em C# na api de post

A única regra é que o método se chame Execute, não tenha parâmetros de entrada e o retorno seja void.

Exemplo:

```C#
public void Execute(){            



  //aqui você pode programar   



}
```

#### Gerenciar as transações de Banco de dados manualmente

Caso você escolha por gerenciar as transactions de banco de dados manualmente, você precisará obrigatoriamente utilizar as 3 funções abaixo:

<p class="callout warning">Atenção: Configuração recomendada apenas para especialista.</p>

1. **ApiContext.DbTransaction\_BeginTransaction()** Para abrir uma transação, antes de iniciar as alterações no banco de dados
2. **ApiContext.DbTransaction\_Commit()** Para finalizar e confirmar com sucesso as alterações no banco de dados
3. **ApiContext.DbTransaction\_Rollback()** Para finalizar e desfazer as alterações no banco de dados

Exemplo de uso:

<p class="callout danger">Atenção: Utilize as transactions sempre dentro de TRY e CATCH</p>

<p class="callout info">Podem ser abertas uma ou mais transações na mesma API. Você ficará responsável por todas as aberturas e encerramentos das transações criadas.</p>

```C#
public async Task RunAsync(){
        
            //converte o conteúdo enviado no body da API para JSON
            var json = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(content);
      
            //guarda em uma variável o ID da  E S T R U T U R A  do formulário de pessoa
            var idEstruturaFormulario_PESSOA = Guid.Parse("0b56b66a-4f6f-4ded-ad04-016d7c0724e1");
    
            try
            {
              
              await ApiContext.DbTransaction_BeginTransactionAsync(); //ABRE A TRANSAÇÃO, DENTRO DO TRY CATCH

              var values = new DataDictionary();
              values.Add("nome", "exemplo1_PRIMEIRA_transacao");
              
              await ApiContext.SaveEntityAsync(idEstruturaFormulario_PESSOA, values); //salva a informação no banco de dados
              
              await ApiContext.DbTransaction_CommitAsync(); //CONFIRMA A TRANSAÇÃO, DENTRO DO TRY CATCH

            }
            catch
            {              
              await ApiContext.DbTransaction_RollbackAsync(); //DESFAZ A TRANSAÇÃO, DENTRO DO CATCH em caso de erro
              throw;
            }
    
  
  			//mais código
  			//...
  			//mais código
  			//...
    		//mais código
  			//...
  			//mais código
  			//...
  
  
  
  
  			try
            {
              
              await ApiContext.DbTransaction_BeginTransactionAsync(); //ABRE A TRANSAÇÃO, DENTRO DO TRY CATCH

              var values2 = new DataDictionary();
              values2.Add("nome", "exemplo2_SEGUNDA_transacao");
              
              await ApiContext.SaveEntityAsync(idEstruturaFormulario_PESSOA, values2); //salva a informação no banco de dados
              
              await ApiContext.DbTransaction_CommitAsync(); //CONFIRMA A TRANSAÇÃO, DENTRO DO TRY CATCH

            }
            catch
            {              
              await ApiContext.DbTransaction_RollbackAsync(); //DESFAZ A TRANSAÇÃO, DENTRO DO CATCH em caso de erro
              throw;
            }
  	
  
    
    }
```