Xtra.Shared 2.2.0

dotnet add package Xtra.Shared --version 2.2.0
                    
NuGet\Install-Package Xtra.Shared -Version 2.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Xtra.Shared" Version="2.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Xtra.Shared" Version="2.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Xtra.Shared" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Xtra.Shared --version 2.2.0
                    
#r "nuget: Xtra.Shared, 2.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Xtra.Shared@2.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Xtra.Shared&version=2.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Xtra.Shared&version=2.2.0
                    
Install as a Cake Tool

Xtra Shared Library

(v2.2.0)

คุณสมบัติหลัก

  • Controllers - Base controller สำหรับ API (XtraBaseController, XtraBaseAuthenController, XtraBaseMasterController, XtraBaseTransactionController)
  • Services / DAL - Data access layer ด้วย Dapper รองรับ Oracle และ SQL Server (XtraBaseDAL, XtraAuthenDAL, XtraTokenDAL, XMasterDAL, XtraTransactionDAL, SysLogDAL, XEmailDAL)
  • Authentication - JWT Token และ LDAP (XtraBaseTokenDAL, LDAPHelper)
  • Email - SendEmailService, EmailSetting, EmailTemplate
  • Helpers - XtraCryptoHelper, XtraConfigurationHelper, AppLogHelper, ExceptionHelper, EmailHelper
  • Extensions - Extension methods สำหรับ DataSet, DataTable, JArray, List, object, string, Type, DbType, QueryOptions
  • Options - JwtConfigOptions, XtraConfigOptions, XtraConnectionOptions, XtraLogOptions, XtraSmtpOptions

โครงสร้างโปรเจกต์

xtra-shared-library/
  Bases/        Parameter และ configuration พื้นฐาน
  Controllers/  Base controllers
  Extensions/   Extension methods
  Helpers/      Utility helpers
  Interfaces/   Interfaces ของ DAL และ Service
  Models/       Authen, Base, Email
  Options/      Strongly-typed options
  Services/     DAL และ SendEmailService
  scripts/      sonar-scan.ps1 (SonarQube scan ในเครื่อง)
  tests/        Unit และ integration tests (Xtra.Shared.Tests, xunit)

อีกโปรเจกต์ในโซลูชัน: xtra-shared-library.tesing-app (แอปสำหรับทดสอบ)

Dependencies หลัก

Dapper, Dapper.Oracle.NetCore, Oracle.ManagedDataAccess.Core, Microsoft.Data.SqlClient, System.IdentityModel.Tokens.Jwt, Microsoft.IdentityModel.Tokens, NETCore.Encrypt, Newtonsoft.Json, System.DirectoryServices.AccountManagement, Serilog.Extensions.Logging, System.Security.Cryptography.Pkcs (pin เวอร์ชันที่แก้ช่องโหว่), Microsoft.AspNetCore.App (FrameworkReference)

คุณภาพโค้ด (SonarQube)

ผล scan ล่าสุด (2026-10-16, v2.2.0) บน SonarQube ในเครื่อง:

หัวข้อ ผล
Quality Gate ✅ Passed
Bugs / Vulnerabilities / Code smells 0 / 0 / 0
Reliability / Security / Maintainability A / A / A
Coverage (ทั้งโปรเจกต์) 76.0%
Coverage on New Code 90.1%
Duplication 3.8%

Scan เอง: ตั้ง environment variable SONAR_TOKEN (User Token หรือ Global Analysis Token) แล้วรัน

.\scripts\sonar-scan.ps1

Integration tests ใช้ SQL Server LocalDB ((localdb)\MSSQLLocalDB) จึงรันได้เฉพาะ Windows ที่ติดตั้ง LocalDB

บันทึกการเปลี่ยนแปลง

v2.2.0

