Escolha uma Página
Integrando o MailingBoss a uma aplicação ASP.NET Core MVC com o Visual Studio 2017

Integrando o MailingBoss a uma aplicação ASP.NET Core MVC com o Visual Studio 2017

Neste artigo veremos como é possível cadastrar um usuário no seu database e, ao mesmo tempo, inserir esse usuário numa lista do MailingBoss, onde é possível automatizar uma sequência de ações de marketing via E-mails. Ou seja, você põe um “robô” digital para interagir com seus leads até conseguir efetuar uma venda… ou o que você imaginar.

O problema

Usando o MailingBoss, que é a ferramenta de e-mail marketing da BuilderAll, é possível trabalhar com Funis de Venda, capturando Leads para uma determinada lista. O fantástico dessa ferramenta é que ela permite montar WORKFLOWS com ações a serem tomadas DEPOIS que o lead se inscreve na lista. Tipicamente essas ações são envios de novos e-mails, contendo conteúdos diferentes e levando o lead a tomar uma decisão de compra. Esses e-mais são programáveis no tempo. E mais: se a pessoa clicar no link de um e-mail, o WORKFLOW permite transferir o lead de uma lista original – onde o e-mail entrou pela primeira vez – para qualquer outra lista (retirando-o, se você quiser, da lista original).

Essencialmente, toda lista é associada a um único formulário que tem em geral poucos campos. O mínimo que pode ter é o campo de e-mail, que é obrigatório. O típico pede um nome e o e-mail. O problema: assim que a pessoa submete o formulário, clicando no botão de submit, é muito complicado passar esses dados para uma outra aplicação e – até o momento em que escrevo este post – o jeito que eles recomendam fazer isso não funcionou e é ainda impraticável passar dados “hidden”, embora isso seja teoricamente possível.  

A solução

Bem, se Maomé não vai à montanha, a montanha vai a Maomé. O jeito que encontrei é cadastrar o lead na minha própria aplicação CORE MVC, num formulário simples que simplesmente injeta o LEAD no database da minha aplicação. Ao completar essa operação, eu emulo um submit para o MailingBoss, como se os dados tivessem saído de um formulário deles – e não da minha aplicação. Assim que o MailingBoss “engole” os dados, ele mesmo dispara e-mail pedindo confirmação de e-mail (se a lista é double opt in) ou um e-mail de confirmação do cadastramento.

Funciona. Se você quiser fazer um teste, pode se inscrever para ter 7 dias de acesso gratuíto ao MailingBoss e mais 17 ferramentas de marketing digital – além de diversos treinamentos sobre tudo quanto é assunto para fazer marketing na WEB.

 

A aplicação em ASP.NET CORE MVC

A ideia é ter uma aplicação muito simples que permitirá fazer um cadastro de pessoas interessadas em fazer um teste, na WEB, sem custos, do seu grau de empreendedorismo.

Assim que a pessoa se cadastra, a aplicação manda um e-mail para o e-mail cadastrado, solicitando a CONFIRMAÇÃO (da veracidade) do mesmo. PAra não complicar a programação do aplicativo, vamos deixar por conta do MailingBoss o envio do e-mail pedindo a Confirmação.

Assim que a pessoa cadastrada clica no link desse e-mail de confirmação, ocorrem duas coisas:

  • Ela é remetida para uma página tipo parabéns, está tudo certo, ‘clique no link abaixo para fazer o teste‘;
  • O sistema muda o status do cadastrado para confirmado;
  • O MailingBoss envia um e-mail de agradecimento.

Modelo de Dados

Crie uma classe de dados no diretório model, tendo como chave o e-mail (para evitar e-mails duplicados).

MODEL->Empreendedor.cs

Gerando a tabela no banco de dados – Contexto

Uma vez que seu modelo já está gravado com Empreendedor.cs, você precisa precisa acrescentar essa tabela na lista de tabelas – que no meu caso está no arquivo ContextoPrimario.cs, dentro da pasta models. Se você não tem ainda na aplicação nenhuma especificação de contexto, crie uma ContextoPrimario.cs na pasta de models e insira o seguinte conteúdo

