Este é um pacote projetado para adicionar métodos auxiliares do lado do servidor para HttpRequest
e HttpResponse
. Isso simplifica o trabalho com conceitos do lado do servidor htmx. Você também deve considerar ler sobre o Hyperscript, um projeto complementar opcional para HTML.
Se você é novo no HTMX, confira esta série sobre introdução ao HTMX para desenvolvedor ASP.NET Core, que também inclui um projeto de amostra e padrões que podem ser úteis.
Instale o pacote Htmx
NuGet em seu projeto ASP.NET Core.
dotnet add package Htmx
Usando HttpRequest
, podemos determinar se a solicitação foi iniciada por Htmx no cliente.
httpContext . Request . IsHtmx ( )
Isso pode ser usado para retornar uma resposta de página completa ou uma renderização parcial da página.
// in a Razor Page
return Request . IsHtmx ( )
? Partial ( " _Form " , this )
: Page ( ) ;
Também podemos recuperar os outros valores de cabeçalho que o htmx pode definir.
Request . IsHtmx ( out var values ) ;
Leia mais sobre os outros valores de cabeçalho na página de documentação oficial.
Como observação especial, lembre-se de que se o seu servidor puder renderizar conteúdo diferente para o mesmo URL dependendo de outros cabeçalhos, você precisará usar o cabeçalho HTTP de resposta Vary. Por exemplo, se o seu servidor renderizar o HTML completo quando Request.IsHtmx() for falso, e renderizar um fragmento desse HTML quando Request.IsHtmx() for verdadeiro, você precisará adicionar Vary: HX-Request. Isso faz com que o cache seja codificado com base em uma combinação do URL de resposta e do cabeçalho da solicitação HX-Request – em vez de ser baseado apenas no URL de resposta.
// in a Razor Page
if ( Request . IsHtmx ( ) )
{
Response . Headers . Add ( " Vary " , " HX-Request " ) ;
return Partial ( " _Form " , this )
}
return Page ( ) ;
Podemos definir cabeçalhos de resposta Http usando o método de extensão Htmx
, que passa uma ação e o objeto HtmxResponseHeaders
.
Response . Htmx ( h => {
h . PushUrl ( " /new-url " )
. WithTrigger ( " cool " )
} ) ;
Leia mais sobre os cabeçalhos de resposta HTTP no site de documentação oficial.
Você pode acionar eventos do lado do cliente com HTMX usando o cabeçalho HX-Trigger
. Htmx.Net fornece um método auxiliar WithTrigger
para configurar um ou mais eventos que você deseja acionar.
Response . Htmx ( h => {
h . WithTrigger ( " yes " )
. WithTrigger ( " cool " , timing : HtmxTriggerTiming . AfterSettle )
. WithTrigger ( " neat " , new { valueForFrontEnd = 42 , status = " Done! " } , timing : HtmxTriggerTiming . AfterSwap ) ;
} ) ;
Por padrão, todas as solicitações e respostas Htmx serão bloqueadas em um contexto de origem cruzada.
Se você configurar seu aplicativo em um contexto de origem cruzada, definir uma política CORS no ASP.NET Core também permitirá definir restrições específicas em cabeçalhos de solicitação e resposta, permitindo um controle refinado sobre os dados que podem ser trocados entre seu servidor web. aplicação e diferentes origens.
Esta biblioteca fornece uma abordagem simples para expor cabeçalhos Htmx à sua política CORS:
var MyAllowSpecificOrigins = " _myAllowSpecificOrigins " ;
var builder = WebApplication . CreateBuilder ( args ) ;
builder . Services . AddCors ( options =>
{
options . AddPolicy ( name : MyAllowSpecificOrigins ,
policy =>
{
policy . WithOrigins ( " http://example.com " , " http://www.contoso.com " )
. WithHeaders ( HtmxRequestHeaders . Keys . All ) // Add htmx request headers
. WithExposedHeaders ( HtmxResponseHeaders . Keys . All ) // Add htmx response headers
} ) ;
} ) ;
Instale o pacote Htmx.TagHelpers
NuGet em seu projeto ASP.NET Core. Destina-se a projetos .NET Core 3.1+.
dotnet add package Htmx.TagHelpers
Disponibilize os Tag Helpers em seu projeto adicionando a seguinte linha ao seu _ViewImports.cshtml
:
@addTagHelper *, Htmx.TagHelpers
Geralmente, você precisará de caminhos de URL apontando para o back-end do ASP.NET Core. Felizmente, Htmx.TagHelpers
imita a geração de URL incluída no ASP.NET Core. Isso torna a vinculação do HTMX ao seu aplicativo ASP.NET Core uma experiência perfeita.
< div hx-target =" this " > < button hx-get hx-page =" Index " hx-page-handler =" Snippet " hx-swap =" outerHtml " > Click Me (Razor Page w/ Handler) button > div > < div hx-target =" this " > < button hx-get hx-controller =" Home " hx-action =" Index " hx-route-id =" 1 " > Click Me (Controller) button > div > < div hx-target =" this " > < button hx-post hx-route =" named " > Click Me (Named) button > div >
Está incluído um auxiliar de tag htmx-config
adicional que pode ser aplicado a um meta
no head
da sua página que simplifica a criação da configuração HTMX. Por exemplo, abaixo podemos definir o historyCacheSize
, indicatorClass
padrão e se devemos incluir os tokens antifalsificação do ASP.NET Core como um elemento adicional na configuração HTMX.
>
< html lang =" en " >
< head >
< meta name =" htmx-config "
historyCacheSize =" 20 "
indicatorClass =" htmx-indicator "
includeAspNetAntiforgeryToken =" true "
/>
head >
O HTML resultante será.
>
< html lang =" en " >
< head >
< meta name =" htmx-config " content =' {"indicatorClass":"htmx-indicator","historyCacheSize":20,"antiForgery":{"formFieldName":"__RequestVerificationToken","headerName":"RequestVerificationToken","requestToken":""}} ' />
head >
Você pode definir o atributo includeAspNetAntiforgerToken
no elemento htmx-config
. Então você precisará incluir esse JavaScript adicional em seu aplicativo web. Incluímos o atributo __htmx_antiforgery
para rastrear se o ouvinte de evento já foi adicionado. Isso nos impede de registrar novamente acidentalmente o ouvinte de evento.
if ( ! document . body . attributes . __htmx_antiforgery ) {
document . addEventListener ( "htmx:configRequest" , evt => {
let httpVerb = evt . detail . verb . toUpperCase ( ) ;
if ( httpVerb === 'GET' ) return ;
let antiForgery = htmx . config . antiForgery ;
if ( antiForgery ) {
// already specified on form, short circuit
if ( evt . detail . parameters [ antiForgery . formFieldName ] )
return ;
if ( antiForgery . headerName ) {
evt . detail . headers [ antiForgery . headerName ]
= antiForgery . requestToken ;
} else {
evt . detail . parameters [ antiForgery . formFieldName ]
= antiForgery . requestToken ;
}
}
} ) ;
document . addEventListener ( "htmx:afterOnLoad" , evt => {
if ( evt . detail . boosted ) {
const parser = new DOMParser ( ) ;
const html = parser . parseFromString ( evt . detail . xhr . responseText , 'text/html' ) ;
const selector = 'meta[name=htmx-config]' ;
const config = html . querySelector ( selector ) ;
if ( config ) {
const current = document . querySelector ( selector ) ;
// only change the anti-forgery token
const key = 'antiForgery' ;
htmx . config [ key ] = JSON . parse ( config . attributes [ 'content' ] . value ) [ key ] ;
// update DOM, probably not necessary, but for sanity's sake
current . replaceWith ( config ) ;
}
}
} ) ;
document . body . attributes . __htmx_antiforgery = true ;
}
Você pode acessar o snippet de duas maneiras. A primeira é usar a classe estática HtmxSnippet
em suas visualizações.
Uma maneira mais simples é usar a classe HtmlExtensions
que estende IHtmlHelper
.
@Html.HtmxAntiforgeryScript()
Este auxiliar HTML resultará em uma tag junto com o JavaScript mencionado anteriormente. Nota: Você ainda pode registrar vários manipuladores de eventos para
htmx:configRequest
, portanto, ter mais de um está ok.
Observe que se o atributo hx-[get|post|put]
estiver em uma tag e o elemento
tiver um atributo
method="post"
(e também um atributo action=""
vazio ou ausente), os auxiliares de tags do ASP.NET adicionarão o token antifalsificação como um elemento input
e você não precisará configurar ainda mais suas solicitações como acima. Você também pode usar hx-include
apontando para um formulário, mas tudo isso se resume a uma questão de preferência.
Além disso, a abordagem recomendada é usar HtmxAntiforgeryScriptEndpoint
, que permitirá mapear o arquivo JavaScript para um endpoint específico e, por padrão, será _htmx/antiforgery.js
.
app . UseAuthorization ( ) ;
// registered here
app . MapHtmxAntiforgeryScript ( ) ;
app . MapRazorPages ( ) ;
app . MapControllers ( ) ;
Agora você pode configurar este endpoint com cache, autenticação, etc. Mais importante ainda, você pode usar o script em sua tag head
agora aplicando a tag defer
, que é preferível a ter JavaScript no final de um elemento body
.
< head > < meta charset =" utf-8 "/> < meta name =" viewport " content =" width=device-width, initial-scale=1.0 "/> < meta name =" htmx-config " historyCacheSize =" 20 " indicatorClass =" htmx-indicator " includeAspNetAntiforgeryToken =" true "/> < title > @ViewData["Title"] - Htmx.Sample title > < link rel =" stylesheet " href =" ~/lib/bootstrap/dist/css/bootstrap.min.css "/> < link rel =" stylesheet " href =" ~/css/site.css " asp-append-version =" true "/> < script src =" ~/lib/jquery/dist/jquery.min.js " defer > script > < script src =" ~/lib/bootstrap/dist/js/bootstrap.bundle.min.js " defer > script > < script src =" https://unpkg.com/htmx.org@@1.9.2 " defer > script > < script src =" @HtmxAntiforgeryScriptEndpoints.Path " defer > script > head >
Direitos autorais © 2022 Khalid Abuhakmeh
É concedida permissão, gratuitamente, a qualquer pessoa que obtenha uma cópia deste software e dos arquivos de documentação associados (o “Software”), para negociar o Software sem restrições, incluindo, sem limitação, os direitos de usar, copiar, modificar, mesclar , publicar, distribuir, sublicenciar e/ou vender cópias do Software e permitir que as pessoas a quem o Software seja fornecido o façam, sujeito às seguintes condições:
O aviso de direitos autorais acima e este aviso de permissão serão incluídos em todas as cópias ou partes substanciais do Software.
O SOFTWARE É FORNECIDO “COMO ESTÁ”, SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM DETERMINADO FIM E NÃO VIOLAÇÃO. EM HIPÓTESE ALGUMA OS AUTORES OU DETENTORES DE DIREITOS AUTORAIS SERÃO RESPONSÁVEIS POR QUALQUER RECLAMAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM UMA AÇÃO DE CONTRATO, ATO ILÍCITO OU DE OUTRA FORMA, DECORRENTE DE, OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTRAS NEGOCIAÇÕES NO SOFTWARE.