การสร้างแอป Blazor และบูรณาการเข้ากับโซลูชัน .NET เป็นเรื่องง่าย ขอบคุณ BlazorWebView แม้ว่าจะเป็นของเก่าอย่าง Windows Forms หรือ WPFก็ตาม
น่าเสียดายที่ชีวิตไม่ใช่ฟาร์มม้า สิ่งนี้มีผลโดยเฉพาะกับซอฟต์แวร์ของบริษัทที่เติบโตขึ้นตามกาลเวลา แอปพลิเคชัน Windows Forms ที่ใช้ .NET Framework แบบคลาสสิกนั้นมีข้อเสียน้อยที่สุด เพราะนอกเหนือจากนั้น ทุกอย่างตั้งแต่ VB6, MFC ไปจนถึง Delphi ก็รวมอยู่ด้วย
แต่เกมยังไม่จบสำหรับแอป Blazor ของคุณ! ต้องขอบคุณมาตรฐาน COM ที่ทำให้แอป Blazor สามารถฝังลงในแอปพลิเคชันที่ดื้อรั้นที่สุดได้ในฐานะตัวควบคุม ActiveX
คำกล่าวอ้างที่กล้าหาญ! จากนั้นคุณก็สามารถปลูกฝังแอปพลิเคชัน Blazor บนเดสก์ท็อปใน Excel ได้ทันที มันควรจะทำงานอย่างไร? เพียงแค่ดู!
ActiveX ตายแล้ว! ActiveX อายุยืนยาว!
ActiveX เป็นเทคโนโลยีการพัฒนาซอฟต์แวร์ที่ช่วยให้ส่วนประกอบต่างๆ โดยเฉพาะอินเทอร์เฟซแบบกราฟิก ถูกสร้างขึ้นในภาษาการเขียนโปรแกรมใดก็ได้ จากนั้นจึงฝังลงในแอปพลิเคชันเป้าหมาย
สิ่งนี้เคยเป็นที่โกรธเคืองโดยเฉพาะใน Internet Explorer ด้วยเหตุนี้ แอปพลิเคชันใดๆ จึงสามารถปรับปรุงฟังก์ชันการทำงานของหน้าเว็บได้ ท้ายที่สุดแล้ว ในช่วงปลายทศวรรษ 1990 การลากและวาง เครื่องเล่นสื่อ HTML5, WebAssembly หรือ Google Maps ไม่ใช่เรื่องไกลตัวที่จะนึกถึง ต้องขอบคุณเว็บเบราว์เซอร์สมัยใหม่และมาตรฐานเว็บ คุณสามารถทำได้โดยไม่ต้องใช้มันในปัจจุบัน — ยังไงซะมันก็ทำงานบน Windows เท่านั้น
แอปพลิเคชัน ActiveX ที่พร้อมใช้งานอีกตัวหนึ่งในการพัฒนาซอฟต์แวร์คือตัวควบคุม ActiveX จากนั้นพวกเขาก็ตัดสินใจเลือกแอปพลิเคชัน สภาพแวดล้อมการพัฒนา และแพลตฟอร์มการเขียนโปรแกรมทุกประเภทตามที่ต้องการ:
- Delphi — แม้ว่าบริษัทจะอดอยากมาหลายครั้ง แต่แพลตฟอร์มการพัฒนาก็ยังดำเนินไปด้วยดี
- Visual Studio พร้อม Windows Forms และ WPF — คุณยังคงสามารถสร้างตัวควบคุม ActiveX (คอมโพเนนต์ COM) ลงใน Windows Forms และ WPF ได้
- Visual Basic 6 — คุณจะไม่เชื่อหรอก แต่ VB6 ยังคงทำงานบน Windows 10 และ Windows 11
- 🎺และ… กลองม้วน 🥁… นอกจากนี้ใน VBA ใน Excel ก็เช่นกัน
และถ้าคุณป้วนเปี้ยนมากไปก็จะไม่มีอะไรทำให้คุณตกใจอีกต่อไป และต้องขอบคุณมาตรฐาน COM ที่ประสบความสำเร็จซึ่งใช้ ActiveX เป็นหลัก มันจะคงอยู่อย่างนั้นต่อไปอีกระยะหนึ่ง
COM — เทคโนโลยีเพื่อความเป็นนิรันดร์
ActiveX มีความยืดหยุ่น (ส่วนใหญ่อยู่ภายใต้ Windows) ตามมาตรฐาน COM เป็นหลัก COM ย่อมาจาก Component Object Model นี่คือเทคโนโลยีอินเทอร์เฟซในการเข้าถึง DLL (ไบนารี) ใดๆ จากกระบวนการ (ไคลเอ็นต์ COM) ผ่านทางการจัดระบบ — เช่น สภาพแวดล้อมรันไทม์ CLR ของ .NET — และเพื่อใช้คลาส วิธีการ คุณสมบัติ และเหตุการณ์ต่างๆ DLL ดังกล่าวเรียกอีกอย่างว่าเซิร์ฟเวอร์ที่อยู่ระหว่างดำเนินการในศัพท์แสง COM และนั่นคือสิ่งที่เราต้องการสร้างสำหรับแอปพลิเคชัน Blazor ของเรา และเราไม่ได้อยู่คนเดียว
เนื่องจากผลิตภัณฑ์ซอฟต์แวร์ทั้งหมดนำเสนอบริการผ่านอินเทอร์เฟซ COM:
- Visual Studio เองก็ใช้โค้ดการทำงานร่วมกันของ COM จำนวนมากภายใต้ประทุน
- โปรโตคอลการสื่อสารแบบเก่าที่ดี OPC (การสื่อสารแพลตฟอร์มแบบเปิด) นั้นใช้ COM/DCOM — IoT มีอยู่ในอุตสาหกรรมมาเป็นเวลานาน
- การใช้งานทางอุตสาหกรรม เช่น WinCC, KEPServerEX หรือ Zenon SCADA
- WebView2 ของ Microsoft นำเสนอฟังก์ชันผ่านอินเทอร์เฟซ COM — ช่างใจกว้างจริงๆ นักพัฒนา BlazorWebView ก็อาจคิดเช่นนั้นเช่นกัน
- และแน่นอนว่า Excel บางทีคุณอาจเคยทดลองใช้ไลบรารีการทำงานร่วมกันใน .NET บ้างไหม?
นอกจากนี้ ยังมีเวอร์ชันอื่นๆ ใน COM อีกด้วย แต่เราจะบันทึกไว้อีกครั้ง
เมื่อไม่มีอะไรเติบโตบนทุ่งหญ้า .NET สีเขียว - COM ยังอยู่ในการพัฒนาซอฟต์แวร์หรือไม่?
ทีมงาน .NET ได้เสนอแนวคิดหลายประการเพื่อทำให้แอปพลิเคชันรุ่นเก่าเหมาะสำหรับอนาคต ส่วนหนึ่งของไลบรารี Windows Forms และ WPF ถูกย้ายไปยัง .NET Core และ .NET ตามลำดับ นี่คือวิธีที่แอปพลิเคชัน Windows Forms ขนาดเล็กถึงขนาดกลางค้นพบหนทางสู่โลก .NET ใหม่ นี่เป็นการล้างเส้นทางสำหรับเดสก์ท็อป Blazor และ BlazorWebView ซึ่งทำให้สามารถโฮสต์แอปพลิเคชันไฮบริดใน Windows Forms ได้ และไม่ยากดังที่เห็นในบทความนี้:
เน้นที่ส่วนหนึ่งของ Windows Forms เพราะยังขาดอีกหลายอย่างก่อนที่ .NET จะเสร็จสมบูรณ์ ดังที่เห็นได้จากกล่องเครื่องมือใน Visual Studio
ด้วยแอปพลิเคชันในสายงานธุรกิจที่ซับซ้อน เสียงโห่ร้องก็สูงตามไปด้วย และมีเหตุผลที่ดีที่จะทำให้คุณไม่ต้องสนใจแอปพลิเคชันรุ่นเก่า โชคดีที่มีมาตรฐาน COM ที่เราสามารถใช้เพื่อลักลอบขนในแอปพลิเคชัน Blazor หรือ .NET ของเรา:
- .NET Framework ไม่เท่ากับ .NET — มีการเปลี่ยนแปลงที่สำคัญบางประการ การโยกย้ายไม่ใช่ทางเลือกเสมอไป และด้วย .NET Framework 4.8 ดูเหมือนว่าจะไม่จำเป็นเร่งด่วน เฉพาะอินเทอร์เฟซ COM เท่านั้นที่สามารถช่วยได้ที่นี่
- แอปพลิเคชันรุ่นเก่าเขียนด้วย Delphi หรือ Visual Basic 6 ที่นี่คุณสามารถปัดการย้ายข้อมูลได้ทันทีหากทุกอย่างยังคงดำเนินไปด้วยดีจากมุมมองของผู้ใช้ทางธุรกิจ เฉพาะตัวควบคุม ActiveX เท่านั้นที่สามารถช่วยได้ที่นี่
- การพัฒนาส่วนประกอบ .NET สำหรับ Microsoft Office (เวอร์ชันเดสก์ท็อป) กรณีที่คล้ายกันข้างต้น หรือคุณต้องการตั้งโปรแกรม Excel ใหม่ด้วย Blazor และ .NET โชคดีที่ Excel ยินดีต้อนรับตัวควบคุม ActiveX เช่นกัน
การเดินทางครั้งยิ่งใหญ่จากเดสก์ท็อป Blazor สู่ Excel VBA เริ่มต้นขึ้น
มีเหตุผลบางประการที่ไม่จำเป็นต้องเป็นที่นิยมในการพัฒนาซอฟต์แวร์เพื่อให้แอปพลิเคชัน .NET หรือแอปพลิเคชันเดสก์ท็อป Blazor มีตัวควบคุม ActiveX หรืออินเทอร์เฟซ COM อย่างไรก็ตาม ยังมีอะไรให้ทำอีกมากเมื่อเทียบกับ .NET Framework แต่ก่อนอื่นเรามาดูกันว่าเราต้องการบรรลุอะไร:
- เราจำกัดตัวเองให้อยู่ในสถานการณ์ทั่วไปง่ายๆ ซึ่งเราสามารถลากและวางการควบคุมของเราจากกล่องเครื่องมือลงในแบบฟอร์ม VBA หรือแผ่นงาน Excel
- จากนั้นเราต้องการตั้งค่าคุณสมบัติง่ายๆ ในตัวแก้ไข เช่น สตริง
- จากนั้นทริกเกอร์เหตุการณ์ในตัวควบคุมและตอบสนองต่อเหตุการณ์นั้นใน Excel-VBA โดยใช้ตัวจัดการเหตุการณ์
- และแน่นอนว่าองค์ประกอบควบคุมควรตอบสนองต่อสิ่งนี้และเปลี่ยนการแสดงผลด้วย
และเพื่อทำเช่นนั้น เรามาปรับใช้สถาปัตยกรรมต่อไปนี้สำหรับการควบคุม BlazorApp ของเรา:
- แอปเดสก์ท็อป Blazor ที่มาพร้อมกับทุกสิ่งที่จำเป็นในการเรียกใช้แอปพลิเคชัน รวมถึง BlazorWebView
- เรามีความโดดเด่นและใช้ไลบรารีของเราเองสำหรับทั้งเซิร์ฟเวอร์ COM และไคลเอนต์ COM นั่นชัดเจนขึ้นเล็กน้อย
- ไลบรารี .NET เป็นตัวตัดคำเพื่อให้อินเทอร์เฟซ COM เป็นเซิร์ฟเวอร์ในกระบวนการ สิ่งนี้เป็นไปไม่ได้ด้วย
*.exe
- จากนั้นตัวควบคุม Windows Forms จะฝังแอปเดสก์ท็อป Blazor ไว้ในตัวมันเอง เธอเล่นไคลเอนต์ COM ตัวอย่างที่ดีของการรวม .NET เข้ากับ .NET Framework แบบคลาสสิก นอกจากนี้ ไลบรารี .NET Framework ยังทำหน้าที่เป็นจุดเริ่มต้นสำหรับ Excel และได้รับการลงทะเบียนเป็นไลบรารี ActiveX Controls (COM)
- แอปพลิเคชัน VBA ตัวอย่างเพื่อเป็นข้อพิสูจน์ว่าโซลูชันซอฟต์แวร์ของเราได้รับการยอมรับจาก Excel เช่นกัน
ถ้ามันได้ผลล่ะ? เริ่มต้นความสนุกของ Blazor Excel!
ในตอนแรกคือเดสก์ท็อป Blazor
เราจะเริ่มต้นอย่างไร้เดียงสาด้วยแอปพลิเคชันเดสก์ท็อป Blazor เมื่อต้องการทำเช่นนี้ เพียงสร้างโครงการ Windows Forms (.NET) ใหม่ และรวม BlazorWebView
ผ่านแพ็คเกจ Microsoft.AspNetCore.Components.WebView.WindowsForms
ตอนนี้หนทางสู่แอปพลิเคชันเดสก์ท็อป Blazor แบบไฮบริดนั้นอยู่ไม่ไกล:
- เราสร้างไฟล์
wwwroot/index.html
หากคุณต้องการ คุณยังสามารถอ้างอิงสไตล์ชีทดีๆ เช่นBootstrap
ฯลฯ ที่นี่ - ต่อไป เราต้องการองค์ประกอบการเปิดตัวของ Blazor ผู้ต้องสงสัยตามปกติจะใช้:
App.razor
- ตอนนี้เราแค่ต้องเริ่มต้นความสนุก
- หลังจากนั้นมันก็จะน่าตื่นเต้น เพื่อให้คลาสของเราสามารถแก้ไขได้โดยใช้อินเทอร์เฟซ COM เราจึงกำหนดอินเทอร์เฟซสองแบบ: หนึ่งรายการสำหรับคุณสมบัติทั้งหมดและอีกรายการหนึ่งสำหรับกิจกรรมทั้งหมด
- เราจัดการเรื่องทั้งหมดไว้ในไลบรารีของชั้นเรียนที่แยกต่างหาก
- อินเทอร์เฟซดี การใช้งานจะดีกว่า นั่นเป็นเหตุผลที่เราจัดเตรียมคุณลักษณะที่เหมาะสมและการใช้งานอินเทอร์เฟซให้กับชั้นเรียนของเรา คุณต้องสงสัยเกี่ยวกับวิธีแปลก ๆ ในการจัดกิจกรรมสำหรับ COM ตอนนี้ให้พิจารณาว่าในท้ายที่สุดแล้ว ทุกอย่างจะต้องบริโภคได้ผ่านการจัดเรียงและอาจเป็นไปได้ใน DLL อื่นๆ ที่พัฒนาด้วย C++ เป็นต้น และพวกเขารู้พอยน์เตอร์ฟังก์ชันสูงสุด แต่ไม่มีเหตุการณ์. NET นั่นเป็นเหตุผลว่าทำไมจึงมีไส้กรอกพิเศษสำหรับ COM
- และแอปพลิเคชัน Blazor ของเราก็พร้อมแล้ว เพียงแค่กด F5
แน่นอนว่าตอนนี้เป็นการวิ่งควบหมู หากคุณต้องการอ่านรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการทำงานของ BlazorWebView คุณสามารถอ่านบทความด้านบนเกี่ยวกับการรวม Blazor ใน Windows Forms
ดูอินเทอร์เฟซ COM อย่างรวดเร็ว
มาดูกันว่าท้ายที่สุดแล้วเราต้องการอะไรเพื่อให้แอป Blazor ของเราสามารถใช้เป็นเซิร์ฟเวอร์ COM ได้:
- อินเทอร์เฟซสำหรับการอธิบายคุณสมบัติและวิธีการ ซึ่งกำหนด
Guid
โดยใช้แอตทริบิวต์ที่ไม่ซ้ำกันGuid
มีความสำคัญ เนื่องจากทันทีที่คุณเรียกใช้อินเทอร์เฟซ COM โปรแกรมของคุณจำเป็นต้องทราบว่า DLL ที่รับผิดชอบด้านความสนุกสนานนั้นอยู่ที่ใดในรีจิสทรี ที่เหลือก็อธิบายได้ด้วยตนเองจริงๆ - ตอนนี้ถึงอินเทอร์เฟซสำหรับเหตุการณ์: สิ่งนี้ไม่ได้กำหนดเหตุการณ์ .NET ตามที่อาจสันนิษฐานได้ แต่เป็นวิธีการที่ทำหน้าที่เป็นเทมเพลตสำหรับตัวจัดการเหตุการณ์ในไคลเอนต์ COM
- และอินเทอร์เฟซ COM สำหรับเหตุการณ์เชื่อมโยงกับการใช้งานที่ถูกต้องอย่างไร ค่อนข้างแปลกตามแบบแผนและการกำหนดประเภทผ่านแอตทริบิวต์คลาส
Wrapper COM สำหรับแอปเดสก์ท็อป Blazor ของเรา
ขออภัย ไม่สามารถลงทะเบียนแอปพลิเคชัน .NET เป็นเซิร์ฟเวอร์ COM ได้โดยตรง สิ่งนี้จำเป็นต้องมีไลบรารี .NET ต้องกำหนดคุณสมบัติพิเศษ EnableComHosting
ในคุณสมบัติโปรเจ็กต์ *.csproj
นอกจากนี้เราต้องจำไว้ว่าหลังจากการลงทะเบียน COM แล้ว DLL ของเราจะรับผิดชอบต่อตัวเองอย่างสมบูรณ์ในโลกนี้ ดังนั้นเราจึงต้องใช้เหตุการณ์หลังการสร้างเพื่อให้แน่ใจว่า DLL ที่จำเป็นทั้งหมดอยู่ในไดเร็กทอรีเอาต์พุต
ขณะนี้กระบวนการสร้างจะสร้าง DLL *.comhost.dll
เพิ่มเติม ซึ่งใช้ในการลงทะเบียนไลบรารี .NET ของเราเป็นเซิร์ฟเวอร์ที่อยู่ระหว่างดำเนินการ
regsvr32.exe YOUR_ASSEMBLY_NAME.comhost.dll // run this as administrator
ตอนนี้ DLL ของเราสามารถใช้งานได้โดยไคลเอนต์ COM
ประตูสู่ EXCEL ของ Blazor - ไลบรารีการควบคุมแบบฟอร์ม Windows ที่มองเห็นได้ของ COM
ยังเร็วไปนิดหน่อยในการใช้การควบคุม Blazor ของเรา เพราะอินเทอร์เฟซ COM เพียงอย่างเดียวไม่เพียงพอ แต่จำเป็นต้องมีไลบรารีประเภทที่คุณจัดเก็บไว้ทั่วโลกในรีจิสทรีด้วย Regasm เมื่อนั้นแอปพลิเคชัน Excel ของเราจะได้รับประโยชน์จากโซลูชันของเราเท่านั้น แต่ก่อนอื่น แอปพลิเคชัน Blazor บนเดสก์ท็อปของเราต้องอยู่ในไลบรารีควบคุม Windows Forms แบบคลาสสิกโดยใช้ COM คุณต้องมีเคล็ดลับบางประการสำหรับสิ่งนี้:
- ก่อนอื่น เราต้องการอินสแตนซ์ของ BlazorApp ของเรา
- นี่คือชั่วโมงทองของที่จับหน้าต่างของเรา เนื่องจากเราสามารถใช้เพื่อจับภาพหน้าต่างที่ปกติจะแสดงในแอป Blazor บนเดสก์ท็อปของเราและวางไว้ในหน้าต่างหลักของเรา
- เราฝังสิ่งทั้งหมดอีกครั้งในหน้าต่าง Windows Forms เท่าที่ฉันรู้ clean docking ในหน้าต่างพาเรนต์ผ่านตัวจัดการใช้งานได้กับคลาสฟอร์มเท่านั้น หากคุณมีข้อเสนอแนะอื่นใดฉันจะขอบคุณมาก
ดังนั้น! เท่านี้ก็เสร็จแล้ว ขั้นตอนที่คุ้นเคยสำหรับการกำหนดอินเทอร์เฟซ COM จากนั้นปฏิบัติตาม นอกจากนี้ ยังมีการบ้านง่ายๆ ที่คุณต้องทำ:
- เหตุการณ์ .NET ของอินเทอร์เฟซของเราต้องแต่งงานกับอินเทอร์เฟซเหตุการณ์ COM ในไคลเอนต์ COM ของเราโดยใช้ตัวให้บริการเหตุการณ์
- จากนั้นอินสแตนซ์แอป Blazor ของอินเทอร์เฟซ COM ของเราก็เชื่อมโยงกับการควบคุม Windows Forms แบบคลาสสิกของเรา
- เครื่องหมายถูกเล็กน้อยทำให้มั่นใจได้ว่าอินเทอร์เฟซที่เรากำหนดไว้นั้นได้รับการลงทะเบียนเป็นไลบรารีประเภทหลังการบิลด์ด้วย
- สุดท้ายแต่ไม่ท้ายสุด มีบางสิ่งที่ดูดี: เราจัดเก็บไอคอนที่สวยงามสำหรับกล่องเครื่องมือโดยใช้ไฟล์ทรัพยากร Win32 อย่างไรก็ตามเราต้องไม่ลืมสร้างคีย์รีจิสทรีที่ถูกต้องเมื่อลงทะเบียนแอสเซมบลี
// You can create a *.res file by Visual Studio Command Line rc.exe <YOUR_RC_FILE> // Example content of *.rc file 101 BITMAP "BlazorApp.WinFormsControls.bmp" //ID TYPE "RELATIVE PATH"
ตอนนี้ทุกอย่างควรมองเห็นได้จาก Excel แล้วมันทำงานแบบนั้นเหรอ?
ความงามของ Blazor และ VBA Beast
ถึงเวลาเก็บเกี่ยวผลงานของเราแล้ว และหลังจากการทำงานหนักในโลก .NET พวกเขาเกือบจะล้มลงแทบเท้าเรา โดยหลักการแล้ว ตอนนี้เรามีสองตัวเลือกในการฝังแอปพลิเคชัน Blazor บนเดสก์ท็อปใน Excel:
- โดยตรงในแผ่นงาน Excel ของเราในฐานะตัวควบคุม ActiveX
- หรือในโค้ด VBA ของเราเป็นตัวควบคุม ActiveX บนแบบฟอร์ม
การฝังในแผ่นงาน Excel ทำได้ง่ายมาก ตอนนี้เราสามารถวางแอป Blazor ของเราได้ทุกที่โดยใช้การลากและวาง และที่ดียิ่งขึ้นไปอีก: เรายังสามารถตั้งค่าคุณสมบัติที่เรากำหนดไว้ในอินเทอร์เฟซ COM ของเราได้อย่างง่ายดายผ่านหน้าต่างคุณสมบัติ
ในที่สุด เราก็ปฏิบัติต่อตัวเองในฐานะตัวจัดการเหตุการณ์และทดสอบทุกสิ่ง:
สำหรับแบบฟอร์ม VBA ให้ไปที่โปรแกรมแก้ไข VBA ของ Excel ก่อน มาสร้างคลาสแบบฟอร์มใหม่และเพิ่มตัวควบคุม Blazor App ActiveX ที่เพิ่งอบใหม่ลงในกล่องเครื่องมือ มันดูดีจริงๆ! หรือ?
อีกครั้ง ทุกอย่างจะถูกแทรกอย่างกระชับและกระชับโดยใช้การลากและวาง เท่านี้ก็เรียบร้อย แอปพลิเคชันเดสก์ท็อป Blazor จะสว่างขึ้นในรูปแบบ VBA ของเรา มหัศจรรย์จริงๆ
การทดลองกับ Blazor ในฐานะตัวควบคุม ActiveX ประสบความสำเร็จหรือไม่
เราสามารถรวม Blazor เข้ากับ Excel ผ่านทาง ActiveX ได้สำเร็จ ทางนั้นค่อนข้างเป็นหิน แต่อย่างอื่นมันคงจะน่าเบื่อ ปัญหาที่ใหญ่ที่สุดคือ COM ยังไม่ได้รับการสนับสนุนอย่างสมบูรณ์ใน .NET 6 เนื่องจากอยู่ใน .NET Framework แบบคลาสสิก จนถึงขณะนี้ การบูรณาการที่สะดวกและโดยตรงในแอปพลิเคชัน Excel หรือ .NET ผ่านทางไลบรารีประเภทได้ถูกปฏิเสธจากเรา เราอาจจะต้องต่อสู้เพื่อฝ่าฟันสิ่งนั้นไปสักระยะหนึ่ง
แต่ท้ายที่สุดแล้ว เราก็สามารถรวม Blazor ซึ่งเป็นหนึ่งในเทคโนโลยีล่าสุดของ Microsoft ไว้ในแอปพลิเคชันที่ใช้ ActiveX และ COM ซึ่งเป็นเทคโนโลยีจากดินแดนก่อนยุคของเรา
หากคุณมีเวลาและความปรารถนา ลองดูตัวอย่าง GitHub แบบเต็ม:
มันมหัศจรรย์มาก…
และคุณรู้ไหมว่า: หากคุณต้องการบริการ .NET ระดับมืออาชีพเพื่อเร่งความเร็วโปรเจ็กต์ของคุณ 🚀 คุณสามารถหาเราได้ที่นี่ (เป็นภาษาเยอรมัน แต่คุณสามารถแปลได้โดยเบราว์เซอร์ของคุณ 😉):