Se você já tem seu arquivo de Contexto, por ter criado o banco de dados anteriormente (ou por estar aproveitando uma solução de teste criada anteriormente, e somente quer ter a tabela do modelo empreendedor lá dentro), simplesmente acrescente à relação de arquivos já existentes a seguinte linha (dentro de public partial class ContextoPrimario : DbContext:):

public virtual DbSet<Empreendedor> Empreendedores { get; set; } // banco de Empreendedores

Feito isso, vá no menu superior e rode BUILD->BUILD SOLUTION. Tem que dar zero erros, se não der acerte o que estiver errado, até rodar e dar zero erros.

Feito isso, precisamos agora gerar o arquivo que vai de fato implementar a tabela de EMpreendedores na sua aplicação. Na janela do Package Manager Console, embaixo, temos de adicionar essa primeira migração. Digite, trocando [nomedamigracao] por qualquer nome, como PrimeiraMigracao:

//PM> Add-Migration [nomedamigracao] -Context ContextoPrimario:

Add-Migration [nomedamigracao] -Context ContextoPrimario 

Se rodar certinho, ele vai gerar um arquivo com um númerogrande_nomedasuamigracao. No meu caso, 20190131213948_Empreendedor3

Agora temos de rodar a Migração, gerando a tabela de Empreendedores no seu banco de dados.Novamente na janela de Package Management Console (PM, embaixo), rode o seguinte comando (troque ContextoPrimario pelo nome do seu contexto, se tiver um outro):

update-database -context ContextoPrimario

Entre no seu gerenciador de banco de dados, você vai ver que a tabela está lá. No meu caso, como uso SQL, entro no MIcrosoft SQL Server Management Studio (MSSMS). Coloco a tabela no modo de edição e vejo o seguinte:

tabela empreendedores

tabela empreendedores

Nada é perfeito, suspirou a raposa. Na migração a tabela foi criada mas, a despeito de ter definido no modelo valores default para idConsultoria (4), flagEmailConfirmado (0) e quantidadeDeAvaliadores (0), estes valores não estão no Binding da tabela, quando todos os campos estão definidos como “não permitindo nulos”. Isso significa que, se deixar assim, vou ter de especificar todos esses valores no meu form, como hidden. Até aí tudo bem. Ocorre que algumas vezes uso procedures e gosto de ter a certeza que se eu não enviar algum desses campos, eles vão assumir valores padrão.

Assim, ajusto o o DEFAULT VALUE OR BINDING para os valores padrão que quero e salvo a tabela (que ainda está vazia).

Gerando o Controller as as Views, com Scaffolding

Agora precisamos criar o controlador (controller) e os formulários (views). Clicks sobre o nome do seu projeto e com o botão da direita escolha ADD-> NEW SCAFFOLDED ITEM. Escolha o template MVC COntroller with Views, using Entity Framework. Click em ADD.

Em Model Class, escolha Empreendedor. Em Data Context Class, escolha  ContextoPrimario (ou o nome do seu contexto). Deixe clicado: Generate Views, Reference Script Libraries e Use a lay-out page. Em Controller name, mude o nome de EmpreendedorsController para EmpreendedoresController. Click em ADD.

Legal. Vamos fazer um check básico. No menu superior clique em IIS EXpress. Sua aplicação vai ter um endereço básico de entrada, definido em startup;cs. No meu caso é http://localhost:50628/.

No NAVEGADOR, altere para o seu endereço localhost + Empreendedores/Create.

No meu caso fica assim: http://localhost:50628/Empreendedores/Create

Que chato, Fernandinho. O formulário fica pedindo coisas que não deveriam e.se tento gravar, dá um monte de erros, E, pior que tudo, não tem o e-mail que considero chave:

 

 

 

 

É necessário que os campos idConsultoria, quantidadeDeAvaliadores e flagEmailConfirmado fiquem em hidden e com valores pré determinados. Além disso:

  • vou mudar a cor do botão para vermelho usando “btn-danger” no lugar de “btn-default”;
  • tirar o link “Back to List”;
  • No títutlo, colocar um texto promocional com a classe “jumbotron” do bootstrap (que é usado na minha aplicação);
  • acrescentar o campo de e-mail que, por ser chave, o CORE assumiu que não precisaria ter porque seria gerado automaticamente – o que não é o nosso caso.

 

