Jarvis.WebPages
2.0.0.2
See the version list below for details.
dotnet add package Jarvis.WebPages --version 2.0.0.2
NuGet\Install-Package Jarvis.WebPages -Version 2.0.0.2
<PackageReference Include="Jarvis.WebPages" Version="2.0.0.2" />
<PackageVersion Include="Jarvis.WebPages" Version="2.0.0.2" />
<PackageReference Include="Jarvis.WebPages" />
paket add Jarvis.WebPages --version 2.0.0.2
#r "nuget: Jarvis.WebPages, 2.0.0.2"
#:package Jarvis.WebPages@2.0.0.2
#addin nuget:?package=Jarvis.WebPages&version=2.0.0.2
#tool nuget:?package=Jarvis.WebPages&version=2.0.0.2
Jarvis.WebPages
Biblioteca de componentes TagHelper para construção de formulários em Razor Pages e MVC.
Instalação
Requer .NET 10.
dotnet add package Jarvis.WebPages
Registre os TagHelpers no _ViewImports.cshtml:
@addTagHelper *, Jarvis.WebPages
Adicione o script de máscaras e formatação no layout:
<script src="/_content/Jarvis.WebPages/js/init.js"></script>
Componentes
Propriedades Comuns (BaseTagHelper)
| Propriedade | Tipo | Descrição |
|---|---|---|
asp-for |
ModelExpression |
Binding com a propriedade do modelo |
asp-readonly |
bool |
Torna o campo somente leitura |
asp-disabled |
bool |
Desabilita o campo |
asp-name |
string |
Sobrescreve o nome do campo |
Todos os componentes geram automaticamente: label, input, texto descritivo (via [Display(Description)]) e mensagem de validação.
FormText
Campo de texto simples.
<form-text asp-for="Nome" asp-col-css="col-md-6" asp-placeholder="Digite o nome" />
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
asp-col-css |
string |
col-md-12 |
Classe CSS da coluna |
asp-input-css |
string |
— | Classe CSS adicional no input |
asp-placeholder |
string |
— | Placeholder do campo |
FormTextArea
Campo de texto multilinha.
<form-text-area asp-for="Observacao" asp-col-css="col-md-12" asp-placeholder="Descreva..." />
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
asp-col-css |
string |
col-md-12 |
Classe CSS da coluna |
asp-input-css |
string |
— | Classe CSS adicional no input |
asp-placeholder |
string |
— | Placeholder do campo |
FormPassword
Campo de senha.
<form-password asp-for="Senha" asp-col-css="col-md-6" />
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
asp-col-css |
string |
col-md-12 |
Classe CSS da coluna |
asp-input-css |
string |
— | Classe CSS adicional no input |
FormDate
Campo de data com suporte a date picker nativo ou input com máscara dd/mm/aaaa.
<form-date asp-for="DataNascimento" asp-col-css="col-md-4" asp-show-picker="false" />
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
asp-input-css |
string |
— | Classe CSS adicional no input |
asp-col-css |
string |
col-md-12 |
Classe CSS da coluna |
asp-max |
DateTime? |
— | Data máxima permitida |
asp-min |
DateTime? |
— | Data mínima permitida |
asp-on-change |
string |
— | Nome da função JS chamada ao alterar a data |
asp-show-picker |
bool |
true |
true = date picker nativo, false = input texto |
Exemplo com asp-on-change
<form-date asp-for="DataInicio"
asp-col-css="col-md-4"
asp-show-picker="true"
asp-on-change="onDataInicioChange" />
<script>
function onDataInicioChange(value) {
// value = "2024-06-15" (formato ISO)
console.log('Data selecionada:', value);
}
</script>
Quando asp-show-picker="true", a função é chamada via onchange do input. Quando asp-show-picker="false", é chamada via data-onchange após o preenchimento completo da data.
FormDateTime
Campo de data e hora (datetime-local).
<form-date-time asp-for="DataHora" asp-col-css="col-md-6" />
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
asp-input-css |
string |
— | Classe CSS adicional no input |
asp-col-css |
string |
col-md-12 |
Classe CSS da coluna |
asp-max |
DateTime? |
— | Data/hora máxima permitida |
asp-min |
DateTime? |
— | Data/hora mínima permitida |
FormSelect
Campo de seleção (dropdown).
<form-select asp-for="CidadeId"
asp-items="Model.Cidades"
asp-value-field="Id"
asp-text-field="Nome"
asp-placeholder="Selecione a cidade"
asp-on-change="onCidadeChange" />
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
asp-input-css |
string |
— | Classe CSS adicional no select |
asp-col-css |
string |
col-md-12 |
Classe CSS da coluna |
asp-items |
IEnumerable |
— | Lista de itens para popular o select |
asp-on-change |
string |
— | Nome da função JS chamada ao alterar o valor |
asp-text-field |
string |
Text |
Nome da propriedade usada como texto |
asp-value-field |
string |
Value |
Nome da propriedade usada como value |
asp-placeholder |
string |
Selecionar... |
Texto da opção vazia |
Exemplo com asp-on-change
<form-select asp-for="EstadoId"
asp-items="Model.Estados"
asp-value-field="Id"
asp-text-field="Nome"
asp-on-change="onEstadoChange" />
<script>
function onEstadoChange(value) {
// value = id do estado selecionado
console.log('Estado selecionado:', value);
// Exemplo: carregar cidades do estado via AJAX
fetch(`/api/cidades?estadoId=${value}`).
then(r => r.json()).
then(cidades => {
// popular outro select de cidades
});
}
</script>
FormNumeric
Campo numérico com formatação automática (dinheiro, percentual, decimal, inteiro).
<form-numeric asp-for="Valor" asp-type="Money" asp-precision="2" asp-col-css="col-md-4" />
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
asp-col-css |
string |
col-md-12 |
Classe CSS da coluna |
asp-input-css |
string |
— | Classe CSS adicional no input |
asp-precision |
int |
2 |
Casas decimais (limitado a 20) |
asp-type |
NumericType |
Decimal |
Tipo de formatação |
asp-allow-negative |
bool |
false |
Permite negativos; o sinal alterna a cada - digitado |
NumericType
| Valor | Formatação |
|---|---|
Money |
R$ 1.234,56 |
Percent |
12,34% |
Decimal |
1.234,56 |
Integer |
1.234 |
O valor digitado é limitado a 15 dígitos, teto a partir do qual o JavaScript perde precisão numérica.
FormMask
Campo com máscara de entrada (aceita apenas números, formatados automaticamente).
<form-mask asp-for="CPF" asp-type="CPF" asp-col-css="col-md-4" />
<form-mask asp-for="Codigo" asp-type="Custom" asp-mask="##.###-##" />
<form-mask asp-for="Quantidade" asp-type="OnlyNumbers" />
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
asp-col-css |
string |
col-md-12 |
Classe CSS da coluna |
asp-input-css |
string |
— | Classe CSS adicional no input |
asp-type |
MaskType |
CPF |
Tipo de máscara |
asp-on-complete |
string |
— | Nome da função JS chamada ao completar a máscara |
asp-mask |
string |
— | Máscara personalizada (usado com Custom) |
MaskType
| Valor | Máscara | Exemplo |
|---|---|---|
CPF |
###.###.###-## |
123.456.789-00 |
CNPJ |
##.###.###/####-## |
12.345.678/0001-90 |
CPF_CNPJ |
Automático por tamanho | CPF ou CNPJ |
CEP |
#####-### |
12345-678 |
PhoneNumber |
(##) #####-#### |
(11) 99876-5432 |
OnlyNumbers |
Sem máscara, só dígitos | 123456 |
Custom |
Definida por asp-mask |
Conforme o pattern |
Exemplo com asp-on-complete
O callback é disparado quando o usuário termina de preencher todos os dígitos da máscara.
<form-mask asp-for="CPF"
asp-type="CPF"
asp-col-css="col-md-4"
asp-on-complete="onCpfComplete" />
<script>
function onCpfComplete(value) {
// value = "123.456.789-00" (com máscara)
console.log('CPF preenchido:', value);
// Exemplo: buscar dados do cliente pelo CPF
const cpf = value.replace(/\D/g, '');
fetch(`/api/clientes?cpf=${cpf}`).
then(r => r.json()).
then(cliente => {
// preencher campos do formulário
});
}
</script>
<form-mask asp-for="CEP"
asp-type="CEP"
asp-col-css="col-md-3"
asp-on-complete="onCepComplete" />
<script>
function onCepComplete(value) {
// value = "12345-678"
const cep = value.replace(/\D/g, '');
fetch(`https://viacep.com.br/ws/${cep}/json/`).
then(r => r.json()).
then(endereco => {
document.querySelector('[name="Logradouro"]').value = endereco.logradouro;
document.querySelector('[name="Bairro"]').value = endereco.bairro;
document.querySelector('[name="Cidade"]').value = endereco.localidade;
});
}
</script>
Máscara Custom
Use # para representar um dígito numérico. Qualquer outro caractere é inserido automaticamente como separador fixo. O asp-on-complete também funciona com máscaras customizadas.
<form-mask asp-for="Protocolo"
asp-type="Custom"
asp-mask="####/####-##"
asp-on-complete="onProtocoloComplete" />
<script>
function onProtocoloComplete(value) {
// value = "2024/0001-01"
console.log('Protocolo preenchido:', value);
}
</script>
Exemplos de patterns:
##.###-## → 12.345-67
####/#### → 2024/0001
###-## → 123-45
####/####-## → 2024/0001-01
Alerts
Componente de alertas Bootstrap que exibe mensagens armazenadas via TempData. Renderiza alertas de info (azul), sucesso (verde), aviso (amarelo) e erro (vermelho).
Na view (layout ou página):
<alerts></alerts>
No PageModel:
// Alerta informativo (azul)
this.Info("Operação realizada.");
// Alerta de sucesso (verde)
this.Success("Registro salvo com sucesso!");
// Alerta de aviso (amarelo)
this.Warning("Atenção: campo opcional não preenchido.");
// Alerta de erro (vermelho)
this.Error("Falha ao salvar o registro.");
return RedirectToPage();
As mensagens são exibidas automaticamente na próxima renderização da página e descartadas após a exibição.
Helpers
is-visible
Controla a visibilidade de qualquer elemento HTML. Quando false, o elemento é completamente removido do output.
<div is-visible="Model.ExibirDetalhes">
Conteúdo visível apenas quando ExibirDetalhes for true.
</div>
<button is-visible="Model.PodeExcluir">Excluir</button>
disabled
Adiciona o atributo disabled a qualquer elemento HTML quando a condição é true.
<button disabled="Model.Processando">Salvar</button>
<input disabled="!Model.PodeEditar" />
ButtonWhatsApp
Botão flutuante de WhatsApp com animação de pulso. Renderiza um ícone fixo no canto inferior direito que abre uma conversa no WhatsApp.
<button-whats-app number="5511999999999" text="Olá, preciso de ajuda!" />
| Propriedade | Tipo | Descrição |
|---|---|---|
number |
string |
Número do WhatsApp com código do país (sem +, espaços ou traços) |
text |
string |
Texto pré-preenchido na mensagem |
Fab
Botão de ação flutuante fixo no canto inferior direito, visível apenas no mobile — fica oculto a partir de 768px. Renderiza um link circular com ícone Font Awesome.
<fab href="/agenda/agendar" icon="fa-plus" label="Agendar compromisso" />
| Propriedade | Tipo | Descrição |
|---|---|---|
href |
string |
URL de destino ao clicar |
icon |
string |
Classe do ícone Font Awesome, renderizado como fa-solid {icon} |
label |
string |
Texto acessível do botão (aria-label) |
Requer Font Awesome carregado na página. A cor de fundo usa a variável CSS --c-primary, com fallback #003299.
Extensions
Métodos de extensão disponíveis para uso no PageModel e HttpContext.
Validação
if (ModelState.NotValid())
{
return Page();
}
Listas para Select
Converte uma GenericList<T> do Jarvis.Toolkit em IEnumerable<SelectListItem>, pronta para o asp-items do FormSelect.
Estados = _service.ListarEstados().ToSelectListItem();
<form-select asp-for="IdEstado" asp-items="Model.Estados" />
IP e Dispositivo do Cliente
var ip = HttpContext.GetIpAddress();
var device = HttpContext.GetDevice();
GetIpAddress normaliza endereços IPv4 recebidos em formato mapeado (::ffff:189.10.20.30) para IPv4 puro. Endereços IPv6 reais são mantidos intactos, então a coluna de IP no banco precisa comportar 45 caracteres.
GetDevice retorna o cabeçalho User-Agent já com Trim(). Devolve string vazia quando o cabeçalho não é enviado.
Atrás de Proxy Reverso
Com IIS/ARR, Docker Swarm ou nginx na frente, GetIpAddress devolve o IP do proxy, não o do cliente. Para obter o IP real, registre o processamento dos cabeçalhos encaminhados:
builder.Services.AddJarvisIpCliente();
var app = builder.Build();
app.UseJarvisIpCliente(); // primeira linha do pipeline, antes de auth e HTTPS redirect
Isso configura X-Forwarded-For e X-Forwarded-Proto com ForwardLimit = 1 (um único proxy na frente). Sem parâmetro, aceita cabeçalhos vindos das faixas privadas 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 e loopback.
Informando os proxies explicitamente, somente esses endereços são aceitos:
builder.Services.AddJarvisIpCliente("192.168.1.50");
Segurança: confiar em faixas inteiras permite que qualquer host daquela rede forje o cabeçalho
X-Forwarded-Fore se passe por outro IP — num cluster Swarm, isso inclui qualquer container. Se o IP for usado para bloqueio, rate limit ou auditoria, passe o endereço do proxy explicitamente.
Notas de infraestrutura:
- O IIS/ARR envia
X-Forwarded-Forpor padrão, mas não oX-Forwarded-Proto— este exige uma regra de rewrite definindo a server variableHTTP_X_FORWARDED_PROTO. Sem ela,UseHttpsRedirectionpode entrar em loop. - No Docker Swarm, o ingress faz SNAT e altera apenas o IP de origem (L3); o cabeçalho
X-Forwarded-Forpassa intacto. Como o gateway do ingress fica em10.0.0.0/8, o modo padrão de publicação funciona. Publicar commode: hostsó é necessário para obter o IP real sem depender de cabeçalho. - Se um dia entrar outro proxy na frente (Cloudflare, nginx), o
ForwardLimitprecisa subir para 2.
Rate Limit
Controle de requisições por política nomeada, particionado por IP do cliente e caminho da requisição.
builder.Services.AddJarvisRateLimit(options =>
{
options.Message = "Muitas tentativas em pouco tempo. Aguarde alguns minutos e tente de novo.";
options.AddPolicy("auth", 5, TimeSpan.FromMinutes(1), HttpMethods.Post);
});
builder.Services.AddRazorPages(options =>
{
options.Conventions.AddJarvisRateLimit("/Login", "auth");
options.Conventions.AddJarvisRateLimit("/RecuperarSenha", "auth");
});
var app = builder.Build();
app.UseJarvisRateLimit(); // depois de UseRouting, antes de MapRazorPages
Aplicando a política a uma pasta inteira:
options.Conventions.AddJarvisRateLimitFolder("/Conta", "auth");
Ou direto no PageModel, sem convenção:
using Microsoft.AspNetCore.RateLimiting;
[EnableRateLimiting("auth")]
public class LoginModel : PageModel
{
public void OnGet() { }
public async Task<IActionResult> OnPostAsync() { }
}
O atributo vale para a página inteira, não por handler — a política é que decide quais métodos HTTP conta. Para liberar uma página dentro de uma pasta limitada, use [DisableRateLimiting].
Com uma política só, dá para registrar direto:
builder.Services.AddJarvisRateLimit("auth", 5, TimeSpan.FromMinutes(1), HttpMethods.Post);
Limitar somente
HttpMethods.Posté o normal em Razor Pages: oGETcontinua exibindo a página e apenas o envio do formulário conta para o limite.
Opções
| Propriedade | Padrão | Descrição |
|---|---|---|
Message |
"Muitas tentativas…" | Mensagem exibida no alerta de erro |
StatusCode |
429 |
Status code da resposta bloqueada |
RedirectOnRejected |
true |
Volta para a página de origem com a mensagem no alerta |
OnRejected |
null |
Substitui a resposta padrão; quando definido, as opções acima deixam de ser aplicadas |
Policies |
vazio | Políticas registradas |
Política
| Propriedade | Padrão | Descrição |
|---|---|---|
Name |
— | Nome usado ao aplicar a política à página |
PermitLimit |
5 |
Requisições permitidas por janela |
Window |
1 min |
Duração da janela |
QueueLimit |
0 |
Requisições que aguardam na fila em vez de serem rejeitadas |
SegmentsPerWindow |
0 |
Acima de 1, troca janela fixa por janela deslizante |
Methods |
null |
Métodos HTTP limitados. Nulo ou vazio limita todos |
IncludePath |
true |
Inclui o caminho na chave — cada página tem sua própria contagem |
IncludeUser |
false |
Inclui o usuário autenticado na chave; anônimos continuam contados por IP |
Configuração detalhada:
builder.Services.AddJarvisRateLimit(options =>
{
options.AddPolicy("conta", policy =>
{
policy.PermitLimit = 20;
policy.Window = TimeSpan.FromMinutes(5);
policy.SegmentsPerWindow = 5; // janela deslizante de minuto em minuto
policy.Methods = [HttpMethods.Post];
policy.IncludeUser = true;
});
});
Resposta bloqueada
- Requisição normal: a mensagem vai para o alerta de erro (TempData) e o usuário volta para a página de origem, onde o componente
<alerts>a exibe. - Requisição AJAX (
X-Requested-With: XMLHttpRequestouAccept: application/json): JSON no formatoModelResponse. - Sem
Referer, emGET, ou comRedirectOnRejected = false: status429com a mensagem em texto puro.
Em todos os casos o cabeçalho Retry-After é enviado, em segundos.
O redirecionamento devolve
302, não429— o status de bloqueio se perde no caminho. Se o cliente depende do429(monitoramento, integração), useRedirectOnRejected = falseou umOnRejectedpróprio.
Contagem em memória: o limite vale por instância da aplicação. Com várias réplicas (Docker Swarm, web farm), o limite efetivo é multiplicado pelo número de réplicas. Para limite compartilhado, use um limitador distribuído (Redis).
A chave de partição usa
GetIpAddress(). Atrás de proxy reverso,UseJarvisIpCliente()precisa vir antes no pipeline — sem isso todas as requisições caem na mesma partição, a do IP do proxy.
Autenticação
// Login
await HttpContext.LoginAsync(user);
// Logout
await HttpContext.LogoutAsync();
// Atualizar uma claim
await HttpContext.UpdateClaimAsync("Role", "Admin");
// Atualizar múltiplas claims
await HttpContext.UpdateClaimsAsync(
new JarvisClaim("Role", "Admin"),
new JarvisClaim("Name", "João")
);
// Reemitir o cookie a partir de uma identidade já montada
await HttpContext.RefreshLoginAsync(identity);
| Método | Descrição |
|---|---|
LoginAsync |
Cria a identidade a partir de JarvisAuthenticationUser e autentica |
LogoutAsync |
Encerra a sessão de autenticação |
RefreshLoginAsync |
Reemite o cookie a partir de um ClaimsIdentity existente |
UpdateClaimAsync |
Substitui uma claim e reemite o cookie |
UpdateClaimsAsync |
Substitui várias claims e reemite o cookie |
UpdateClaimAsync e UpdateClaimsAsync reemitem o cookie de autenticação — o usuário permanece logado, mas HttpContext.User na requisição atual continua com os valores antigos. A mudança só aparece na próxima requisição.
Todos emitem o cookie com
IsPersistent = true, ou seja, a sessão sobrevive ao fechamento do navegador. Não há opção de sessão temporária.
Sessão
// Armazenar string
HttpContext.SetSession("Token", "abc123");
// Armazenar objeto (serializado automaticamente)
HttpContext.SetSession("Carrinho", carrinho);
// Recuperar string
var token = HttpContext.GetSession("Token");
// Recuperar objeto (deserializado automaticamente)
var carrinho = HttpContext.GetSession<Carrinho>("Carrinho");
// Remover
HttpContext.DeleteSession("Token");
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Jarvis.Toolkit (>= 1.2.2.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.1 | 45 | 9/17/2026 |
| 2.0.0.9 | 81 | 9/13/2026 |
| 2.0.0.8 | 110 | 8/19/2026 |
| 2.0.0.7 | 101 | 8/19/2026 |
| 2.0.0.6 | 105 | 8/17/2026 |
| 2.0.0.5 | 109 | 8/16/2026 |
| 2.0.0.4 | 106 | 8/16/2026 |
| 2.0.0.3 | 101 | 8/15/2026 |
| 2.0.0.2 | 97 | 8/10/2026 |
| 2.0.0.1 | 112 | 8/2/2026 |
| 2.0.0 | 113 | 8/1/2026 |
| 1.0.1.6 | 119 | 5/19/2026 |
| 1.0.1.5 | 141 | 2/1/2026 |
| 1.0.1.4 | 127 | 1/28/2026 |
| 1.0.1.3 | 224 | 11/28/2025 |
| 1.0.1.2 | 328 | 11/13/2025 |
| 1.0.1.1 | 234 | 10/1/2025 |
| 1.0.1 | 167 | 7/11/2025 |
| 1.0.0.9 | 349 | 3/26/2025 |
| 1.0.0.8 | 189 | 2/13/2025 |