diff --git a/Directory.Packages.props b/Directory.Packages.props index 42492cf6e0..bed31674c8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -114,10 +114,10 @@ - - - - + + + + @@ -129,11 +129,11 @@ - - - - - + + + + + diff --git a/docs/en/Community-Articles/2025-09-02-training-campaign/post.md b/docs/en/Community-Articles/2025-09-02-training-campaign/post.md index 821b06de6b..20f2bcf4bd 100644 --- a/docs/en/Community-Articles/2025-09-02-training-campaign/post.md +++ b/docs/en/Community-Articles/2025-09-02-training-campaign/post.md @@ -25,5 +25,5 @@ Simply visit our training page, select your preferred package, add your note if Invest in your skills and advance your career with ABP.IO training. This offer won’t last long, so grab your spot now\! -### 🔗[Sign up for training now and start building with ABP](https://abp.io/trainings?utm_source=referral&utm_medium=website&utm_campaign=training_abpblogpost)\! +### 🔗[Pick your package and send your training request now!](https://abp.io/trainings?utm_source=referral&utm_medium=website&utm_campaign=training_abpblogpost) diff --git a/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/Post.md b/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/Post.md new file mode 100644 index 0000000000..3de235e86d --- /dev/null +++ b/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/Post.md @@ -0,0 +1,173 @@ +# .NET 10: What You Need to Know (LTS Release, Coming November 2025) + +The next version of .NET is .NET 10 and it is coming with **Long-Term Support (LTS)**, scheduled for **November 2025**. + +On **September 9, 2025**, Microsoft released **.NET 10 Release Candidate 1 (RC1)**, which supports go-live usage and is compatible with [Visual Studio 2026 Insider](https://visualstudio.microsoft.com/insiders/) and [Visual Studio Code Insider](https://code.visualstudio.com/insiders/) via the [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) extension. + +------ + +## .NET 10 Runtime Enhancements + +- **JIT Speed-ups**: Enhanced struct argument handling—members now go directly into registers, reducing memory load/store operations. +- **Advanced Loop Optimization**: New graph-based loop inversion improves precision and boosts further optimizations. +- **Array Interface De-virtualization**: Critical for performance, now array-based enumerations inline and skip virtual calls including de-abstraction of array enumeration and small-array stack allocation. +- **General JIT Improvements**: Better code layout and branch reduction support overall efficiency. + +------ + +## Language & Library Upgrades + +### C# 14 Enhancements + +- Field-backed properties: easier custom getters/setters. +- `nameof` for unbound generics like `List<>`. +- Implicit conversions for `Span` and `ReadOnlySpan`. +- Lambda parameter modifiers (`ref`, `in`, `out`). +- Partial constructors/events. +- `extension` blocks for static extension members. +- Null-conditional assignment (`?.=`) and custom compound/increment operators. + +### F# & Visual Basic Enhancements + +- F# improvements via `preview`, updated `FSharp.Core`, and compiler fixes. +- VB compiler supports `unmanaged` generics and respects `OverloadResolutionPriorityAttribute` for performance and overload clarity. + +## .NET Libraries & SDK + +### Libraries: + +- Better ZipArchive performance (lazy entry loading). +- JSON improvements, including `JsonSourceGenerationOptions` and reference-handling tweaks. +- Enhanced `OrderedDictionary`, ISOWeek date APIs, PEM data and certificate handling, `CompareOptions.NumericOrdering` + +### SDK & CLI: + +- No major new SDK features in RC1—you should expect stability fixes rather than additions. +- Earlier previews brought JSON support improvements (e.g., `PipeReader` for JSON, WebSocketStream, ML-DSA crypto, AES KeyWrap), TLS 1.3 for macOS + +------ + +## ASP.NET Core & Blazor + +### Blazor & Web App Security: + +Enhanced OIDC and Microsoft Entra ID integration, including encrypted token caching and Key Vault use. + +### UI Enhancements: + +- `QuickGrid` gains `RowClass` for conditional styling. +- Scripts now served as static assets with compression and fingerprinting. +- NavigationManager no longer scrolls to top for same-page updates. + +### API Improvements: + +Full support for OpenAPI 3.1 (JSON Schema draft 2020-12), and metrics for authentication/authorization events (e.g., sign-ins, logins) . + +------ + +## .NET MAUI + +Updates include multiple file selection, image compression, WebView request interception, and support for Android API 35/36. + +## EF Core + +LINQ enhancements, performance boosts, better Azure Cosmos DB support, and more flexible named query filters. + + + +## Breaking Changes in .NET 10 + +### ASP.NET Core - Breaking Changes in .NET 10: + +.NET 10 Preview 7 brings **several deprecations + behavior changes**, while **RC1 removes the old WebHost model**. + +- **[Cookie login redirects disabled](https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/cookie-authentication-api-endpoints)** → Redirects no longer occur for API endpoints; APIs now return `401`/`403`. *(Behavioral change)* +- **[WithOpenApi deprecated](https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/withopenapi-deprecated)** → Extension method removed; use updated OpenAPI generator features. *(Source incompatible)* +- **[Exception diagnostics suppressed](https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/exception-handler-diagnostics-suppressed)** → When `TryHandleAsync` returns true, exception details aren’t logged. *(Behavioral change)* +- **[IActionContextAccessor obsolete](https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/iactioncontextaccessor-obsolete)** → Marked obsolete; may break code depending on it. *(Source/behavioral change)* +- **[IncludeOpenAPIAnalyzers deprecated](https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/openapi-analyzers-deprecated)** → Property and MVC API analyzers removed. *(Source incompatible)* +- **[IPNetwork & KnownNetworks obsolete](https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/ipnetwork-knownnetworks-obsolete)** → Old networking APIs removed in favor of new ones. *(Source incompatible)* +- **[ApiDescription.Client package deprecated](https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/apidescription-client-deprecated)** → No longer maintained; migrate to other tools. *(Source incompatible)* +- **[Razor run-time compilation obsolete](https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/razor-runtime-compilation-obsolete)** → Disabled at runtime; precompilation required. *(Source incompatible)* +- **[WebHostBuilder, IWebHost, WebHost obsolete](https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/webhostbuilder-deprecated)** → Legacy hosting model deprecated; use `WebApplicationBuilder`. *(Source incompatible, RC1)* + +### EF Core - Breaking Changes in .NET 10: + +You can find the complete list at [Microsoft EF Core 10 Breaking Changes page](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-10.0/breaking-changes). Here's the brief summary: + +#### EF Core - SQL Server + +- **JSON column type by default (Azure SQL / compat level ≥170).** Primitive collections and owned types mapped to JSON now use SQL Server’s native `json` type instead of `nvarchar(max)`. A migration may alter existing columns. Mitigate by setting compat level <170 or explicitly forcing `nvarchar(max)`. +- **`ExecuteUpdateAsync` signature change.** Column setters now take a regular `Func<…>` (not an expression). Dynamic expression-tree code won’t compile; replace with imperative setters inside the lambda. + +#### Microsoft.Data.Sqlite + +- **`GetDateTimeOffset` (no offset) assumes UTC.** Previously assumed local time. You can temporarily revert via `AppContext.SetSwitch("Microsoft.Data.Sqlite.Pre10TimeZoneHandling", true)`. +- **Writing `DateTimeOffset` to REAL stores UTC.** Conversion now happens before writing; revertable with the same switch. +- **`GetDateTime` (with offset) returns UTC `DateTime` (`DateTimeKind.Utc`).** Was `Local` before. Same temporary switch if needed. + +#### Who’s most affected + +- Apps on **Azure SQL / SQL Server 2025** using JSON mapping. +- Codebases building **expression trees** for bulk updates. +- Apps using **SQLite** with date/time parsing or REAL timestamp storage. + +#### Quick mitigations + +- Set SQL Server compatibility <170 or force column type. +- Rewrite `ExecuteUpdateAsync` callers to use the new delegate form. +- For SQLite, update handling to UTC or use the temporary AppContext switch while transitioning. + +### Containers - Breaking Changes in .NET 10: + +Default .NET images now use [Ubuntu](https://learn.microsoft.com/en-us/dotnet/core/compatibility/containers/10.0/default-images-use-ubuntu). + +### Core Libraries - Breaking Changes in .NET 10: + +[ActivitySource](https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/activity-sampling) behavior tweaks; [generic math](https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/generic-math) shift behavior aligned; W3C trace context is [default](https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/default-trace-context-propagator); [DriveInfo](https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/driveinfo-driveformat-linux) reports Linux FS types; InlineArray size rules tightened; [System.Linq.AsyncEnumerable](https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/asyncenumerable) included in core libs... + +### Cryptography - Breaking Changes in .NET 10: + +[Stricter X500](https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/10.0/x500distinguishedname-validation) name validation; [OpenSSL](https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/10.0/openssl-macos-unsupported) primitives unsupported on macOS; [some key members](https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/10.0/mldsa-slhdsa-secretkey-to-privatekey) nullable/renamed; env var [rename to](https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/10.0/version-override) `DOTNET_OPENSSL_VERSION_OVERRIDE`. + +### Extensions - Breaking Changes in .NET 10: + +[Config preserves](https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/10.0/configuration-null-values-preserved) nulls; [logging](https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/10.0/console-json-logging-duplicate-messages)/[package](https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/10.0/provideraliasattribute-moved-assembly)/trim annotations changes; some [trim-unsafe](https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/10.0/dynamically-accessed-members-configuration) code annotations removed. + +### Globalization & Interop - Breaking Changes in .NET 10: + +[ICU](https://learn.microsoft.com/en-us/dotnet/core/compatibility/globalization/10.0/version-override) env var renamed; single-file apps stop probing executable dir for native libs; [DllImport](https://learn.microsoft.com/en-us/dotnet/core/compatibility/interop/10.0/search-assembly-directory) search path tightened. + +Networking: + +[HTTP/3 disabled ](https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/10.0/http3-disabled-with-publishtrimmed) by default when trimming; [default cert revocation](https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/10.0/ssl-certificate-revocation-check-default) check now Online; [browser clients](https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/10.0/default-http-streaming) stream responses by default; [URI length limits](https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/10.0/uri-length-limits-removed) removed. + +### SDK & MSBuild/NuGet - Breaking Changes in .NET 10: + +`dotnet --interactive` [defaults to true](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-cli-interactive); tool packages are [RID-specific](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-tool-pack-publish); [workload](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/default-workload-config) sets default; `dotnet new sln` uses [SLNX](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-new-sln-slnx-default); restore audits transitives; [local tool](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-tool-install-local-manifest) install creates manifest by default; `project.json` [not supported](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-restore-project-json-unsupported); stricter NuGet [validation](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/nuget-packageid-validation)/[errors](https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/http-warnings-to-errors). + +WinForms/WPF: + +Multiple [API obsoletions](https://learn.microsoft.com/en-us/dotnet/core/compatibility/windows-forms/10.0/obsolete-apis)/parameter [renames](https://learn.microsoft.com/en-us/dotnet/core/compatibility/windows-forms/10.0/insertadjacentelement-orientation); [rendering](https://learn.microsoft.com/en-us/dotnet/core/compatibility/windows-forms/10.0/statusstrip-renderer)/behavior tweaks; stricter XAML rules (e.g., [disallow empty row](https://learn.microsoft.com/en-us/dotnet/core/compatibility/wpf/10.0/empty-grid-definitions)/column definitions or incorrect usage of [DynamicResource](https://learn.microsoft.com/en-us/dotnet/core/compatibility/wpf/10.0/dynamicresource-crash) will crash). + + + +------ + + + +## Support Policy for .NET 10 +As you can see from the picture below, **.NET 10 has long term support** therefore it will be maintained for 3 years **until November 2028**. + +[![.NET 10 Support Policy](image-2.png)](https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core) + + + +## Download .NET10 + +Click 👉 https://dotnet.microsoft.com/en-us/download/dotnet/10.0 to download the latest release candidate (currently RC.1). + +[![Download .NET 10](image-1.png)](https://dotnet.microsoft.com/en-us/download/dotnet/10.0) + +Also to use the latest features, download/update your Visual Studio to the latest 👉 https://visualstudio.microsoft.com/downloads/ + diff --git a/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/cover.png b/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/cover.png new file mode 100644 index 0000000000..e85f53b9ec Binary files /dev/null and b/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/cover.png differ diff --git a/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/image-1.png b/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/image-1.png new file mode 100644 index 0000000000..970f3194bc Binary files /dev/null and b/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/image-1.png differ diff --git a/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/image-2.png b/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/image-2.png new file mode 100644 index 0000000000..6e5b57c588 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/image-2.png differ diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/BenchmarkDotnet.png b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/BenchmarkDotnet.png new file mode 100644 index 0000000000..ed81071118 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/BenchmarkDotnet.png differ diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Disruptor.png b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Disruptor.png new file mode 100644 index 0000000000..d66333865c Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Disruptor.png differ diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/MemoryPack.png b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/MemoryPack.png new file mode 100644 index 0000000000..cdb4f81e38 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/MemoryPack.png differ diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/MessagePack.png b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/MessagePack.png new file mode 100644 index 0000000000..dc7d76dd2f Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/MessagePack.png differ diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Polly.png b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Polly.png new file mode 100644 index 0000000000..18a930df0e Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Polly.png differ diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Post.md b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Post.md new file mode 100644 index 0000000000..5a258da00a --- /dev/null +++ b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Post.md @@ -0,0 +1,161 @@ +# High-Performance .NET Libraries You Didn’t Know You Needed + +Whether you’re building enterprise apps, microservices, or SaaS platforms, using the right libraries can help you ship faster and scale effortlessly. +Here are some **high-performance .NET libraries** you might not know but definitely should. + + + +## 1. BenchmarkDotNet – Measure before you optimize + +![BenchmarkDotnet](BenchmarkDotnet.png) + +BenchmarkDotNet makes it simple to **benchmark .NET code with precision**. + +- Easy setup with `[Benchmark]` attributes +- Generates detailed performance reports +- Works with .NET Core, .NET Framework, and Mono + +Perfect for spotting bottlenecks in APIs, background services, or CPU-bound operations. + +- **NuGet** (40M downloads) 🔗 https://www.nuget.org/packages/BenchmarkDotNet +- **GitHub** (11k stars) 🔗 https://github.com/dotnet/BenchmarkDotNet + +------ + +## 2. MessagePack – Fastest JSON serializer + +Need speed beyond System.Text.Json or Newtonsoft.Json ? MessagePack is the fastest serializer for C# (.NET, .NET Core, Unity, Xamarin). MessagePack has a compact binary size and a full set of general purpose expressive data types. Ideal for high-traffic APIs, IoT data processing, and microservices. + +![MessagePack Benchmark](MessagePack.png) + +- **NuGet** (204M downloads) 🔗 https://www.nuget.org/packages/messagepack +- **GitHub** (6.4K stars) 🔗 https://github.com/MessagePack-CSharp/MessagePack-CSharp + +------ + +## 3. Polly – Resilience at scale + +![Polly](Polly.png) + +In distributed systems, failures are inevitable. **Polly** provides a fluent way to add **retry, circuit-breaker, and fallback** strategies. + +- Handle transient faults gracefully +- Improve uptime and user experience +- Works seamlessly with HttpClient and gRPC + +A must-have for cloud-native .NET applications. + +- **NuGet** (1B downloads) 🔗 https://www.nuget.org/packages/polly/ +- **GitHub** (14K stars) 🔗 https://github.com/App-vNext/Polly + +------ + +## 4. MemoryPack – Zero-cost binary serialization + +If you need **blazing-fast serialization** for in-memory caching or network transport, **MemoryPack** is a game-changer. + +- Zero-copy, zero-alloc serialization +- Perfect for high-performance caching or game servers +- Strongly typed and version-tolerant + +![MemoryPack](MemoryPack.png) + +Great for real-time multiplayer games, chat apps, or financial systems. + +- **NuGet** (5.3M downloads) 🔗 https://www.nuget.org/packages/MemoryPack +- **GitHub** (4K stars) 🔗 https://github.com/Cysharp/MemoryPack + +------ + +## 5. WolverineFx – Ultra-low latency messaging + +![wolverine](wolverine-logo.png) + +MediatR was one of the best mediator library but now it's a paid library. Wolverine is a toolset for command execution and message handling within .NET applications. The killer feature of Wolverine is its very efficient command execution pipeline that can be used as: + +- An [inline "mediator" pipeline](https://wolverinefx.net/tutorials/mediator.html) for executing commands +- A [local message bus](https://wolverinefx.net/guide/messaging/transports/local.html) for in-application communication +- A full-fledged [asynchronous messaging framework](https://wolverinefx.net/guide/messaging/introduction.html) for robust communication and interaction between services when used in conjunction with low level messaging infrastructure tools like RabbitMQ +- With the [WolverineFx.Http](https://wolverinefx.net/guide/http/) library, Wolverine's execution pipeline can be used directly as an alternative ASP.Net Core Endpoint provider + +*Below image is from [codecrash.net](https://www.codecrash.net/2024/02/06/Mediatr-versus-Wolverine-performance.html)* +![WolverineFx](wolverine.png) + +WolverineFx is great for cleanly separating business logic from controllers while unifying in-process mediator patterns with powerful distributed messaging in a single, high-performance .NET library. + +- **NuGet** (1.5M downloads) 🔗 https://www.nuget.org/packages/WolverineFx +- **GitHub** (1.7K stars) 🔗 https://github.com/JasperFx/wolverine + + + +## 6. Disruptor-net – Next generation free .NET mediator + +The Disruptor is a high performance inter-thread message passing framework. A lock-free ring buffer for ultra-low latency messaging. +features are: + +- Zero memory allocation after initial setup (the events are pre-allocated). + +- Push-based consumers. + +- Optionally lock-free. + +- Configurable wait strategies. + +![Disruptor](Disruptor.png) + +- **NuGet** (1.2M downloads) 🔗 https://www.nuget.org/packages/Disruptor/ +- **GitHub** (1.3K stars) 🔗 https://github.com/disruptor-net/Disruptor-net + + + +## 7. CliWrap - Running command-line processes + +![CLIWrap](C:\Users\alper\Desktop\high-perf-dotnet-libs\cliwrap.png) + +CliWrap makes it easy to **run and manage external CLI processes in .NET**. + +- Fluent, task-based API for starting commands +- Streams standard input/output and error in real time +- Supports cancellation, timeouts, and piping between processes + +Ideal for automation, build tools, and integrating external executables. + +- **NuGet** (14.1M downloads) 🔗 https://www.nuget.org/packages/CliWrap +- **GitHub** (4.7K stars) 🔗 https://github.com/Tyrrrz/CliWrap + + + +--- + + + +## Hidden Libs from the Community + +### Sylvan.Csv & **Sep** + +- **Sylvan.Csv**: Up to *10× faster* and *100× less memory allocations* than `CsvHelper`, making CSV processing lightning-fast. ([Reddit](https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com)) +- **Sep**: Even faster than Sylvan, but trades off some flexibility. Great when performance matters more than API richness. ([Reddit](https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com)) + +### String Parsing: **csFastFloat** + +- Parses `float` and `double` around *8–9× faster* than `.Parse` methods—perfect for high-volume parsing tasks. ([Reddit](https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com)) + +### CySharp’s Suite: MemoryPack, MasterMemory, SimdLinq + +- **MemoryPack**: One of the fastest serializers available, with low allocations and high throughput. Ideal for Web APIs or microservices. ([Reddit](https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com)) +- **MasterMemory**: Designed for databases or config storage. Claims *4,700× faster than SQLite* with zero-allocations per query. ([Reddit](https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com)) +- **SimdLinq**: SIMD-accelerated LINQ operations supporting a broader set of methods than .NET's built-in SIMD. Works when slight floating-point differences are acceptable. ([Reddit](https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com)) + +### Jil – JSON Deserializer + +- Ultra-fast JSON (de)serializer with low memory overhead, used in high-scale systems. ([Performance is a Feature!](https://www.mattwarren.org/2014/09/05/stack-overflow-performance-lessons-part-2/?utm_source=chatgpt.com)) + +### StackExchange.NetGain – WebSocket Efficiency + +- High-performance WebSocket server library designed for low-latency IO scenarios. (Now mostly replaced by Kestrel's built-in support, but worth knowing.) ([GitHub](https://github.com/StackExchange/NetGain?utm_source=chatgpt.com)) + +### Math Libraries: Math.NET Numerics & ILNumerics + +- **Math.NET Numerics**: Core numerical methods and matrix math, similar to BLAS/LAPACK. ([Wikipedia](https://en.wikipedia.org/wiki/Math.NET_Numerics?utm_source=chatgpt.com)) +- **ILNumerics**: Efficient numerical arrays with parallelized processing, loop unrolling, cache optimizations. Great for scientific computing. ([Wikipedia](https://en.wikipedia.org/wiki/ILNumerics?utm_source=chatgpt.com)) + diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/cliwrap.png b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/cliwrap.png new file mode 100644 index 0000000000..718d1b558b Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/cliwrap.png differ diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/cover.png b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/cover.png new file mode 100644 index 0000000000..a1b4c825e2 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/cover.png differ diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/wolverine-logo.png b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/wolverine-logo.png new file mode 100644 index 0000000000..b14dc2b7ed Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/wolverine-logo.png differ diff --git a/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/wolverine.png b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/wolverine.png new file mode 100644 index 0000000000..5ef73f0149 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/wolverine.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_1.png b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_1.png new file mode 100644 index 0000000000..9889c8d813 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_1.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_2.png b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_2.png new file mode 100644 index 0000000000..5e00300c81 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_2.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_3.png b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_3.png new file mode 100644 index 0000000000..3675376cb3 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_3.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_4.png b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_4.png new file mode 100644 index 0000000000..e0b94bb47c Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_4.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_5.png b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_5.png new file mode 100644 index 0000000000..4ed8c4eabe Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_5.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_6.png b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_6.png new file mode 100644 index 0000000000..ad2640da1f Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_6.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_7.png b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_7.png new file mode 100644 index 0000000000..cfdf76ea7e Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_7.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_8.png b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_8.png new file mode 100644 index 0000000000..f399892ee8 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_8.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_9.png b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_9.png new file mode 100644 index 0000000000..171ff61851 Binary files /dev/null and b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/images/img_9.png differ diff --git a/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/post.md b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/post.md new file mode 100644 index 0000000000..cfd4db30bf --- /dev/null +++ b/docs/en/Community-Articles/2025-09-11-Web-Design-Basics-for-Graphic-Designers-Who-Dont-Code/post.md @@ -0,0 +1,282 @@ +# Web Design Basics for Graphic Designers Who Don't Code + +## Introduction + +As a **designer**, I have been working on **logos**, **posters**, and **social media announcement** **visuals** for years. However, when it comes to the web, I used to hold back saying “I **don’t know how to code**.” We have all thought about this at some point and unfortunately, we still think about it from time to time. + +🚀 **Good news**: We can learn **web design** without writing code and design **user-friendly**, **aesthetic, and functional web interfaces** using basic knowledge. + +In this article, we will talk about the **basics of web design**, its **differences from graphic design**, and whether it is possible to do **web design without knowing how to code**. + +## Differences Between Graphic Design & Web Design + +![](images/img_2.png) + +### What is Graphic Design? + +Graphic design is creating **visual content** that conveys a message to a **specific audience**. Graphic designers use various **visual elements** such as **color**, **typography**, **imagery**, and **layout** to communicate a message effectively. They work on a wide range of projects, including **logos**, **websites**, **packaging**, **advertisements, and branding**. + +### What is Web Design? + +Web design is the process of creating a website that can be viewed on computers or mobile devices. Like graphic design, web design also involves creating **graphics**, **typography**, **and visuals**, but they use the **internet** as the communication channel. + +### Graphic Design + +* Graphic Design is concerned with **visuals** and **appearance**. +* Graphic design focuses on visually conveying specific messages or ideas through **typography**, **visuals**, **colors**, and i**llustrations**. +* Graphic design focuses on how objects **look**. +* Graphic designers **do not need coding knowledge**. +* Graphic design is **static**. + +### Web Design + +* Web design is user experience–focused. +* Web design aims to create **functional** and **user-friendly** **websites** that provide the **best experience** for users. +* Web design considers **search engine optimization** when creating websites. +* Web designers need to have **knowledge of HTML**, **CSS**, and other web development languages to create **functional and responsive designs**. +* Web design is **dynamic**. + +## Fundamental Principles of Web Design (Applicable Without Coding) + +Companies and **brands** from almost every sector request the **creation of their own websites**. This way, they gain the opportunity to introduce their **services**, **prices**, and themselves to their **target audiences**. However, for this to have the desired effect, the website must be **designed properly**. What are the **fundamental principles** to pay attention to when designing a website? Now, it’s time to answer this question by introducing the basics. Here are the **indispensable principles in web design**. + + ### 1\) User-Centered Designs: + +Users always value **ease and practicality** when receiving a service. For this reason, it is important for websites to be designed in a user-centered way. **Easy to find menus**, **fast usage**, and the **easy to locate any information** are very important. With **user centered design**, it is possible to create websites that are **easy to use** and also **satisfy users**. + + + ### 2\) Responsive Designs: + +It is very important for the website and its design to be **usable on every digital platform**. Therefore, the designed sites must have a **responsive design**. This means easy access to the site on a **phone**, **tablet**, or **computer**. This also ensures that users continue to prefer the site. + + ### 3\) Visual Hierarchy: + +The page must have **visuals related to itself**, and **product content** should be matched with the **correct visuals**. It is also very important for visual elements to be placed according to their order of importance. On web pages, content compatible with visuals must be provided with **sufficient and accurate information**. + + ### 4\) Color and Typography Selection: + +Color and typography selection is very important for handling visuals, colors, and text in a certain **harmony**. For the site to **attract attention** or for the relevant pages to achieve the expected interaction, the use of color and the chosen font style and font color must be harmonious. A design that is both **easy to read** and **eye catching** without causing any disturbance should be preferred. + + ### 5\) Content and Layout Structure: + +One of the most desired features on web pages is **content organization**. Content that is **unrelated to the pages, creates confusion while reading**, or **lacks simplicity**, such as overly frequent paragraphs, incorrect fonts, and similar factors, causes web pages to have less impact. **Content structure** also includes **placing related topics sequentially** and **adding them to the menu**. For example, on a website created for shoes, if shoe types are grouped separately, users find it easier. Options like high heels, sandals, and sneakers help users find what they are looking for more easily, which in turn ensures positive site feedback. + + ### 6\) Speed Optimization: + +As with every type of service, speed is very important for services provided through web pages. Easy navigation between pages, error-free performance, and ease of use are very important for users. No one wants to shop or use a service on a website that takes a long time to load, because everyone prefers websites to save time. + + ### 7\) Consistency: + +For a service to be preferred, it must first be reliable. This is directly related to the information, visuals, and everything on the website. The information in the content, visuals, and content details must be consistent and should not raise any questions in visitors’ minds. Otherwise, negative feedback can later affect customer preferences and damage the brand image. + +## Is It Possible to Do Web Design Without Coding? + +In the past, it was not possible to create a website without at least some basic coding knowledge. However, today, almost anyone can build a website. Even if you have not written a **single line of code**. + +The biggest helpers for those who want to do **web development without coding** are **No-Code** and **Low-Code** platforms. These tools help users **design websites** without dealing with **technical details**. + +Systems like **Wix**, **Webflow**, **Shopify**, and **WordPress** are very common in this area. + +![](images/img_3.png) + +The web development process on these platforms is carried out through practical methods such as **drag-and-drop**, selecting **ready-made templates**, and filling out forms. + +### **No Code** + +As the name suggests, it allows you to create websites, mobile applications, automations, and workflows **without writing a single line of code**. + +* **How Does It Work**? They usually have a visual editor. You create the skeleton of your application by dragging and dropping ready “building blocks” such as buttons, forms, and visuals onto your canvas. Then, you determine what these elements will do (for example, “go to this page when this button is clicked”) by selecting options from the menus. +* **Who Uses It**? It is perfect for entrepreneurs, marketers, product managers, designers, and anyone who wants to quickly test an idea. +* **Examples**: Platforms like Webflow, Bubble, Adalo, and Glide allow you to create a wide range of products, from complex web applications to mobile apps. + +### **Low Code** + +Low-Code systems require a bit more **technical knowledge** but still **do not require learning full-scale programming**. + +* **How Does It Work**? You handle 80% of the work with drag-and-drop, and for the remaining 20% that requires customization, you add small code snippets. +* **Who Uses It**? It is generally preferred by IT departments of corporate companies and technical teams that want to develop more complex, scalable applications. +* **Examples**: Platforms like OutSystems and Mendix are used to build large, integrated systems that manage a company’s internal processes. + +## What Should the Web Design Process be Like? + +![](images/img_4.png) + +**Web design** is a passionate field but can be **overwhelming** at times. When starting out, coming up with a plan on how to tackle your website or a web app idea often feels daunting: Where should you begin?Web designers often think about the **web design process** with a focus on **technical matters** such as wireframes, code, and content management. But great + +design isn’t about how you integrate the social media buttons or even slick visuals. **Great design** is actually about having **a website creation process** that aligns with an **overarching strategy.** + +Doing all the thinking beforehand ensures that you don’t forget anything crucial. It also frees up headspace for doing the actual work, avoids overwhelm, improves efficiency, and allows you to build better websites on repeat. + +But how do you achieve that harmonious synthesis of elements? Through a **holistic web design** process that takes both **form and function** into account. + +We have already covered the fundamentals, now, I'll share the steps to an **effective web design process.** + +Let's get started. + +### 1\) Goal Identification + +In this **initial stage**, the designer needs to identify the end goal of the website design, usually in close collaboration with the client or other stakeholders. Questions to explore and answer in this stage of the design and website development process include: + +* Who is the site for? +* What do they hope to find or do there? +* Is the main purpose of this website to inform, to sell (e-commerce, for everyone?), or to entertain? +* Does the website need to clearly convey the **brand's core message**, or is it part of a broader **brand strategy** with its own unique focus? +* If there are any, which **competitor sites** exist, and how should this site be **inspired by them** / how should it differ from them? + +To have clear answers to above questions will lead to the **successful execution** of the project. + +### What Purpose Will the Website Serve? + +Whatever the project you’re taking on, you always want each and every initiative you take to achieve the goals you’ve set for it. **Goal setting is critical** because it will be key in making decisions throughout the project by asking yourself the right questions and **prioritizing tasks and efforts**. + +As basic as it may seem, following the **SMART framework** is always a great idea when setting your goals, to **ensure effectiveness:** + +**S \- SPECIFIC** +Your goal is direct, detailed, and meaningful. + +**M \- MEASURABLE** +Your goal is quantifiable to track progress or success. + +**A \- ATTAINABLE** +Your goal is realistic and you have the tools and/or resources to attain it. + +**R \- RELEVANT** +Your goal aligns with your company mission. + +**T \- TIME-BASED** +Your goal has a deadline. + +### 2\) Scope Definition + +This is easier said than done when starting out, so it is best to approach it with caution : Everyone has once been guilty of saying a project “will be done by next week” before realizing they dramatically **underestimated** how hard it would be. + +Nevertheless, **setting** a timeline will help a lot with **accountability**, both internal and external, and will help **break down the project in distinct stages**. + +You don’t have to reinvent anything from scratch, as a lot of tools such as Airtable’s timeline view will help you put the timeline together. + +![](images/img_5.png) + +Source: [Airtable](https://blog.airtable.com/introducing-airtables-new-timeline-view/) + +### 3\) Sitemap and Wireframe Creation + +The site map forms the foundation of a well-designed website. It gives web designers a clear idea of the **information architecture** of the website and explains the **relationships** between various **pages and content elements**. + +![](images/img_6.png) + +Building a web site without a site map is like building a house without a plan. And it rarely ends well. + +Time to start building the first iteration of your project\! To put it shortly, **wireframes** serve as a blueprint, a visual guide representing the skeletal framework of a website or application. It will be a raw version of your project, a great way to get your **initial idea down** in its first “physical” form. + +![](images/img_7.png) + +Source: [Afolayan Daniel](https://medium.com/fbdevclagos/4-reasons-why-wire-frame-is-important-during-website-or-mobile-app-development-46fabdf47190) + +While it won’t be functional yet, it’ll be a major web design step to share with your team, potential leads or even investors, and will highlight issues that you might not have thought about previously. Wireframes are a great opportunity to move fast, once they’re ready, you’ll be able to: + +* Gather early feedback; +* Run UX testing groups; +* Iterate on your timeline if necessary; +* Get concept validation. + +There are different ways to create wireframes. You can of course sketch them out on paper to start with, but creating a digital version will eventually be much more practical to share them. + +#### Tools for sitemapping and wireframing; + +* Pen/pencil and paper. +* Balsamiq. +* Moqups. +* Sketch. +* Axure. +* Webflow. +* Slickplan. +* Writemaps. +* Mindnode. +* Figma. +* Sketch. + +### 4\) Content Creation +A website should offer more than just a simple design and attractive graphics. An effective content strategy is essential to capture users’ interest and to make the site stand out in search engines. + +![](images/img_8.png) +When it comes to content, search engine optimization is only +half of the battle. + +There are two main goals that you need to focus on while creating content. + +#### **Goal 1 Content encourages engagement and action:** + +First of all, content drives readers to take action and encourages them to perform the actions necessary to achieve a site's goals. This is influenced both by the content itself (writing) and by the way it is presented (typography and structural elements). + +Boring, lifeless, and lengthy writing rarely holds visitors' attention for long enough. Short, fluent, and engaging content captures them and makes them click through to other pages. Even if your pages need a lot of content (which they often do), properly "breaking it up" into short paragraphs supported by visuals can help create a light and engaging feel. + +#### **Goal 2 Search Engine Optimization**: + +Content also increases a site's visibility in the eyes of search engines. The practice of creating and developing content to achieve a good ranking in search results is called search engine optimization or SEO. + +Identifying your keywords and key phrases correctly is very important for the success of any website. + +### 5\) Visual Elements + +![](images/img_9.png) + +Style Tile: a free style tile / moodboard template built by Mat Vogels. + +It is time to create the **visual style** of the site. This part of the design process is usually shaped by **existing brand elements, color choices**, and **logos** specified by the client. However, it is also the stage of the web design process where a **good web designer can truly shine**. + +**Visuals play a more important** **role** in web design than ever before. High quality visuals not only give a website a professional look and feel, but also convey a message, are mobile friendly, and help build trust. + +**Visual design is a way of communicating** with the web site users to make the site as **appealing to them** as possible. When done right, it can determine the site’s being one of the major successes amongst competitors. On the other hand, any mistake might put it in risk of becoming just another ordinary web site. + +**Tools for visual elements**: + +* (Sketch, Illustrator, Photoshop, Figma, vb.) +* Visual Style Guides. + + + +### 6\) Development & Platforms + +**Front-End Development**: The parts that users interact with (HTML, CSS, JavaScript). + +**Back-End Developmen**t: Database and server-side processes (PHP, Python, Node.js). + +**No-Code Platforms**: Publishing on platforms like Webflow, Bubble, Adalo, Glide. + +### 7\) Testing + +When your site has all the visuals and content, you are ready to test. +Once the **first iteration** of your website/web app is ready, it’s time for some **testing** to make sure it **runs smoothly**. + +A website should undergo a detailed testing process before going live. +Items to check during the testing process: + +* Mobile Compatibility. +* Functionality across different browsers. +* Functionality of forms and buttons. + +Alongside these steps, setting up website uptime monitoring is essential to ensure the site remains functional after launch, providing immediate alerts if any downtime occurs. Ultimately, while testing is an important part of the web design process, it’s not worth losing sleep over. **Done is always better than perfect** and when in doubt, keep this quote in mind. + +*“If you are not embarrassed by the first version of your product, you've launched too late.” \- Reid Hoffman, founder of LinkedIn* + +### 8\) Website Launch + +Now it’s time for everyone’s favorite part of the website design process: When everything has been thoroughly tested and you’re happy with the site, you can start. + +Don’t expect this to go perfectly. There may still be some elements that need fixing. Web design is a fluid and ongoing process that requires constant maintenance. + +Web design and design in general is about finding the right balance between form and function. You need to use the right fonts, colors, and design motifs. But the way users navigate and experience your site is just as important. + +## Conclusion + +Previously, when we wanted to turn our designs into reality, the barrier of learning and using a programming language tool stood in our way. This barrier has now been removed thanks to **No-Code tools**. With these tools, even without coding knowledge, there is now a way to bring your designs to life. + +## Resources + +* Bulut, B. (2025, July 20). *Kod yazmayı bilmeden yazılımcı olmak nasıl mümkün oldu?* Webtekno. [https://www.webtekno.com/kod-bilmeden-yazilimci-olmak-nasil-mumkun-oldu-h159799.html](https://www.webtekno.com/kod-bilmeden-yazilimci-olmak-nasil-mumkun-oldu-h159799.html) + +* Ectasarim. (2024, Kasım 10). *Web tasarım ilkeleri nelerdir? Önemli hususlar*. [https://www.ectasarim.com/web-tasarim-ilkeleri/](https://www.ectasarim.com/web-tasarim-ilkeleri/?utm_source=chatgpt.com) + +* Meazey, M. (2020, February 12). *The web design process in 7 simple steps*. *Webflow Blog*. [https://webflow.com/blog/the-web-design-process-in-7-simple-steps](https://webflow.com/blog/the-web-design-process-in-7-simple-steps) + +* University of California Office of the President. (2016). *How to write SMART goals: A how-to guide.* University of California. [https://www.ucop.edu/local-human-resources/\_files/performance-appraisal/How+to+write+SMART+Goals+v2.pdf](https://www.ucop.edu/local-human-resources/_files/performance-appraisal/How+to+write+SMART+Goals+v2.pdf) diff --git a/docs/en/framework/fundamentals/localization.md b/docs/en/framework/fundamentals/localization.md index 6e8a3f678a..47c4ca564a 100644 --- a/docs/en/framework/fundamentals/localization.md +++ b/docs/en/framework/fundamentals/localization.md @@ -91,6 +91,34 @@ A JSON localization file content is shown below: > ABP will ignore (skip) the JSON file if the `culture` section is missing. +You can also use nesting or array in localization files, like this: + +````json +{ + "culture": "en", + "texts": { + "HelloWorld": "Hello World!", + "Hello": { + "World": "Hello World!" + }, + "Hi":[ + "Bye": "Bye World!" + "Hello": "Hello World!" + ] + } +} +```` + +Then you can use it like this: + +> The double underscore (`__`) is used to separate the parent key from the child key. + +````csharp +var str = L["Hello__World"]; // Hello World! +var str2 = L["Hi__0"]; // Bye World! +var str3 = L["Hi__1"]; // Hello World! +```` + ### Default Resource `AbpLocalizationOptions.DefaultResourceType` can be set to a resource type, so it is used when the localization resource was not specified: diff --git a/docs/en/release-info/migration-guides/AutoMapper-To-Mapperly.md b/docs/en/release-info/migration-guides/AutoMapper-To-Mapperly.md index 11112e2bc6..7356a6930b 100644 --- a/docs/en/release-info/migration-guides/AutoMapper-To-Mapperly.md +++ b/docs/en/release-info/migration-guides/AutoMapper-To-Mapperly.md @@ -56,7 +56,7 @@ public class ExampleAutoMapper : Profile And the Mapperly mapping class: ```csharp -[Mapper] +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] [MapExtraProperties] public partial class IdentityUserToIdentityUserDtoMapper : MapperBase { @@ -71,7 +71,7 @@ public partial class IdentityUserToIdentityUserDtoMapper : MapperBase { public override partial IdentityUserClaimDto Map(IdentityUserClaim source); @@ -79,7 +79,7 @@ public partial class IdentityUserClaimToIdentityUserClaimDtoMapper : MapperBase< public override partial void Map(IdentityUserClaim source, IdentityUserClaimDto destination); } -[Mapper] +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] [MapExtraProperties] public partial class OrganizationUnitToOrganizationUnitDtoMapper : MapperBase { @@ -87,7 +87,7 @@ public partial class OrganizationUnitToOrganizationUnitDtoMapper : MapperBase { public override partial OrganizationUnitRoleDto Map(OrganizationUnitRole source); @@ -97,7 +97,7 @@ public partial class OrganizationUnitRoleToOrganizationUnitRoleDtoMapper : TwoWa public override partial void ReverseMap(OrganizationUnitRoleDto destination, OrganizationUnitRole source); } -[Mapper] +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] [MapExtraProperties] public partial class OrganizationUnitToOrganizationUnitWithDetailsDtoMapper : MapperBase { @@ -110,7 +110,7 @@ public partial class OrganizationUnitToOrganizationUnitWithDetailsDtoMapper : Ma public override partial void Map(OrganizationUnit source, OrganizationUnitWithDetailsDto destination); } -[Mapper] +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] public partial class IdentityRoleToOrganizationUnitRoleDtoMapper : MapperBase { [MapProperty(nameof(IdentityRole.Id), nameof(OrganizationUnitRoleDto.RoleId))] @@ -120,7 +120,7 @@ public partial class IdentityRoleToOrganizationUnitRoleDtoMapper : MapperBase { [MapperIgnoreTarget(nameof(IdentityUserExportDto.Roles))] @@ -143,7 +143,7 @@ public partial class IdentityUserToIdentityUserExportDtoMapper : MapperBase { public IdentityUserToIdentityUserDtoMapper(MyService myService) @@ -173,6 +174,170 @@ public partial class IdentityUserToIdentityUserDtoMapper : MapperBase AI may generate some code that is not correct. Please check the code carefully. + +``` +Please help me migrate AutoMapper Profile classes to Mapperly. I have AutoMapper Profile files in my current workspace/context that need to be converted. + +**Conversion Requirements:** + +1. **Convert AutoMapper Profile to Mapperly Mappers**: Transform each `CreateMap` into a separate Mapperly mapper class +2. **Rename the file**: Change from `XXXAutoMapperProfile.cs` to `XXXMappers.cs` +3. **Use proper Mapperly attributes**: + - `[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]` for each mapper class + - `[MapExtraProperties]` for classes that need extra properties mapping + - `[MapperIgnoreTarget]` for ignored properties + - `[MapProperty]` for custom property mappings +4. **Inherit from appropriate base classes**: + - `MapperBase` for one-way mapping + - `TwoWayMapperBase` for reverse mapping +5. **Handle complex mappings**: Use `AfterMap` method for complex transformations + +**Note:** The code below contains two parts - both are reference examples for you to understand the conversion pattern: +1. **AutoMapper Profile example** - shows the original AutoMapper code structure +2. **Mapperly Mappers example** - shows the expected converted Mapperly code structure + +Please convert the actual AutoMapper Profile files that exist in your current context/workspace, following the same conversion pattern as shown in these examples. + +**Reference Examples:** + +**1. AutoMapper Profile (original code):** + +using System; +using AutoMapper; +using System.Linq; +using Volo.Abp.AutoMapper; + +namespace Volo.Abp.Identity; + +public class ExampleAutoMapperProfile : Profile +{ + public ExampleAutoMapperProfile() + { + CreateMap() + .MapExtraProperties() + .Ignore(x => x.IsLockedOut) + .Ignore(x => x.SupportTwoFactor) + .Ignore(x => x.RoleNames); + + CreateMap(); + + CreateMap() + .MapExtraProperties(); + + CreateMap() + .ReverseMap(); + + CreateMap() + .ForMember(dest => dest.RoleId, src => src.MapFrom(r => r.Id)); + + CreateMap() + .ForMember(dest => dest.Active, src => src.MapFrom(r => r.IsActive ? "Yes" : "No")) + .ForMember(dest => dest.EmailConfirmed, src => src.MapFrom(r => r.EmailConfirmed ? "Yes" : "No")) + .ForMember(dest => dest.TwoFactorEnabled, src => src.MapFrom(r => r.TwoFactorEnabled ? "Yes" : "No")) + .ForMember(dest => dest.AccountLookout, src => src.MapFrom(r => r.LockoutEnd != null && r.LockoutEnd > DateTime.UtcNow ? "Yes" : "No")) + .Ignore(x => x.Roles); + } +} + +--- + +**2. Mapperly Mappers (converted code):** + +using System; +using System.Linq; +using Riok.Mapperly.Abstractions; +using Volo.Abp.Mapperly; + +namespace Volo.Abp.Identity; + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +[MapExtraProperties] +public partial class IdentityUserToIdentityUserDtoMapper : MapperBase +{ + [MapperIgnoreTarget(nameof(IdentityUserDto.IsLockedOut))] + [MapperIgnoreTarget(nameof(IdentityUserDto.SupportTwoFactor))] + [MapperIgnoreTarget(nameof(IdentityUserDto.RoleNames))] + public override partial IdentityUserDto Map(IdentityUser source); + + [MapperIgnoreTarget(nameof(IdentityUserDto.IsLockedOut))] + [MapperIgnoreTarget(nameof(IdentityUserDto.SupportTwoFactor))] + [MapperIgnoreTarget(nameof(IdentityUserDto.RoleNames))] + public override partial void Map(IdentityUser source, IdentityUserDto destination); +} + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +public partial class IdentityUserClaimToIdentityUserClaimDtoMapper : MapperBase +{ + public override partial IdentityUserClaimDto Map(IdentityUserClaim source); + + public override partial void Map(IdentityUserClaim source, IdentityUserClaimDto destination); +} + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +[MapExtraProperties] +public partial class OrganizationUnitToOrganizationUnitDtoMapper : MapperBase +{ + public override partial OrganizationUnitDto Map(OrganizationUnit source); + public override partial void Map(OrganizationUnit source, OrganizationUnitDto destination); +} + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +public partial class OrganizationUnitRoleToOrganizationUnitRoleDtoMapper : TwoWayMapperBase +{ + public override partial OrganizationUnitRoleDto Map(OrganizationUnitRole source); + public override partial void Map(OrganizationUnitRole source, OrganizationUnitRoleDto destination); + + public override partial OrganizationUnitRole ReverseMap(OrganizationUnitRoleDto destination); + public override partial void ReverseMap(OrganizationUnitRoleDto destination, OrganizationUnitRole source); +} + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +[MapExtraProperties] +public partial class OrganizationUnitToOrganizationUnitWithDetailsDtoMapper : MapperBase +{ + [MapperIgnoreTarget(nameof(OrganizationUnitWithDetailsDto.Roles))] + [MapperIgnoreTarget(nameof(OrganizationUnitWithDetailsDto.UserCount))] + public override partial OrganizationUnitWithDetailsDto Map(OrganizationUnit source); + + [MapperIgnoreTarget(nameof(OrganizationUnitWithDetailsDto.Roles))] + [MapperIgnoreTarget(nameof(OrganizationUnitWithDetailsDto.UserCount))] + public override partial void Map(OrganizationUnit source, OrganizationUnitWithDetailsDto destination); +} + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +public partial class IdentityRoleToOrganizationUnitRoleDtoMapper : MapperBase +{ + [MapProperty(nameof(IdentityRole.Id), nameof(OrganizationUnitRoleDto.RoleId))] + public override partial OrganizationUnitRoleDto Map(IdentityRole source); + + [MapProperty(nameof(IdentityRole.Id), nameof(OrganizationUnitRoleDto.RoleId))] + public override partial void Map(IdentityRole source, OrganizationUnitRoleDto destination); +} + +[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)] +public partial class IdentityUserToIdentityUserExportDtoMapper : MapperBase +{ + [MapperIgnoreTarget(nameof(IdentityUserExportDto.Roles))] + public override partial IdentityUserExportDto Map(IdentityUser source); + + [MapperIgnoreTarget(nameof(IdentityUserExportDto.Roles))] + public override partial void Map(IdentityUser source, IdentityUserExportDto destination); + + public override void AfterMap(IdentityUser source, IdentityUserExportDto destination) + { + destination.Active = source.IsActive ? "Yes" : "No"; + destination.EmailConfirmed = source.EmailConfirmed ? "Yes" : "No"; + destination.TwoFactorEnabled = source.TwoFactorEnabled ? "Yes" : "No"; + destination.AccountLookout = source.LockoutEnd != null && source.LockoutEnd > DateTime.UtcNow ? "Yes" : "No"; + } +} +``` + ## Mapperly Documentation Please refer to the [Mapperly documentation](https://mapperly.riok.app/docs/intro/) for more details. diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs index 803f208d8a..1791a5e928 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddModuleCommand.cs @@ -69,6 +69,7 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency var newProTemplate = !string.IsNullOrEmpty(template) && template == ModuleProTemplate.TemplateName; var withSourceCode = newTemplate || newProTemplate || commandLineArgs.Options.ContainsKey(Options.SourceCode.Long); var addSourceCodeToSolutionFile = withSourceCode && commandLineArgs.Options.ContainsKey("add-to-solution-file"); + var skipOpeningDocumentation = commandLineArgs.Options.ContainsKey(Options.SkipOpeningDocumentation.Long); var skipDbMigrations = newTemplate || newProTemplate || commandLineArgs.Options.ContainsKey(Options.DbMigrations.Skip); var solutionFile = GetSolutionFile(commandLineArgs); @@ -98,7 +99,8 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency withSourceCode, addSourceCodeToSolutionFile, newTemplate, - newProTemplate + newProTemplate, + skipOpeningDocumentation ); _lastAddedModuleInfo = new AddModuleInfoOutput @@ -223,5 +225,10 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency public const string Short = "t"; public const string Long = "template"; } + + public class SkipOpeningDocumentation + { + public const string Long = "skip-opening-documentation"; + } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularSourceCodeAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularSourceCodeAdder.cs index f996247217..aecc1ad222 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularSourceCodeAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularSourceCodeAdder.cs @@ -14,11 +14,11 @@ namespace Volo.Abp.Cli.ProjectModification; public class AngularSourceCodeAdder : ITransientDependency { - public ILogger Logger { get; set; } + public ILogger Logger { get; set; } public AngularSourceCodeAdder() { - Logger = NullLogger.Instance; + Logger = NullLogger.Instance; } public async Task AddFromModuleAsync(string solutionFilePath, string angularPath) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs index 1c6a2abd3f..8a703a8deb 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs @@ -98,7 +98,8 @@ public class SolutionModuleAdder : ITransientDependency bool withSourceCode = false, bool addSourceCodeToSolutionFile = false, bool newTemplate = false, - bool newProTemplate = false) + bool newProTemplate = false, + bool skipOpeningDocumentation = false) { Check.NotNull(solutionFile, nameof(solutionFile)); Check.NotNull(moduleName, nameof(moduleName)); @@ -159,10 +160,13 @@ public class SolutionModuleAdder : ITransientDependency await SetLeptonXAbpVersionsAsync(solutionFile, Path.Combine(modulesFolderInSolution, module.Name)); } - var documentationLink = module.GetFirstDocumentationLinkOrNull(); - if (documentationLink != null) + if (!skipOpeningDocumentation) { - CmdHelper.Open(documentationLink); + var documentationLink = module.GetFirstDocumentationLinkOrNull(); + if (documentationLink != null) + { + CmdHelper.Open(documentationLink); + } } return module; diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs index bf017d041e..85c47c738d 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs @@ -26,6 +26,16 @@ public class ObjectToInferredTypesConverter : JsonConverter public override void Write( Utf8JsonWriter writer, object objectToWrite, - JsonSerializerOptions options) => - JsonSerializer.Serialize(writer, objectToWrite, objectToWrite.GetType(), options); + JsonSerializerOptions options) + { + var runtimeType = objectToWrite.GetType(); + if (runtimeType == typeof(object)) + { + writer.WriteStartObject(); + writer.WriteEndObject(); + return; + } + + JsonSerializer.Serialize(writer, objectToWrite, runtimeType, options); + } } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs index e4b66148a5..f065f0e695 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text.Json; using Microsoft.Extensions.Localization; @@ -47,12 +48,11 @@ public static class JsonLocalizationDictionaryBuilder { throw new AbpException("Can not parse json string. " + ex.Message); } - if (jsonFile == null) { return null; } - + var cultureCode = jsonFile.Culture; if (string.IsNullOrEmpty(cultureCode)) { @@ -61,18 +61,17 @@ public static class JsonLocalizationDictionaryBuilder var dictionary = new Dictionary(); var dublicateNames = new List(); - foreach (var item in jsonFile.Texts) + + foreach (var item in FlattenTexts(jsonFile.Texts)) { if (string.IsNullOrEmpty(item.Key)) { throw new AbpException("The key is empty in given json string."); } - if (dictionary.GetOrDefault(item.Key) != null) { dublicateNames.Add(item.Key); } - dictionary[item.Key] = new LocalizedString(item.Key, item.Value.NormalizeLineEndings()); } @@ -85,4 +84,67 @@ public static class JsonLocalizationDictionaryBuilder return new StaticLocalizationDictionary(cultureCode, dictionary); } + + private static Dictionary FlattenTexts(Dictionary texts, string prefix = "") + { + var result = new Dictionary(); + foreach (var text in texts) + { + var currentKey = string.IsNullOrEmpty(prefix) ? text.Key : $"{prefix}__{text.Key}"; + switch (text.Value) + { + case JsonElement jsonElement: + foreach (var item in FlattenJsonElement(jsonElement, currentKey)) + { + result[item.Key] = item.Value; + } + break; + case string str: + result[currentKey] = str; + break; + case null: + result[currentKey] = ""; + break; + default: + result[currentKey] = text.Value.ToString() ?? ""; + break; + } + } + return result; + } + + private static IEnumerable> FlattenJsonElement(JsonElement element, string prefix) + { + switch (element.ValueKind) + { + case JsonValueKind.String: + yield return new KeyValuePair(prefix, element.GetString() ?? ""); + break; + case JsonValueKind.Object: + foreach (var prop in element.EnumerateObject()) + { + var newKey = $"{prefix}__{prop.Name}"; + foreach (var item in FlattenJsonElement(prop.Value, newKey)) + { + yield return item; + } + } + break; + case JsonValueKind.Array: + var i = 0; + foreach (var prop in element.EnumerateArray()) + { + var newKey = $"{prefix}__{i}"; + foreach (var item in FlattenJsonElement(prop, newKey)) + { + yield return item; + } + i++; + } + break; + default: + yield return new KeyValuePair(prefix, element.ToString()); + break; + } + } } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs index 8470e2696f..337a03a31e 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationFile.cs @@ -9,10 +9,5 @@ public class JsonLocalizationFile /// public string Culture { get; set; } = default!; - public Dictionary Texts { get; set; } - - public JsonLocalizationFile() - { - Texts = new Dictionary(); - } + public Dictionary Texts { get; set; } = []; } diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/ObjectToInferredTypesConverter_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/ObjectToInferredTypesConverter_Tests.cs new file mode 100644 index 0000000000..b5d5c3b394 --- /dev/null +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/ObjectToInferredTypesConverter_Tests.cs @@ -0,0 +1,54 @@ +using System.Text.Json; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Json; + +public class ObjectToInferredTypesConverter_Tests : AbpJsonSystemTextJsonTestBase +{ + private readonly IJsonSerializer _jsonSerializer; + + public ObjectToInferredTypesConverter_Tests() + { + _jsonSerializer = GetRequiredService(); + } + + [Fact] + public void Test() + { + var objString = _jsonSerializer.Serialize(new object()); + objString.ShouldBe("{}"); + var obj = _jsonSerializer.Deserialize(objString); + obj.ShouldBeOfType(); + + var booleanString = _jsonSerializer.Serialize(true); + booleanString.ShouldBe("true"); + var boolean = _jsonSerializer.Deserialize(booleanString); + boolean.ShouldBe(true); + + var booleanString2 = _jsonSerializer.Serialize(false); + booleanString2.ShouldBe("false"); + var boolean2 = _jsonSerializer.Deserialize(booleanString2); + boolean2.ShouldBe(false); + + var numberString = _jsonSerializer.Serialize(1); + numberString.ShouldBe("1"); + var number = _jsonSerializer.Deserialize(numberString); + number.ShouldBe(1); + + var numberString2 = _jsonSerializer.Serialize(1.1); + numberString2.ShouldBe("1.1"); + var number2 = _jsonSerializer.Deserialize(numberString2); + number2.ShouldBe(1.1); + + var dateString = _jsonSerializer.Serialize(System.DateTime.Parse("2024-01-01")); + dateString.ShouldBe("\"2024-01-01T00:00:00\""); + var date = _jsonSerializer.Deserialize(dateString); + date.ShouldBe(System.DateTime.Parse("2024-01-01")); + + var textString = _jsonSerializer.Serialize("text"); + textString.ShouldBe("\"text\""); + var text = _jsonSerializer.Deserialize(textString); + text.ShouldBe("text"); + } +} diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs index e5262bc8a2..189c1b8614 100644 --- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs +++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs @@ -196,7 +196,7 @@ public class AbpLocalization_Tests : AbpIntegratedTest x.Permissions).All(p => p.IsGranted); await InvokeAsync(_modal.Show); } @@ -76,17 +73,14 @@ public partial class PermissionManagementModal protected virtual async Task GrantAllAsync(bool grantAll) { GrantAll = grantAll; - + if (_allGroups == null) { return; } - - _grantedPermissionCount = 0; - _notGrantedPermissionCount = 0; await OnPermissionGroupSearchTextChangedAsync(string.Empty); - + foreach (var permission in _allGroups.SelectMany(x => x.Permissions)) { if (IsDisabledPermission(permission)) @@ -95,49 +89,28 @@ public partial class PermissionManagementModal } permission.IsGranted = grantAll; - - if (grantAll) - { - _grantedPermissionCount++; - } - else - { - _notGrantedPermissionCount++; - } } - + await InvokeAsync(StateHasChanged); } - + protected virtual void NormalizePermissionGroup(bool checkDisabledPermissions = true) { _selectAllDisabled = _groups.All(IsPermissionGroupDisabled); - _grantedPermissionCount = 0; - _notGrantedPermissionCount = 0; if (checkDisabledPermissions) { _disabledPermissions.Clear(); } - + foreach (var permission in _groups.SelectMany(x => x.Permissions)) { if (checkDisabledPermissions && permission.IsGranted && permission.GrantedProviders.All(x => x.ProviderName != _providerName)) { _disabledPermissions.Add(permission); - continue; - } - - if (permission.IsGranted) - { - _grantedPermissionCount++; - } - else - { - _notGrantedPermissionCount++; } } - + foreach (var group in _groups) { SetPermissionDepths(group.Permissions, null, 0); @@ -210,7 +183,7 @@ public partial class PermissionManagementModal return _permissionDepths.GetValueOrDefault(name, 0); } - protected virtual void GroupGrantAllChanged(bool value, PermissionGroupDto permissionGroup) + protected virtual async Task GroupGrantAllChanged(bool value, PermissionGroupDto permissionGroup) { foreach (var permission in permissionGroup.Permissions) { @@ -219,9 +192,12 @@ public partial class PermissionManagementModal SetPermissionGrant(permission, value); } } + + GrantAll = _groups.SelectMany(x => x.Permissions).All(p => p.IsGranted); + await InvokeAsync(StateHasChanged); } - protected virtual void PermissionChanged(bool value, PermissionGroupDto permissionGroup, PermissionGrantInfoDto permission) + protected virtual async Task PermissionChanged(bool value, PermissionGroupDto permissionGroup, PermissionGrantInfoDto permission) { SetPermissionGrant(permission, value); @@ -238,6 +214,9 @@ public partial class PermissionManagementModal SetPermissionGrant(childPermission, false); } } + + GrantAll = _groups.SelectMany(x => x.Permissions).All(p => p.IsGranted); + await InvokeAsync(StateHasChanged); } private void SetParentPermissionGrant(PermissionGroupDto permissionGroup, PermissionGrantInfoDto permission) @@ -261,17 +240,6 @@ public partial class PermissionManagementModal return; } - if (value) - { - _grantedPermissionCount++; - _notGrantedPermissionCount--; - } - else - { - _grantedPermissionCount--; - _notGrantedPermissionCount++; - } - permission.IsGranted = value; } @@ -338,22 +306,22 @@ public partial class PermissionManagementModal return permissions.All(x => x.IsGranted) && grantedProviders.Any(p => p.ProviderName != _providerName); } - + protected virtual async Task OnPermissionGroupSearchTextChangedAsync(string value) { if (value == _permissionGroupSearchText) { return; } - + _permissionGroupSearchText = value; _groups = _permissionGroupSearchText.IsNullOrWhiteSpace() ? _allGroups.ToList() : _allGroups.Where(x => x.DisplayName.Contains(_permissionGroupSearchText, StringComparison.OrdinalIgnoreCase) || x.Permissions.Any(permission => permission.DisplayName.Contains(_permissionGroupSearchText, StringComparison.OrdinalIgnoreCase))).ToList(); - + NormalizePermissionGroup(false); await InvokeAsync(StateHasChanged); } - + protected virtual Task OnSelectedTabChangedAsync(string name) { _selectedTabName = name;