هذه حزمة مصممة لإضافة أساليب مساعدة من جانب الخادم لـ HttpRequest
و HttpResponse
. وهذا يجعل العمل مع مفاهيم جانب خادم htmx أكثر بساطة. يجب عليك أيضًا أن تفكر في القراءة عن Hyperscript، وهو مشروع مصاحب اختياري لـ HTMX.
إذا كنت جديدًا في استخدام HTMX، فاطلع على هذه السلسلة حول بدء استخدام HTMX لمطور ASP.NET Core والذي يتضمن أيضًا نموذجًا للمشروع والأنماط التي قد تجدها مفيدة.
قم بتثبيت حزمة Htmx
NuGet على مشروع ASP.NET Core الخاص بك.
dotnet add package Htmx
باستخدام HttpRequest
، يمكننا تحديد ما إذا كان الطلب قد بدأ بواسطة Htmx على العميل.
httpContext . Request . IsHtmx ( )
يمكن استخدام هذا إما لإرجاع استجابة كاملة للصفحة أو عرض جزئي للصفحة.
// in a Razor Page
return Request . IsHtmx ( )
? Partial ( " _Form " , this )
: Page ( ) ;
يمكننا أيضًا استرداد قيم الرؤوس الأخرى التي قد يحددها htmx.
Request . IsHtmx ( out var values ) ;
اقرأ المزيد حول قيم الرؤوس الأخرى على صفحة الوثائق الرسمية.
كملاحظة خاصة، يرجى الانتباه إلى أنه إذا كان الخادم الخاص بك يمكنه عرض محتوى مختلف لنفس عنوان URL اعتمادًا على بعض الرؤوس الأخرى، فستحتاج إلى استخدام رأس HTTP للاستجابة Vary. على سبيل المثال، إذا كان الخادم الخاص بك يعرض HTML الكامل عندما يكون Request.IsHtmx() خطأ، ويعرض جزءًا من HTML عندما يكون Request.IsHtmx() صحيحًا، فستحتاج إلى إضافة Vary: HX-Request. يؤدي ذلك إلى إنشاء مفتاح لذاكرة التخزين المؤقت استنادًا إلى مركب من عنوان URL للاستجابة ورأس طلب HX-Request - بدلاً من الاعتماد فقط على عنوان URL للاستجابة.
// in a Razor Page
if ( Request . IsHtmx ( ) )
{
Response . Headers . Add ( " Vary " , " HX-Request " ) ;
return Partial ( " _Form " , this )
}
return Page ( ) ;
يمكننا تعيين رؤوس استجابة Http باستخدام طريقة ملحق Htmx
، والتي تمرر إجراءً وكائن HtmxResponseHeaders
.
Response . Htmx ( h => {
h . PushUrl ( " /new-url " )
. WithTrigger ( " cool " )
} ) ;
اقرأ المزيد حول رؤوس استجابة HTTP على موقع التوثيق الرسمي.
يمكنك تشغيل الأحداث الجانبية للعميل باستخدام HTMX باستخدام رأس HX-Trigger
. يوفر Htmx.Net طريقة مساعد WithTrigger
لتكوين حدث واحد أو أكثر ترغب في تشغيله.
Response . Htmx ( h => {
h . WithTrigger ( " yes " )
. WithTrigger ( " cool " , timing : HtmxTriggerTiming . AfterSettle )
. WithTrigger ( " neat " , new { valueForFrontEnd = 42 , status = " Done! " } , timing : HtmxTriggerTiming . AfterSwap ) ;
} ) ;
افتراضيًا، سيتم حظر كافة طلبات واستجابات Htmx في سياق عبر الأصل.
إذا قمت بتكوين التطبيق الخاص بك في سياق متعدد الأصل، فإن تعيين سياسة CORS في ASP.NET Core يسمح لك أيضًا بتحديد قيود محددة على رؤوس الطلب والاستجابة، مما يتيح التحكم الدقيق في البيانات التي يمكن تبادلها بين الويب الخاص بك التطبيق وأصول مختلفة.
توفر هذه المكتبة طريقة بسيطة لكشف رؤوس Htmx لسياسة 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
} ) ;
} ) ;
قم بتثبيت حزمة Htmx.TagHelpers
NuGet على مشروع ASP.NET Core الخاص بك. يستهدف مشاريع .NET Core 3.1+.
dotnet add package Htmx.TagHelpers
اجعل مساعدي العلامات متاحين في مشروعك عن طريق إضافة السطر التالي إلى _ViewImports.cshtml
الخاص بك:
@addTagHelper *, Htmx.TagHelpers
ستحتاج عمومًا إلى مسارات URL تشير إلى الواجهة الخلفية لـ ASP.NET Core. لحسن الحظ، يحاكي Htmx.TagHelpers
إنشاء عناوين url المضمنة في ASP.NET Core. وهذا يجعل ربط HTMX بتطبيق ASP.NET Core الخاص بك تجربة سلسة.
< 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 >
يتم تضمين مساعد إضافي لعلامة htmx-config
يمكن تطبيقه على عنصر meta
في head
صفحتك مما يجعل إنشاء تكوين HTMX أكثر بساطة. على سبيل المثال، يمكننا أدناه تعيين historyCacheSize
، و indicatorClass
الافتراضي، وما إذا كان سيتم تضمين رموز مكافحة التزوير الخاصة بـ ASP.NET Core كعنصر إضافي في تكوين HTMLX.
<!DOCTYPE html >
< html lang =" en " >
< head >
< meta name =" htmx-config "
historyCacheSize =" 20 "
indicatorClass =" htmx-indicator "
includeAspNetAntiforgeryToken =" true "
/>
<!-- additional elements... -->
</ head >
سيكون HTML الناتج.
<!DOCTYPE html >
< html lang =" en " >
< head >
< meta name =" htmx-config " content =' {"indicatorClass":"htmx-indicator","historyCacheSize":20,"antiForgery":{"formFieldName":"__RequestVerificationToken","headerName":"RequestVerificationToken","requestToken":"<token>"}} ' />
<!-- additional elements... -->
</ head >
يمكنك تعيين السمة includeAspNetAntiforgerToken
على عنصر htmx-config
. ستحتاج بعد ذلك إلى تضمين JavaScript الإضافي في تطبيق الويب الخاص بك. نقوم بتضمين السمة __htmx_antiforgery
لتتبع مستمع الحدث الذي تمت إضافته بالفعل. وهذا يمنعنا من إعادة تسجيل مستمع الحدث عن طريق الخطأ.
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 ;
}
يمكنك الوصول إلى المقتطف بطريقتين. الأول هو استخدام فئة HtmxSnippet
الثابتة في طرق العرض الخاصة بك.
<script>
@Html.Raw(HtmxSnippets.AntiforgeryJavaScript)
</script>
الطريقة الأسهل هي استخدام فئة HtmlExtensions
التي تمتد إلى IHtmlHelper
.
@Html.HtmxAntiforgeryScript()
سينتج عن مساعد HTML هذا علامة <script>
بالإضافة إلى JavaScript المذكورة سابقًا. ملاحظة: لا يزال بإمكانك تسجيل معالجات أحداث متعددة لـ htmx:configRequest
، لذا لا بأس بوجود أكثر من معالج واحد.
لاحظ أنه إذا كانت السمة hx-[get|post|put]
موجودة على علامة <form ..>
وكان العنصر <form>
يحتوي على سمة method="post"
(وكذلك action=""
فارغ أو مفقود)، ستضيف ASP.NET Tag Helpers رمز مكافحة التزوير كعنصر input
ولا تحتاج إلى مزيد من تكوين طلباتك على النحو الوارد أعلاه. يمكنك أيضًا استخدام hx-include
للإشارة إلى نموذج، ولكن كل هذا يعود إلى مسألة التفضيل.
بالإضافة إلى ذلك، فإن الطريقة الموصى بها هي استخدام HtmxAntiforgeryScriptEndpoint
، والذي سيتيح لك تعيين ملف JavaScript إلى نقطة نهاية محددة، وسيكون _htmx/antiforgery.js
افتراضيًا.
app . UseAuthorization ( ) ;
// registered here
app . MapHtmxAntiforgeryScript ( ) ;
app . MapRazorPages ( ) ;
app . MapControllers ( ) ;
يمكنك الآن تكوين نقطة النهاية هذه بالتخزين المؤقت والمصادقة وما إلى ذلك. والأهم من ذلك، أنه يمكنك استخدام البرنامج النصي في علامة head
الآن عن طريق تطبيق علامة defer
، والتي تُفضل وجود JavaScript في نهاية عنصر 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 >
<!-- this uses the static value in a script tag -->
< script src =" @HtmxAntiforgeryScriptEndpoints.Path " defer > </ script >
</ head >
حقوق النشر © 2022 خالد أبوحكمة
يُمنح الإذن مجانًا لأي شخص يحصل على نسخة من هذا البرنامج وملفات الوثائق المرتبطة به ("البرنامج") للتعامل في البرنامج دون قيود، بما في ذلك، على سبيل المثال لا الحصر، حقوق الاستخدام والنسخ والتعديل والدمج. ونشر و/أو توزيع وترخيص من الباطن و/أو بيع نسخ من البرنامج، والسماح للأشخاص الذين تم توفير البرنامج لهم بالقيام بذلك، وفقًا للشروط التالية:
يجب تضمين إشعار حقوق الطبع والنشر أعلاه وإشعار الإذن هذا في جميع النسخ أو الأجزاء الكبيرة من البرنامج.
يتم توفير البرنامج "كما هو"، دون أي ضمان من أي نوع، صريحًا أو ضمنيًا، بما في ذلك، على سبيل المثال لا الحصر، ضمانات القابلية للتسويق والملاءمة لغرض معين وعدم الانتهاك. لا يتحمل المؤلفون أو أصحاب حقوق الطبع والنشر بأي حال من الأحوال المسؤولية عن أي مطالبة أو أضرار أو مسؤولية أخرى، سواء في إجراء العقد أو الضرر أو غير ذلك، الناشئة عن أو خارج أو فيما يتعلق بالبرنامج أو الاستخدام أو المعاملات الأخرى في برمجة.