Rodando a aplicação no localhost, nossa telinha de entrada fica assim:

Fazendo um cadastramento o sistema manda para a página Index ferada pelo Core MVC:

tela index Empreendedor

Ou conferindo na base de dadosse está tudo OK:

 

Agora vamos criar um espelho dessa tabela no MailingBoss. Se você não tem uma conta na BuilderAll, crie uma conta de 7 dias grátis.

Entre no MailingBoss Autoresponder->Acessar MailingBoss e preencha os dados em CRIAR NOVA LISTA DE CONTATOS. Dê o nome à lista de EMPREENDEDOR DIGITAL. No topo, clique em LISTAS e clique na engrenagem da Lista de Empreendedor Digital Abra o seletor LINKS RÁPIDOS e escolha a opção VER CAMPOS CUSTOMIZADOS.

Aqui vamos inserir os campos que nos interessam, todos como texto, além do e-mail: senha, nome, idconsultoria e telefone (que chamei de whatsap):

campos mailingboss

Não esqueça de salvar. Depois selecione em LINKS RÁPIDOS -> formulários de interação. Copie todo contéudo numa janela de texto, para podermos retirar dela as informações que nos interessam para o controlador do core mvc,

 

Podemos ver que a lista esta vazia:

Precisamos alterar o controlador para além de submeter ao database, também “”emular” o submit para o MailingBoss.

Vejamos o código original do POST do CREATE do CORE MVC:

Acrescente ao controlador:

using System.Net.Http;
using System.Net.Http.Headers;