แก้ข้อค้นพบจาก SonarQube และ bug ที่พบระหว่างเพิ่ม test (test เพิ่มจาก 33 เป็น 324) ต้อง rebuild โปรเจกต์ที่ใช้งาน และควรทดสอบ login/refresh token, การส่งอีเมล, log ลงไฟล์ และไฟล์แนบบน dev ก่อนใช้งานจริง

ความปลอดภัย

  • XtraBaseController.DeleteFiles: แก้ช่องโหว่ที่ request ส่ง FileName แล้วลบหรือเขียนทับไฟล์ในโฟลเดอร์ของแอปได้ (เช่น appsettings.json) — แนะนำให้ทุกโปรเจกต์อัปเกรด
  • SaveFiles / DeleteFiles / SetDefaultFile และ helper ของโฟลเดอร์ไฟล์แนบ: ปิด path traversal ผ่าน DocuType, ID, FileName (เช่น ..\..\appsettings.json) — ค่าต้องเป็นชื่อเดี่ยว ไม่มี / \ : หรือ .. มิฉะนั้นได้ 400; ชื่อไฟล์ที่ upload ถูกตัดเหลือเฉพาะชื่อไฟล์
  • อ้างอิง System.Security.Cryptography.Pkcs 10.0.13 ตรง เพื่อแทน 9.0.18 ที่ติดมากับ Microsoft.Data.SqlClient / Oracle.ManagedDataAccess.Core (CVE-2026-84008 ระดับ high, CVE-2026-70162 ระดับ moderate)
  • SeparateWords ใช้ Regex ที่มี timeout 1 วินาที (ป้องกัน ReDoS)

Breaking changes

  • GrantTypes.Password / RefreshToken / ChangeRole เปลี่ยนจาก static field เป็น const
  • XType.GetOracleDbType / GetOracleMappingType มีพารามิเตอร์ใหม่ useNameRules (default true) และผลลัพธ์ของ property แบบ string / nullable เปลี่ยน (ดูหัวข้อแก้ไข)
  • Member ร่วมของ AbstractBaseDAL และ AbstractBaseTokenDAL ย้ายไปอยู่ใน base class ใหม่ AbstractDALCore (ชื่อและ type เหมือนเดิม)

พฤติกรรมที่เปลี่ยน

  • JWT claim iat เป็นตัวเลขวินาที (NumericDate ตาม RFC 7519) แทนข้อความวันที่ตาม culture ของ server — token อ่านได้ด้วย JwtSecurityTokenHandler แล้ว; token เดิมยังใช้ได้จนหมดอายุ
  • วันที่ในอีเมล (EmailHelper.getEmailTemplate) เป็น dd/MM/yyyy แบบ ค.ศ. เสมอ ไม่ขึ้นกับ culture ของ server
  • ชื่อไฟล์ log เริ่มต้นเป็น log-yyyyMMdd.txt (เดิมเป็น log-YYYY{เดือน}DD.txt จาก format ที่ผิด)
  • GetFiles / DeleteFiles จัดการเฉพาะ content folder (ส่วน default folder ถูกปิดไว้ตั้งแต่ปี 2022 และลบโค้ดที่ไม่ทำงานออกแล้ว)
  • ข้อความของ DBConcurrencyException ใน DAL บางเมธอดเปลี่ยน (เช่น Cancel เป็น "cancelling the transaction")

