ASP.NET QRCode
Gerar um QRCode no ASP.NET é uma tarefa simples e rápida quando usamos o pacote certo. Neste artigo, vamos criar uma classe reutilizável que transforma qualquer URL em imagem e devolve essa imagem a partir de um controlador MVC.
Ao final, você terá uma rota que responde com o QRCode pronto e saberá exibi-lo em qualquer página HTML.
Versão em vídeo
Se você prefere acompanhar o passo a passo em vídeo, o conteúdo completo está logo abaixo.
O que é um QRCode
O QRCode é um código de barras bidimensional, formado por pequenos quadrados pretos e brancos chamados módulos. Diferente do código de barras tradicional, ele armazena informação nos dois eixos da imagem.
Por isso, um único QRCode guarda uma URL, um texto, um contato ou os dados de uma rede WiFi. A câmera do celular lê esse conteúdo em segundos, sem nenhum aplicativo extra na maioria dos aparelhos.
Níveis de correção de erro
Todo QRCode carrega dados redundantes para continuar legível mesmo quando parte da imagem está danificada. Essa redundância segue quatro níveis de correção de erro.
| Nível | Capacidade aproximada de recuperação |
|---|---|
| L | Cerca de 7% das palavras de código |
| M | Cerca de 15% das palavras de código |
| Q | Cerca de 25% das palavras de código |
| H | Cerca de 30% das palavras de código |
Quanto maior o nível, mais robusto o código fica. Em contrapartida, a imagem ganha mais módulos e fica mais densa.
Como o QRCode guarda os dados
Além dos módulos de dados, todo QRCode possui três quadrados maiores nos cantos, chamados padrões de localização. Eles ajudam a câmera a identificar a posição e a rotação do código.
O tamanho do código também varia conforme a quantidade de informação. Assim, uma URL curta gera um QRCode pequeno, enquanto um texto longo gera uma grade bem mais densa.
Essa relação explica por que encurtar o conteúdo melhora a leitura. Quanto menos dados, maiores ficam os módulos na mesma área impressa.
Por que gerar QRCode no ASP.NET
Muitas aplicações web precisam de QRCodes dinâmicos. Por exemplo, ingressos de eventos, links de pagamento, autenticação em dois fatores e cardápios digitais.
Nesses casos, gerar o QRCode no ASP.NET evita depender de serviços externos. Além disso, você mantém o controle total sobre os dados que entram na imagem.
Outro ponto importante é a privacidade. Quando o servidor gera o QRCode no ASP.NET, a URL ou o token nunca saem da sua infraestrutura.
QRCoder, a biblioteca para gerar QRCode no ASP.NET
Para facilitar nosso trabalho, vamos utilizar um pacote chamado QRCoder. Trata-se de um projeto open source, disponível no GitHub e via NuGet, sob a licença MIT.
Segundo a página oficial do QRCoder no NuGet, o pacote oferece vários renderizadores. Entre eles estão QRCode, PngByteQRCode, SvgQRCode, Base64QRCode e AsciiQRCode.
Além disso, o QRCoder traz geradores de payload para casos comuns. Assim, você monta QRCodes de WiFi, vCard, eventos de calendário e pagamentos sem formatar as strings à mão.
Criando o projeto
Vamos começar criando um projeto ASP.NET MVC e adicionando o pacote do QRCoder.
dotnet new mvc -o MyApp
cd MyApp
dotnet add package QRCoder
Pronto, temos nosso projeto criado com o pacote necessário para começarmos. O template mvc já traz controladores, views e o roteamento configurado.
Organizando o projeto
A ideia aqui é criar uma classe que permita reutilizar o QRCode em diferentes pontos do nosso App. Dessa forma, controladores, serviços e jobs chamam o mesmo código.
Essa separação também facilita testes, porque a lógica do QRCode no ASP.NET fica isolada do pipeline HTTP.
O pacote em si já faz muita coisa. No entanto, prefiro separar a parte de gerar imagens para um reuso ainda maior.
Gerando o QRCode
O trecho para gerar um QRCode utilizando o QRCoder é bem simples. Precisamos do QRCodeGenerator e dos dados do QRCode.
var qrGenerator = new QRCodeGenerator();
// cria os dados do QRCode com nível de correção Q (cerca de 25%)
var qrCodeData = qrGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
var qrCode = new QRCode(qrCodeData);
// 10 pixels por módulo
var qrCodeImage = qrCode.GetGraphic(10);
return qrCodeImage;
O método CreateQrCode recebe o conteúdo e o nível de correção de erro. Em seguida, o renderizador QRCode desenha a imagem com o método GetGraphic.
O número passado ao GetGraphic define quantos pixels cada módulo ocupa. Então, valores maiores geram imagens maiores e mais nítidas.
Retornando um Bitmap
Para ficar ainda melhor, vamos separar esse código em um método que já retorna um Bitmap. Isso vai nos ajudar em todo o processo.
public static Bitmap GenerateImage(string url)
{
var qrGenerator = new QRCodeGenerator();
var qrCodeData = qrGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
var qrCode = new QRCode(qrCodeData);
var qrCodeImage = qrCode.GetGraphic(10);
return qrCodeImage;
}
O Bitmap pertence ao namespace System.Drawing. Por enquanto, guarde essa informação, porque ela faz diferença nas versões mais novas do .NET.
Convertendo a imagem em bytes
Em alguns pontos, também precisei dos bytes da imagem em vez do Bitmap. Por isso, decidi criar dois métodos adicionais.
O primeiro retorna os bytes a partir de uma URL. Já o segundo converte qualquer imagem em um array de bytes no formato PNG.
public static byte[] GenerateByteArray(string url)
{
var image = GenerateImage(url);
return ImageToByte(image);
}
private static byte[] ImageToByte(Image img)
{
using var stream = new MemoryStream();
// salva a imagem em memória no formato PNG
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
return stream.ToArray();
}
O MemoryStream funciona como um arquivo temporário em memória. Assim, não precisamos gravar nada em disco para obter os bytes.
A classe completa para QRCode no ASP.NET
Como resultado final, nossa classe ficou com os seguintes métodos.
public static class QrCodeGenerator
{
public static Bitmap GenerateImage(string url)
{
var qrGenerator = new QRCodeGenerator();
var qrCodeData = qrGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
var qrCode = new QRCode(qrCodeData);
var qrCodeImage = qrCode.GetGraphic(10);
return qrCodeImage;
}
public static byte[] GenerateByteArray(string url)
{
var image = GenerateImage(url);
return ImageToByte(image);
}
private static byte[] ImageToByte(Image img)
{
using var stream = new MemoryStream();
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
return stream.ToArray();
}
}
A classe é estática, porque não guarda estado. Portanto, qualquer parte da aplicação gera um QRCode no ASP.NET com uma única chamada.
Utilizando o QRCode no ASP.NET em um controlador
Agora, tudo que temos a fazer é chamar nosso gerador em algum método do controlador.
var image = QrCodeGenerator.GenerateByteArray("https://balta.io");
Com a imagem gerada, podemos responder com um FileResult, passando os bytes da imagem e o MIME type.
[HttpGet("qrcode")]
public IActionResult GetQrCode()
{
var image = QrCodeGenerator.GenerateByteArray("https://balta.io");
return File(image, "image/png");
}
O método File do controlador devolve um FileContentResult com status 200. De acordo com a documentação do ControllerBase.File, o segundo parâmetro vira o cabeçalho Content-Type da resposta.
Dessa forma, ao executar nossa aplicação, o QRCode aparece na URL abaixo.
https://localhost:5001/qrcode
Ajustando o MIME type
Na versão original deste exemplo, a action respondia com image/jpeg. Contudo, o método ImageToByte salva a imagem em PNG, então o tipo correto é image/png.
Na prática, a maioria dos navegadores exibe a imagem mesmo com o tipo trocado. Ainda assim, informar o MIME type correto evita problemas com caches, proxies e ferramentas que validam o conteúdo.
Utilizando no HTML
Para renderizar o QRCode na tela, basta utilizar a tag img com a URL anterior.
<img src="https://localhost:5001/qrcode" alt="QRCode com o link do balta.io" />
Em uma view Razor, você também pode usar uma URL relativa, como /qrcode. Assim, o mesmo HTML funciona em desenvolvimento e em produção.
Gerando o QRCode a partir de um parâmetro
O exemplo usa uma URL fixa, mas o mesmo gerador aceita qualquer texto. Então, você pode receber o conteúdo pela rota ou pela query string.
[HttpGet("qrcode/order/{id:int}")]
public IActionResult GetOrderQrCode(int id)
{
// monta a URL do pedido e gera o QRCode correspondente
var url = $"https://example.com/orders/{id}";
var image = QrCodeGenerator.GenerateByteArray(url);
return File(image, "image/png");
}
Nesse caso, cada pedido ganha o próprio QRCode no ASP.NET, gerado sob demanda. Contudo, valide sempre o que chega do usuário antes de transformar em imagem.
Testando o QRCode no ASP.NET
Com a action pronta, execute a aplicação com o comando abaixo.
dotnet watch run
O dotnet watch recompila o projeto sempre que você salva um arquivo e mantém o QRCode no ASP.NET sempre atualizado. Assim, qualquer ajuste no tamanho ou no nível de correção aparece no navegador logo em seguida.
Conferindo a resposta pelo terminal
Além do navegador, vale conferir os cabeçalhos da resposta. Para isso, use o curl com a opção -I, que exibe apenas os cabeçalhos.
curl -I -k https://localhost:5001/qrcode
A resposta deve trazer o status 200 e o cabeçalho Content-Type: image/png. Já a opção -k ignora o certificado de desenvolvimento, que não é confiável para o curl em alguns sistemas.
Lendo o código com o celular
Por fim, aponte a câmera do celular para a imagem na tela. O aparelho deve reconhecer o link do balta.io e oferecer a opção de abrir a página.
Se a leitura do QRCode no ASP.NET falhar, aumente o valor passado ao GetGraphic. Em telas pequenas, módulos maiores facilitam bastante o trabalho da câmera.
QRCode no ASP.NET com .NET 6 ou superior
O renderizador QRCode usa o System.Drawing.Common por baixo dos panos. Porém, a partir do .NET 6, a Microsoft passou a tratar esse pacote como uma biblioteca exclusiva do Windows.
Segundo a nota de breaking change do .NET 6, o analisador de plataforma emite avisos de compilação fora do Windows. Além disso, a execução lança uma TypeInitializationException em Linux e macOS.
No .NET 6 ainda existia a chave System.Drawing.EnableUnixSupport para contornar o problema. No entanto, o .NET 7 removeu essa chave de vez.
A própria Microsoft cita os geradores de QRCode como um dos usos mais comuns do System.Drawing.Common fora do Windows. Ou seja, quem hospeda o QRCode no ASP.NET em containers Linux precisa de uma alternativa.
Alternativa multiplataforma com PngByteQRCode
O QRCoder oferece o renderizador PngByteQRCode, que gera os bytes do PNG sem depender do System.Drawing. Com isso, o mesmo código roda em Windows, Linux e macOS.
public static class QrCodeGenerator
{
public static byte[] GenerateByteArray(string url)
{
var qrGenerator = new QRCodeGenerator();
var qrCodeData = qrGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
// gera o PNG direto em bytes, sem System.Drawing
var qrCode = new PngByteQRCode(qrCodeData);
return qrCode.GetGraphic(10);
}
}
Repare que a assinatura pública do método GenerateByteArray continua igual. Portanto, o controlador não precisa de nenhuma alteração.
Se você realmente precisa do Bitmap, mantenha a versão original apenas em aplicações que rodam no Windows. Para todo o resto, prefira trabalhar com bytes.
Gerando QRCode de WiFi com payloads
Os geradores de payload do QRCoder formatam o texto no padrão que os celulares reconhecem. Por exemplo, o código abaixo cria um QRCode que conecta o aparelho a uma rede WiFi.
// monta o texto no formato esperado pelos leitores de QRCode
var payload = new PayloadGenerator.WiFi("MyNetwork", "MyPassword", PayloadGenerator.WiFi.Authentication.WPA);
var image = QrCodeGenerator.GenerateByteArray(payload.ToString());
Como o nosso gerador recebe uma string, ele aceita esse payload sem nenhuma mudança. Da mesma forma, você pode montar vCards e eventos de calendário.
Outros formatos de QRCode no ASP.NET
O PNG atende a maioria dos cenários, mas não é o único formato possível. Por isso, o QRCoder oferece outros renderizadores para necessidades específicas.
QRCode no ASP.NET em SVG
O renderizador SvgQRCode devolve uma string com o conteúdo SVG. Como o SVG é vetorial, a imagem escala para qualquer tamanho sem perder nitidez.
public static string GenerateSvg(string url)
{
var qrGenerator = new QRCodeGenerator();
var qrCodeData = qrGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
var qrCode = new SvgQRCode(qrCodeData);
// retorna o markup SVG como texto
return qrCode.GetGraphic(10);
}
No controlador, basta devolver essa string com o tipo image/svg+xml, como no exemplo a seguir.
[HttpGet("qrcode.svg")]
public IActionResult GetSvgQrCode()
{
var svg = QrCodeGenerator.GenerateSvg("https://balta.io");
return Content(svg, "image/svg+xml");
}
O método Content devolve texto com o tipo informado. Assim, o navegador renderiza o SVG como qualquer outra imagem, inclusive dentro da tag img.
Dessa maneira, o formato funciona muito bem em materiais impressos e em telas de alta densidade. Além disso, o arquivo SVG costuma ser leve, porque descreve apenas retângulos simples.
QRCode embutido na página
Às vezes, você não quer uma rota separada só para a imagem. Nesse caso, converta os bytes do PNG em Base64 e monte uma data URI direto na view.
var bytes = QrCodeGenerator.GenerateByteArray("https://balta.io");
// monta a data URI para usar no atributo src da tag img
var dataUri = $"data:image/png;base64,{Convert.ToBase64String(bytes)}";
Com isso, a página carrega o QRCode no ASP.NET junto com o HTML, sem uma segunda requisição. Por outro lado, o Base64 aumenta o tamanho dos dados em cerca de um terço, então use essa técnica com moderação.
Boas práticas ao gerar QRCode no ASP.NET
Alguns cuidados deixam a geração de QRCode no ASP.NET mais segura e eficiente em produção.
- Escolha o nível de correção conforme o uso: Q ou H para materiais impressos, L ou M para telas.
- Use um valor de pixels por módulo que gere imagens nítidas sem exagerar no tamanho.
- Armazene em cache os QRCodes que não mudam, porque gerar a imagem consome CPU.
- Valide e limite o tamanho do conteúdo recebido, já que textos longos geram códigos muito densos.
- Prefira o
PngByteQRCodequando a aplicação roda em containers Linux.
Também vale registrar logs quando a geração falhar, para identificar conteúdos inválidos rapidamente.
Imagens PNG já chegam compactadas ao navegador. Por isso, a compressão de respostas do ASP.NET traz pouco ganho para essa rota, e o cache costuma ser a melhor otimização.
Se você trabalha com o modelo mais novo de hospedagem, a mesma classe também funciona em Minimal APIs. Basta retornar os bytes com Results.File no lugar do File do controlador.
Conclusão
Pronto! Temos um gerador de QRCode com ASP.NET, separado em uma classe reutilizável e exposto por uma action simples.
Em resumo, o QRCoder cuida da codificação, a nossa classe cuida da imagem e o controlador devolve os bytes. Para rodar o QRCode no ASP.NET fora do Windows, troque o renderizador QRCode pelo PngByteQRCode e mantenha o restante do código.
FAQ
O QRCoder é gratuito?
Sim, o QRCoder é open source e usa a licença MIT. Você pode usar o pacote em projetos comerciais.
Qual nível de correção de erro devo usar?
O nível Q, usado no exemplo, recupera cerca de 25% dos dados e funciona bem na maioria dos casos. Para materiais impressos sujeitos a desgaste, prefira o nível H.
Por que meu QRCode falha no Linux?
O renderizador QRCode depende do System.Drawing.Common, que só funciona no Windows a partir do .NET 6. Use o PngByteQRCode para rodar em Linux e macOS.
Qual MIME type devo usar na resposta?
Use image/png, porque o exemplo salva os bytes no formato PNG. Assim, o cabeçalho Content-Type corresponde ao conteúdo real.
Posso gerar QRCode em SVG?
Sim, o QRCoder possui o renderizador SvgQRCode. O SVG é útil quando a imagem precisa escalar sem perder qualidade.