e altere seu código post conforme abaixo. Não se esqueça de incluir a rotina privada para inserir os pares de valores do form e de trocar – no post – o código para o código de sua lista que você guardou no arquivo texto (no meu caso, o código zw93898d6db44 (que é o “cpf” da lista).

Testando a aplicação

No formulário original aparecia o campo MBOSSLASTCLICKS, que não documentado em lugar algum. Simplesmente pedi sua inserção com valor 1:

new KeyValuePair<string, string>(“MBOSSLASTCLICKS”,”1″)

cadastro 2

Solicitei o cadastramento com email alcides2@mailinator.com.

O email entrou:

Listando os contatos do MailingBoss, cuja lista estava vazia:

cadastro não confirmado 1

Observe que ele entrou como não confirmado, o que significa que a aplicação funcionou direitinho, emulando o post para o MailingBoss. Vendo os detalhes do contato:

cadastro não confirmado 2

Olhando no Mailinator. vemos que foi remetido um e-mail de confirmação:

cadastro não confirmado 2

Abrindo e e-mail e clicando no link de confirmação:

cadastro não confirmado 2

A confirmação leva para uma tela de confirmação no MailingBoss. Não é o que queremos, mas vamos refinar isso mais adiante:

tela de confirmação mailingboss

Voltando aos contatos do MailingBoss, vemos que agora o e-mail está com status confirmado.

cadastro mailingboss confirmado

No MailingBoss você pode ajeitar o e-mail de confirmação de inscrição, colocando sua arca e acertado oo texto. No meu caso:

email de confirmação da inscrição

Se o usuário clicar no link, vai cair na página de inscrição confirmada do MailingBoss. Como eu quero que ele caiana minha aplicação, tenho de configurar isso clicando no AVANÇADO.

Página de inscrição confirmada

Aí eu defino para onde quero remeter o usuário na minha aplicação e o tempo que isso demora. Deixei com zero segundos.

avançado da página de inscrição

Não esqueça de clicar em Salvar e próximo. Volto para a aplicação e registro um novo e-mail (alcides3@mailinator.com), vou nos e-mails recebidos (mailinator.com) e clico no link de confirmação. Imediatamente vai para a MINHA tela de confirmação:

minha tela de confirmação

Agora é embelezar a tela e mudar o FlagEmailConfirmado na minha aplicação, alterando o valor de 0 para 1. Outra coisa a fazer, uma vez que sei que o e-mail é quente, é inserir o usuário na aplicação de testes, para que ele possa fazer o teste prometido usando os mesmos dados com que se cadastrou na minha lista,

Nova tela de Detalhes

nova tela de detalhes

Observe que já passo os parâmetros no link para evitar que o usuário tenha de redigitar o que acabou de cadastrar. O que é bem chato especialmente em celular,

 

Acertando o Controlador

Assim que o usuário vê a tela de detalhes o controlador atualiza o flag de confirmação e chama uma procedure para inserir a pessoa confirmada no sistema de Avaliação e cria uma autoavaliação para ela preencher.

Esta é uma ISCA DIGITAL gratuíta e dá para o interessado, sem custos, sua autoavaliação como empreendedor. Ela poderá ver os resultados em tela, na forma gráfica e em tabelas.

Se ela gostar e quiser que outras pessoas a avaliem (amigos, parentes, pessoal de networking, etc), ela poderá comprar avaliações adicionais por um preço módico. Este seria um UP SELL . Se o resultado dela for muito bom, já na autoavaliação, no MailingBoss, vou colocá-la num FUNIL para ela juntar-se à CAMPANHA DE UM MILHÃO DE EMPREENDEDORES 

 

Ajustes Finais

Quando o usuário se cadastra, o sistema está ainda mandando o usuário para a página Index, que dá a relação de todos os cadastrado Não é isso que queremos: precisamos remetê-lo a uma página dizendo “Que legal, estamos quase lá, Por favor confirme sua inscrição clicando no link recebido por e-mail (veja se não caiu no SPAM”. Assim, o controlador no final do POST do create tem de redirecionar não para Index, e sim para uma pagina diferente. Vamos nos basear na própria página de details.cshtml, criando uma chamada details_confirma_email.cshtml.

Logo após cadastrar um novo e-mail (alcides6@mailinator.com) , aparece a tela do “estamos quase lá”.

TELA ESTAMOS QUASE LÁ

O e-mail foi enviado para o Mailinator.comO EMAIL FOI ENVIADO PARA O MAILINATOR.COM

Depois de clicar no link de confirmação do E-mail, a tela para pré-acessar o teste.

tela tudo pronto

Clicando no botão “Vai para o teste”, a tela já é pré-preenchida

tela tudo pronto

Clicando em entrar a pessoa já pode responder o questionário (no caso sobre seu grau de empreendedorismo).

tela interna do sistema

Todos e-mails ficaram registrados no MailingBoss e com status confirmados.

tela com relação de emails no mailingboss

Obrigado pela sua leitura. Continue visitando este blog e compartilhe artigos em sua rede de relacionamento. Por favor, se quiser, registre sugestões e comentários ao final da página.

Junte-se à nossa rede de Empreendedores Builderall.

turbine seus negócios online com mais de 20 aplicativos Builderall

Usando SQL Storage Procedures no CORE MVC – Parte 1

Usando SQL Storage Procedures no CORE MVC – Parte 1

Um dos problemas complicados no Core MVC é que não dá para usar as Views do SQL. Quando você tem de mostrar dados que tem diversas tabelas agrupadas, há algumas formas de contornar isso, usando procedures do SQL.

Se você vai operar com procedures, antes de tudo instale pelo Gerenciador do NuGet – se ainda não o tem instalado na sua aplicação, o Microsoft.AspNetCore.Identity.EntityFrameworkCore.

No arquivo do controlador que tiver actions com SQL, em alguns casos poderá será preciso acrescentar a diretiva using System.Data.SqlClient;.

Casos do método FromSql

Para executar procedures, use o método FromSql executa consultas RAW SQL. Mas existem algumas limitações para executar consultas RAW SQL ou procedures.

  • As consultas SQL só podem ser usadas para retornar tipos de entidades que fazem já parte do seu modelo. Portanto, não podem conter dados relacionados ou “montados” através de procedures. Existe uma forma de contornar isso, mas ninguém explica direito. Você deve montar um modelo “fake”, falso mesmo. Que não existe fisicamente no banco de dados. Depois de montar o modelo tem que fazer duas coisas:
    • incluir esse modelo “fake” no seu arquivo SuaAplicacaoContext.cs, dentro do diretório de modelos (Models);
    • o modelo tem que ter uma chave única (uniq key). No arquivo do modelo “fake” a chave da tabela combinada da procedure tem que ser precedida pelo comando [Key] (e para isso é preciso acrescentar a diretiva, no topo do arquivo de modelo, using System.ComponentModel.DataAnnotations). Aí, mesmo sem ser um arquivo físico ,a procedure ser comportará como se assim o fosse;
  • A consulta SQL sempre deve retornar dados para todas as propriedades da entidade. Então, basicamente, sua consulta SQL sempre vai ser algo como “Select * from {NomeDaTabela}” (sempre de uma única tabela dentre as que já estão mapeadas ou o da tabela “fake”).
    É até possível filtrar a tabela, usando parâmetros que funcionarão como uma cláusula “where”. Porém a procedure sempre irá retornar todos os campos da tabela (simples ou “fake”), retornando listas (claro que a procedure poderá trabalhar com outras tabelas, fazendo outras operações, mas o método FromSql sempre retornará uma lista do tipo “select * from Tabela” ou,em alguns casos, um valor único como “Select Count(*) from Tabela“. Você é quem decide: se o resultado é uma lista, injeta num .ToList(). Se o resultado é único, injeta num .SingleOrDefault();
  • Os nomes das colunas no conjunto de resultados sempre devem corresponder exatamente aos nomes das colunas às quais as propriedades são mapeadas (no modelo, ou Model, do contrário vai dar erro e s colunas que não batem virão com valores nulos).

Não há sentido em se usar o FromSql se não houver necessidade de filtrar a tabela com parâmetros ou necessidade de fazer operações acessórias dentro da procedure (atualizando outras tabelas). A procedure abaixo é praticamente inútil, no sentido de que poderia ser facilmente obtida sem nenhuma procedure:

CREATE PROCEDURE lista_todas_consultorias
AS
BEGIN
	SET NOCOUNT ON;
	SELECT * from consultorias
END
GO

Ela teria que usar, no controller, algo do tipo:

List<Consultorias> ListaDeConsultorias = _context.Consultorias.FromSql("lista_todas_consultorias").ToList();

Mas isso poderia ser obtido de várias outras formas, pois a tabela Consultorias já é mapeada, sendo possível obter a lista como no como por exemplo:

var ListagemDeConsultorias = await _context.Consultorias.ToListAsync();

Procedures simples com parâmetros usando FromSql

Já quando você que utilizar uma tabela já mapeada usando filtros (passando parâmetros), começa a fazer sentido usar o FromSql. Por exemplo, selecionar pessoas que estão ligadas a uma determinada Consultoria (considerando que as pessoas estão numa tabela já mapeada):

CREATE PROCEDURE seleciona_pessoas_duma_consultoria 
	@idConsultoria int
AS
BEGIN
	SET NOCOUNT ON;
	SELECT *  FROM dbo.ac_redepessoas
WHERE        (idConsultoria = @idConsultoria)
END
GO

Mesmo este uso, considerando que a tabela de pessoas já é mapeada e que contém o campo IdConsultoria, é bobinho. A instrução FromSql seria:

int idConsultoria = 1;
List<AcRedepessoas> ListagemDePessoasDaConsultoria = _context.AcRedepessoas.FromSql("seleciona_pessoas_duma_consultoria @p0", idConsultoria).ToList;

Mas isso também seria facilmente obtido diretamente no Core:

ListagemDePessoasDaConsultoria =  _context.AcRedepessoas.Where(x => x.IdConsultoria == idConsultoria).ToList();

Então, o uso de FromSql deve ocorrer em situações onde o Core MVC não pode, automaticamente, atualizar alguma tabela secundária ou fazer operações intermediárias. Também não se presta para operações do tipo Insert, Update e Delete.

Passando mais de um parâmetro

Algumas vezes você precisa passar mais de um parâmetro. O FromSql() tem um “overload”que aceita os parâmetros do objeto []. A primeira coisa a notar é o nome do parâmetro é “@p0”. Se houver mais parâmetros, incremente o contador como @p1, @p2 etc… O código seguinte mostra como passar vários parâmetros:

var ListagemDeConsultorias = await _context.Consultorias.ToListAsync();
int idConsultoria = 1;
var NomesDePessoas = "Roberto";
var ListagemDePessoasDaConsultoria = _context.AcRedepessoas
    .FromSql("ListaPessoasPorConsultoriaENome @p0, @p1",
    parameters: new[] { idConsultoria.ToString(), NomesDePessoas })
    .ToList();

Um cuidado: ao passar números inteiros, converta para string antes (se não vai dar erro no SQL). Existe também outra maneira de passar os parâmetros. Substitua @p0 por {0} (e se tiver mais parâmetros, @p1 por {1} e assim por diante.

int idConsultoria = 1;
var parametroConsultoria = new SqlParameter("@idDaConsultoria", idConsultoria);
List<acRedepessoas> ListaDePessoas = _context.acRedePessoas
            .FromSql("proc_lista_pessoas @idDaConsultoria", parametroConsultoria)
            .ToList();

Nesse formato, não é preciso antes converter o inteiro em “string“. Para passar 4 parâmetros, por exemplo:

var userType = _context.acRedepessoas.FromSql("dbo.AlgumaProcedure @Id = {0}, @Nome = {1}", 45, "Ada");

Para casos mais complexos, é preciso usar ExecuteSqlComand

Quando se trata de alterar um arquivo com procedure, este é comando que executa a procedure: ExecuteSqlComand, adequado para operações do tipo Insert, Update e Delete.

O que quase lugar nenhum explica é o seguinte: o comando ExecuteSqlComand não retorna listas. Retorna um inteiro. 0, se a operação foi bem sucedida. É só isso. Novamente: não há sentido em se usar esse comando a menos que você esteja atualizando outras tabelas intermediárias ou fazendo cálculos complexos antes de alterar ou inserir em registro.

A procedure a seguir insere um registro na tabela de Consultorias Categorias.

CREATE PROCEDURE usp_InsereConsultoria
 @NomeDaConsultoria nvarchar(300)
AS
BEGIN
    SET NOCOUNT ON;
    Insert into Consultorias Values (@NomeDaConsultoria)
END
GO

ExecuteSqlCommand deve ser usado em context.Database (na minha aplicação de exemplo _context = contexto;). Você pode usá-lo da seguinte maneira.

var NomeConsultoria= "José Consultores e Associados";
_context.Database
           .ExecuteSqlCommand("usp_InsereConsultoria @p0", NomeConsultoria);

É possível rodar o ExecuteSqlCommand no modo assíncrono também, como por exemplo:

await _context.Database.ExecuteSqlCommandAsync("usp_CriaConsultoria @p0, @p1", 
        parameters: new[] { "Nome Completo da Consultoria", "Nome de Guerra" });

Outro exemplo, usando diretamente dados de um modelo (model) diretamente na chamada da procedure. Após salvar os dados em edição, a procedure executa diversas tarefas de atualização em outras tabelas – e por isso é chamada logo após o “save”:

_context.Update(avaliacoesRespostas);
            await _context.SaveChangesAsync();
            await _context.Database.ExecuteSqlCommandAsync("atualiza_nota @p0, @p1",
        parameters: new[] { avaliacoesRespostas.Nota, avaliacoesRespostas.IdRespostaAvaliacao });
            return RedirectToAction("RespondeFormulario", "Avaliacoes", new { id = avaliacoesRespostas.IdAvaliacao });

Obrigado pela sua leitura. Continue visitando este blog e compartilhe artigos em sua rede de relacionamento. Por favor, se quiser, registre sugestões e comentários ao final da página.

Junte-se à nossa rede de Empreendedores Builderall.

turbine seus negócios online com mais de 20 aplicativos Builderall