แก้ไข

  • AppLogHelper.WriteLogFile ไม่เคยเขียน log ได้ (error "The parent is missing" ทุกครั้ง) — ตอนนี้เขียนผ่าน ILogger หรือลงไฟล์ (มี timestamp นำหน้า) ได้แล้ว และไม่แก้ไข JObject ที่ส่งเข้ามา
  • SendEmailService.SmtpSendAsyncEmail อาจไม่ได้ส่งเมลจริง (ไม่ได้ await แล้ว dispose client) — ตอนนี้ส่งครบทุกฉบับ
  • XDataSet.SuggestDuplicateName วนลูปไม่รู้จบ ทำให้ XDataSet.NewInstance / CastJObject / ReplaceTable ค้างเมื่อ JSON มี array
  • XDataTable.SetValue แบบระบุแถวไม่เคยเซ็ตค่า
  • XDbType.SqlDbTypeName คืน "" เสมอ (เงื่อนไขกลับด้าน) — ตอนนี้คืนชื่อ SQL type เช่น nvarchar
  • XType.GetOracleDbType คืน Object ให้ property แบบ string ทุกตัว; กฎตามชื่อ (...ID → Varchar2, ...DATE/...DATETIME → Date, ...TIMESTAMP → TimeStamp) ไม่เคยทำงาน; int? ได้ Object — แก้แล้วทั้งหมด
  • XtraBaseAuthenController.GetJwt(null) throw NullReferenceException แทนการคืน response ว่าง; ClearJwt log warning แม้ expire สำเร็จ
  • ExceptionHelper.Clear() throw เมื่อเรียกก่อนเมธอดอื่น
  • EmailHelper: ไม่ตั้งค่า MailTo แล้วไม่ throw อีก — ส่งไปที่ผู้รับในข้อมูลอีเมล (ReSendEmail ใช้ ToEmail ของแถว)
  • XtraConfigOptions: property เป็น public (เดิมเป็น private ทั้งหมด จึง bind จาก configuration ไม่ได้)
  • XtraQueryOptions.AddQueryData: DTO ที่มี collection / object ซ้อนไม่ throw อีก; Password ของ DTO ไม่ถูกเก็บ (ตั้งใจ — ระบุชัดในโค้ดแล้ว)
  • XtraBaseTransactionController.GetToken: แจ้ง error ชัดเจนเมื่อไม่ได้ตั้งค่า GetToken / BasicAuthToken และไม่ block ด้วย .Result

ปรับปรุงโค้ด

  • รวมการส่งอีเมลทั้ง 8 จุดไว้ที่ SmtpMailSender และเพิ่ม XtraSmtpOptions (EnableSsl ยังมาจาก configuration)
  • DAL ใช้ helper กลาง (UseStoredProcedure, QueryString, ExecuteInTransaction, QueryInTransaction) — โค้ด DAL ลดลงประมาณ 460 บรรทัด
  • Structured logging (placeholder มีชื่อ และเช็ค IsEnabled ก่อน serialize), dotnet format และแก้ analyzer rules (CA/IDE) — issue จาก SonarQube ลดจาก 407 เหลือ 0
  • .editorconfig จำกัด IDE0290 / IDE0130 / CA1822 / IDE0060 ไว้กับโค้ดที่ไม่ใช่ public (การแก้จะทำให้ public API เปลี่ยน — รอ 3.0.0)

Test และเครื่องมือ

  • Unit test 311 ตัว + integration test 13 ตัว บน SQL Server LocalDB (Category=Integration; GitLab CI ข้ามด้วย --filter "Category!=Integration")
  • Fake SMTP server ในตัว test (ไม่เพิ่ม package), coverage ผ่าน coverlet.collector
  • scripts/sonar-scan.ps1 สำหรับ scan SonarQube ในเครื่อง (ต้องตั้ง SONAR_TOKEN)

ขั้นตอนอัปเกรด

  1. Rebuild โปรเจกต์ที่ใช้งาน (GrantTypes เป็น const และ DAL base class เปลี่ยน)
  2. ถ้ามีโค้ดเรียก GetOracleDbType / GetOracleMappingType กับ property แบบ string ที่ชื่อลงท้าย Date / DateTime / Timestamp แต่ค่าไม่ตรงกับ NLS date format ของ Oracle ให้ส่ง useNameRules: false
  3. ถ้ามีระบบที่อ่าน JWT iat เป็น string ให้แก้เป็นตัวเลข (Unix seconds)
  4. ถ้าแอปใช้ ID หรือ DocuType ที่มี / หรือ \ เป็นชื่อโฟลเดอร์ไฟล์แนบ (เช่น PO/2026/001) ต้องเปลี่ยนเป็นค่าที่ไม่มีตัวคั่น path

v2.1.1

  • Package ID เปลี่ยนเป็น Xtra.Shared

v2.1.0

มี breaking changes สำหรับโปรเจกต์ที่สืบทอด base controller หรือใช้ type ของ SqlClient โดยตรง รวมการแก้ของ v2.0.4 ไว้ครบ

Breaking changes

  • Constructor ของ base controller รับ logging เพิ่ม: ต้องส่ง ILogger<T> และ IOptions<XtraLogOptions> ให้ base class (XtraBaseController, XtraBaseMasterController, XtraBaseAuthenController, XtraBaseTransactionController)
  • AppLogHelper เป็น static class: เรียก AppLogHelper.Initialize(systemLogDAL, logger, logOptions) ตอน startup แทนการสร้าง instance (เอา ConnectionString และ appLogKey ออก)
  • ย้ายจาก System.Data.SqlClient ไป Microsoft.Data.SqlClient 7.1.1 — โค้ดที่อ้าง namespace เดิมต้องเปลี่ยน
  • เลิก throw ex เปลี่ยนเป็น throw exception ที่ห่อ inner exception: DAL/token ใช้ DBConcurrencyException, XtraQueryOptions.CloneDeep ใช้ InvalidOperationException, การ cast ผิดใช้ InvalidCastException, login ไม่ผ่านใช้ UnauthorizedAccessException (เดิมเป็น Exception)
  • ถอด System.Drawing.Common ออกจาก dependencies — โปรเจกต์ที่ใช้ต่อเนื่องผ่านไลบรารีนี้ต้องอ้างเอง
  • เปลี่ยนจาก package Microsoft.AspNetCore.* (Authentication.Abstractions, Authorization, Authorization.Policy, Http, Mvc.Core), Microsoft.Net.Http.Headers และ Microsoft.Extensions.Http เป็น FrameworkReference Microsoft.AspNetCore.App — โปรเจกต์ที่ใช้ต้องมี ASP.NET Core shared framework

เพิ่ม

  • XtraLogOptions (Xtra.Options): LogLevel, FileName, Extension, FilePath, IsFileLog, IsDbLog, FileSizeLimitMB, LogRetainDays, RetainFileCountLimit, LogTable, LogColumnMapping
  • AppLogHelper.PrepareLogPath() และ GetLogFilePath() อ่านค่าจาก XtraLogOptions; เขียน log ผ่าน ILogger (เพิ่ม Serilog.Extensions.Logging)
  • Config key ใหม่ DefaultFilePath และ TempFileExpirationMinutes ใน XtraKeyConfiguration
  • XtraBaseTransactionController: method ตรวจสิทธิ์ และขอ access token แบบ client credentials; เพิ่ม XML docs ให้ base controllers
  • [SupportedOSPlatform("windows")] บน LDAP helper

แก้ไข

  • XtraAuthenDAL: ชื่อ stored procedure เริ่มต้นใช้ DatabaseTable ({table}_Sel_Logout, {table}_Save_Signin, default smUser) เดิม string.Format ไม่ได้ใช้ชื่อ table
  • ลบโค้ดที่ comment ไว้และตัวแปรที่ไม่ใช้ใน DAL และ token helpers

ขั้นตอนอัปเกรด

  1. แก้ constructor ของ controller ที่สืบทอด ให้ส่ง ILogger<T> และ IOptions<XtraLogOptions> และตั้งค่า XtraLogOptions ใน configuration
  2. เรียก AppLogHelper.Initialize(...) หนึ่งครั้งตอน startup
  3. เปลี่ยน System.Data.SqlClient เป็น Microsoft.Data.SqlClient
  4. เพิ่ม System.Drawing.Common ในโปรเจกต์ถ้าใช้งาน

v2.0.4

แก้ regression ของ v2.0.3 — แนะนำให้ทุกโปรเจกต์ที่ใช้ v2.0.3 ย้ายมา v2.0.4

  • คืนพฤติกรรมของ TitleCase และ CamelCase ให้ตรงกับ v2.0.2:
    • TitleCase(value, removeSpace = false, removeSpecialCharacter = true, lowerRest = false)
    • CamelCase(value, removeSpace = false, removeSpecialCharacter = true, lowerRest = false)
  • คืน RemoveSpecialCharacters(value, removeUnderscore, removeDash, removeSpace) ที่หายไปใน v2.0.3
  • lowerRest (แปลงเป็นตัวพิมพ์เล็กก่อนเพื่อให้คำตัวพิมพ์ใหญ่ล้วนถูกแปลงด้วย) ยังอยู่ แต่ย้ายไปเป็นพารามิเตอร์ ท้ายสุด และ default เป็น false — ถ้าต้องการพฤติกรรมแบบ v2.0.3 ให้ส่ง lowerRest: true
  • เพิ่ม unit tests (tests/Xtra.Shared.Tests) ล็อกพฤติกรรมของ TitleCase/CamelCase และรันใน GitLab CI
  • เพิ่ม job publish_nuget ใน GitLab CI (กดรันเอง) สำหรับ publish ขึ้น nuget.org ด้วย Trusted Publishing (ไม่ต้องใช้ API key ถาวร)
  • Package ID เป็น CODATIC.XtraPM.Shared.Libraries.NET_10.0 (assembly ยังชื่อ Xtra.Shared, namespace Xtra.Extensions)
  • ย้าย repository URL เป็น https://gitlab.com/sharedlibrary/xtra-shared-libraries

v2.0.3 (เลิกใช้ — ห้ามใช้)

  • เพิ่ม CamelCase และพารามิเตอร์ lowerRest ให้ TitleCase ใน XString
  • อัปเดตแพ็กเกจ dependencies เป็นเวอร์ชันล่าสุด
  • ปัญหา: v2.0.3 แตกจาก master โดยไม่มีงานของ v2.0.2 ทำให้พารามิเตอร์ตัวที่สองของ TitleCase/CamelCase เปลี่ยนความหมายจาก removeSpecialCharacter เป็น lowerRest โดยไม่มี compile error, ค่า default เปลี่ยน และ RemoveSpecialCharacters หายไป ผลคือชื่อที่ได้ต่างจากเดิม เช่น UserId เป็น userid, CurrentStatus เป็น currentstatus
  • แก้แล้วใน v2.0.4

v2.0.2

  • TitleCase เพิ่มพารามิเตอร์ removeSpecialCharacter (default true)
  • เพิ่ม CamelCase(value, removeSpace = false, removeSpecialCharacter = true) และ RemoveSpecialCharacters
  • เพิ่ม Microsoft.Net.Http.Headers และถอด Microsoft.AspNetCore.Authentication.Core ออกจาก dependencies

การใช้งาน

dotnet add package Xtra.Shared --version 2.2.0

Build และ Publish

dotnet build -c Release
dotnet test tests/Xtra.Shared.Tests/Xtra.Shared.Tests.csproj                                    # ทั้งหมด (ต้องมี LocalDB)
dotnet test tests/Xtra.Shared.Tests/Xtra.Shared.Tests.csproj --filter "Category!=Integration"   # ไม่รวม integration tests
nuget.exe push {package file} {apikey} -Source 

หรือ publish ขึ้น nuget.org ผ่าน GitLab CI: job publish_nuget (กดรันเองบน default branch) ใช้ Trusted Publishing — ต้องตั้ง CI/CD variable NUGET_USERNAME (nuget.org profile name) และมี policy บน nuget.org ที่ตรงกับ project นี้

ดูเพิ่มเติมที่ package-commands.md

ลิงก์

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.2.0 88 10/16/2026
2.1.1 83 10/14/2026
2.0.3 92 10/12/2026 2.0.3 is deprecated because it has critical bugs.
2.0.2 84 10/12/2026