+ `,
+})
+export class UserFriendsComponent {
+ friends = input([]);
+ friendSelected = output();
+
+ selectFriend(friend: string) {
+ this.friendSelected.emit(friend);
+ }
+}
+```
+
+Then, you can use them in a container component like this
+
+```ts
+// 🧩 new user profile components that uses other user components
+import { Component } from "@angular/core";
+import { signal } from "@angular/core";
+import { UserAvatarComponent } from "./user-avatar.component";
+import { UserPostsComponent } from "./user-posts.component";
+import { UserFriendsComponent } from "./user-friends.component";
+
+@Component({
+ selector: "app-user-profile",
+ imports: [UserAvatarComponent, UserPostsComponent, UserFriendsComponent],
+ template: `
+
+
+
+
+
+ `,
+})
+export class UserProfileComponent {
+ user = signal({
+ name: "Jane Doe",
+ avatar: "/assets/avatar.png",
+ posts: ["Angular Tips", "Reusable Components FTW!"],
+ friends: ["John", "Mary", "Steve"],
+ });
+
+ onFriendSelected(friend: string) {
+ console.log(`Selected friend: ${friend}`);
+ }
+}
+```
+
+The most common problem of creating such components is over-creating new elements when you actually do not need them. So, it is a design decision that needs to be carefully taken while building the application. If misused, it can lead to:
+
+- a management nightmare
+- unnecessary lifecycle hook complexity
+- extra indirect data flow (makes debugging harder)
+
+Nevertheless, this makes the app more scalable and maintainable if correctly used. Such structure will provide:
+
+- a clear separation of concerns as each component will maintain decided tasks
+- faster feature development
+- shared libraries or elements across the application
+
+---
+
+## 🚀 Why Standalone Components Matter
+
+As Angular has announced standalone components starting from version 17, they have been gradually developing features that support reusability. This important feature brings a great migration for components, directives, and pipes.
+
+Since it allows these elements to be used directly inside an `imports` array rather than through a module structure, it reinforces reusability patterns and simplifies management.
+
+Back in the module-based structure, we used to create these components and declare them in modules. This still offers some reusability, as we can import the modules where needed. However, standalone components can be consumed both by other standalone components and modules. For this reason, migrating from the module-based structure to a fully standalone architecture brings many benefits for this concern.
+
+---
+
+## 🧠 Designing Components That Scale and Reuse Well
+
+The first point you need to consider here is to encapsulate and isolate logic.
+
+For example:
+
+1. This counter component isolates the concept of incrementing/decrementing so the parent component will not take care of this logic except showing the result.
+
+ ```ts
+ import { Component, signal } from "@angular/core";
+
+ @Component({
+ selector: "app-counter",
+ template: `
+
+ {{ count() }}
+
+ `,
+ })
+ export class CounterComponent {
+ private count = signal(0); // internal state
+
+ increment() {
+ this.count.update((v) => v + 1);
+ }
+ decrement() {
+ this.count.update((v) => v - 1);
+ }
+ }
+ ```
+
+2. This component isolates the styles and makes the badge reusable. Styles in this component will not leak out to others, and global styles will not affect it.
+
+ ```ts
+ import { Component, ViewEncapsulation } from "@angular/core";
+
+ @Component({
+ selector: "app-badge",
+ template: `{{ label }}`,
+ styles: [
+ `
+ .badge {
+ background: #007bff;
+ color: white;
+ padding: 4px 8px;
+ border-radius: 4px;
+ }
+ `,
+ ],
+ encapsulation: ViewEncapsulation.Emulated, // default; isolates CSS
+ })
+ export class BadgeComponent {
+ label = "New";
+ }
+ ```
+
+3. The search component below is a very common example since it handles a business logic exposing simple inputs/outputs
+
+ ```ts
+ import { Component, input, output } from "@angular/core";
+
+ @Component({
+ selector: "app-search-box",
+ template: `
+
+ `,
+ })
+ export class SearchBoxComponent {
+ query = input("");
+ changed = output();
+
+ onChange(event: Event) {
+ const value = (event.target as HTMLInputElement).value;
+ this.changed.emit(value);
+ }
+ }
+ ```
+
+Encapsulation ensures that each component manages its own logic without leaking details to the outside. By keeping behavior self-contained, components become easier to understand, test, and reuse. This isolation prevents unexpected side effects, keeps your UI predictable, and allows each component to evolve independently as your application grows.
+
+At this point, we can also briefly mention smart and dumb components. Smart components handle business logic, while dumb components take care of displaying data and emitting user actions.
+
+This separation keeps your UI structure scalable. Smart components can change how data is loaded or handled without affecting presentation components, and dumb components can be reused anywhere since they just rely on inputs and outputs.
+
+```ts
+// smart component (container)
+@Component({
+ selector: "app-user-profile",
+ imports: [UserCardComponent],
+ template: ``,
+})
+export class UserProfileComponent {
+ user = signal({ name: "Jane", role: "Admin" });
+
+ onSelect(user: any) {
+ console.log("Selected user:", user);
+ }
+}
+
+// dumb component (presentation)
+@Component({
+ selector: "app-user-card",
+ standalone: true,
+ template: `
+
+
{{ user().name }}
+
{{ user().role }}
+
+ `,
+})
+export class UserCardComponent {
+ user = input.required<{ name: string; role: string }>();
+ select = output<{ name: string; role: string }>();
+}
+```
+
+---
+
+## 🔁 Reusing Components Across the Application
+
+As there are many ways of reusing a component in the project, we will go over a real-life example.
+
+Here are two very common ABP components that can be reused anywhere in the app:
+
+```ts
+//...
+import { ABP } from "@abp/ng.core";
+
+@Component({
+ selector: "abp-button",
+ template: `
+
+ `,
+ imports: [NgClass],
+})
+export class ButtonComponent implements OnInit {
+ private renderer = inject(Renderer2);
+
+ @Input()
+ buttonId = "";
+
+ @Input()
+ buttonClass = "btn btn-primary";
+
+ @Input()
+ buttonType = "button";
+
+ @Input()
+ formName?: string = undefined;
+
+ @Input()
+ iconClass?: string;
+
+ @Input()
+ loading = false;
+
+ @Input()
+ disabled: boolean | undefined = false;
+
+ @Input()
+ attributes?: ABP.Dictionary;
+
+ @Output() readonly click = new EventEmitter();
+
+ @Output() readonly focus = new EventEmitter();
+
+ @Output() readonly blur = new EventEmitter();
+
+ @Output() readonly abpClick = new EventEmitter();
+
+ @Output() readonly abpFocus = new EventEmitter();
+
+ @Output() readonly abpBlur = new EventEmitter();
+
+ @ViewChild("button", { static: true })
+ buttonRef!: ElementRef;
+
+ get icon(): string {
+ return `${
+ this.loading ? "fa fa-spinner fa-spin" : this.iconClass || "d-none"
+ }`;
+ }
+
+ ngOnInit() {
+ if (this.attributes) {
+ Object.keys(this.attributes).forEach((key) => {
+ if (this.attributes?.[key]) {
+ this.renderer.setAttribute(
+ this.buttonRef.nativeElement,
+ key,
+ this.attributes[key]
+ );
+ }
+ });
+ }
+ }
+}
+```
+
+This button component can be used by simply importing the `ButtonComponent` and using the `` tag.
+
+You can reach the source code [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts).
+
+This modal component is also commonly used. The source code is [here](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts).
+
+```ts
+//...
+export type ModalSize = "sm" | "md" | "lg" | "xl";
+
+@Component({
+ selector: "abp-modal",
+ templateUrl: "./modal.component.html",
+ styleUrls: ["./modal.component.scss"],
+ providers: [SubscriptionService],
+ imports: [NgTemplateOutlet],
+})
+export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
+ protected readonly confirmationService = inject(ConfirmationService);
+ protected readonly modal = inject(NgbModal);
+ protected readonly modalRefService = inject(ModalRefService);
+ protected readonly suppressUnsavedChangesWarningToken = inject(
+ SUPPRESS_UNSAVED_CHANGES_WARNING,
+ {
+ optional: true,
+ }
+ );
+ protected readonly destroyRef = inject(DestroyRef);
+ private document = inject(DOCUMENT);
+
+ visible = model(false);
+
+ busy = input(false, {
+ transform: (value: boolean) => {
+ if (this.abpSubmit() && this.abpSubmit() instanceof ButtonComponent) {
+ this.abpSubmit().loading = value;
+ }
+ return value;
+ },
+ });
+
+ options = input({ keyboard: true });
+
+ suppressUnsavedChangesWarning = input(
+ this.suppressUnsavedChangesWarningToken
+ );
+
+ modalContent = viewChild>("modalContent");
+
+ abpHeader = contentChild>("abpHeader");
+
+ abpBody = contentChild>("abpBody");
+
+ abpFooter = contentChild>("abpFooter");
+
+ abpSubmit = contentChild(ButtonComponent, { read: ButtonComponent });
+
+ readonly init = output();
+
+ readonly appear = output();
+
+ readonly disappear = output();
+
+ modalRef!: NgbModalRef;
+
+ isConfirmationOpen = false;
+
+ modalIdentifier = `modal-${uuid()}`;
+
+ get modalWindowRef() {
+ return this.document.querySelector(
+ `ngb-modal-window.${this.modalIdentifier}`
+ );
+ }
+
+ get isFormDirty(): boolean {
+ return Boolean(this.modalWindowRef?.querySelector(".ng-dirty"));
+ }
+
+ constructor() {
+ effect(() => {
+ this.toggle(this.visible());
+ });
+ }
+
+ ngOnInit(): void {
+ this.modalRefService.register(this);
+ }
+
+ dismiss(mode: ModalDismissMode) {
+ switch (mode) {
+ case "hard":
+ this.visible.set(false);
+ break;
+ case "soft":
+ this.close();
+ break;
+ default:
+ break;
+ }
+ }
+
+ protected toggle(value: boolean) {
+ this.visible.set(value);
+
+ if (!value) {
+ this.modalRef?.dismiss();
+ this.disappear.emit();
+ return;
+ }
+
+ setTimeout(() => this.listen(), 0);
+ this.modalRef = this.modal.open(this.modalContent(), {
+ size: "md",
+ centered: false,
+ keyboard: false,
+ scrollable: true,
+ beforeDismiss: () => {
+ if (!this.visible()) return true;
+
+ this.close();
+ return !this.visible();
+ },
+ ...this.options(),
+ windowClass: `${this.options().windowClass || ""} ${
+ this.modalIdentifier
+ }`,
+ });
+
+ this.appear.emit();
+ }
+
+ ngOnDestroy(): void {
+ this.modalRefService.unregister(this);
+ this.toggle(false);
+ }
+
+ close() {
+ if (this.busy()) return;
+
+ if (this.isFormDirty && !this.suppressUnsavedChangesWarning()) {
+ if (this.isConfirmationOpen) return;
+
+ this.isConfirmationOpen = true;
+ this.confirmationService
+ .warn(
+ "AbpUi::AreYouSureYouWantToCancelEditingWarningMessage",
+ "AbpUi::AreYouSure",
+ {
+ dismissible: false,
+ }
+ )
+ .subscribe((status: Confirmation.Status) => {
+ this.isConfirmationOpen = false;
+ if (status === Confirmation.Status.confirm) {
+ this.visible.set(false);
+ }
+ });
+ } else {
+ this.visible.set(false);
+ }
+ }
+
+ listen() {
+ if (this.modalWindowRef) {
+ fromEvent(this.modalWindowRef, "keyup")
+ .pipe(
+ takeUntilDestroyed(this.destroyRef),
+ debounceTime(150),
+ filter(
+ (key: KeyboardEvent) =>
+ key && key.key === "Escape" && this.options().keyboard
+ )
+ )
+ .subscribe(() => this.close());
+ }
+
+ fromEvent(window, "beforeunload")
+ .pipe(takeUntilDestroyed(this.destroyRef))
+ .subscribe((event) => {
+ if (this.isFormDirty && !this.suppressUnsavedChangesWarning()) {
+ event.preventDefault();
+ }
+ });
+
+ this.init.emit();
+ }
+}
+```
+
+This concept differs slightly from the others mentioned above since these components are introduced within a library called `theme-shared`, which you can explore [here](https://github.com/abpframework/abp/tree/dev/npm/ng-packs/packages/theme-shared).
+
+Using **shared libraries** for such common components is one of the most effective ways to make your app modular and maintainable. By grouping frequently used elements into a dedicated library, you create a single source of truth for your UI and logic.
+
+However, over-creating or prematurely abstracting small pieces of logic into separate libraries can lead to unnecessary complexity and dependency management overhead. When every feature has its own “mini-library,” updates and debugging become scattered and difficult to coordinate.
+
+The key is to extract shared functionality only when it is proven to be reused across multiple contexts. Start small, let patterns emerge naturally, and then move them into a shared library when the benefits of reusability outweigh the maintenance cost.
+
+---
+
+## ⚙️ Best Practices and Common Pitfalls
+
+### ✅ Best Practices
+
+1. **Start with real reuse:** Extract components only after the pattern appears in multiple places.
+2. **Keep them focused:** One clear responsibility per component—avoid “do-it-all” designs.
+3. **Use standalone components:** Simplify imports and improve independence.
+4. **Promote through libraries:** Move proven, stable components into shared libraries for wider use.
+
+### ⚠️ Common Mistakes
+
+1. **Premature abstraction:** Don't create components before actual reuse.
+2. **Too many input/output bindings:** Overly generic components are hard to configure and maintain.
+3. **Neglecting performance:** Too many micro-components can hurt performance.
+4. **Ignoring accessibility and semantics:** Reusable does not mean usable—always consider ARIA roles and HTML structure.
+
+---
+
+## 📚 Further Reading and References
+
+As this article has mentioned some concepts and best practices, you can explore these resources for more details:
+
+- [Angular Components Guide](https://angular.dev/guide/components)
+- [Standalone Migration Guides](https://angular.dev/reference/migrations/standalone), [ABP Angular Standalone Applications](https://abp.io/community/articles/abp-now-supports-angular-standalone-applications-zzi2rr2z#gsc.tab=0)
+- [Smart vs. Dumb Components](https://blog.angular-university.io/angular-2-smart-components-vs-presentation-components-whats-the-difference-when-to-use-each-and-why/)
+- [Angular Libraries Overview](https://angular.dev/tools/libraries)
+
+You can also check these open-source libraries for a better understanding of reusability and modularity:
+
+- [Angular Components on GitHub](https://github.com/angular/components)
+- [ABP NPM Libraries](https://github.com/abpframework/abp/tree/dev/npm/ng-packs/packages)
+
+---
+
+## 🏁 Conclusion
+
+Reusability is one of the strongest architectural foundations for scalable Angular applications. By combining **standalone components**, **signals**, **encapsulated logic**, and **shared libraries**, you can create a modular system that grows gracefully over time.
+
+The goal is not just to make components reusable. It is to make them meaningful, maintainable, and consistent across your app. Build only what truly adds value, reuse intentionally, and let Angular's evolving ecosystem handle the rest.
diff --git a/docs/en/Community-Articles/2025-10-09-how-to-change-logo-in-angular-abp-apps/article.md b/docs/en/Community-Articles/2025-10-09-how-to-change-logo-in-angular-abp-apps/article.md
new file mode 100644
index 0000000000..59939beab1
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-09-how-to-change-logo-in-angular-abp-apps/article.md
@@ -0,0 +1,289 @@
+# How to Change Logo in Angular ABP Applications
+
+## Introduction
+
+Logo application customization is one of the most common branding requirements in web applications. In ABP Framework's Angular applications, we found that developers were facing problems while they were trying to implement their application logos, especially on theme dependencies and flexibility. To overcome this, we moved the logo provider from `@volo/ngx-lepton-x.core` to `@abp/ng.theme.shared`, where it is more theme-independent and accessible. Here, we will describe our experience using this improvement and guide you on the new approach for logo configuration in ABP Angular applications.
+
+## Problem
+
+Previously, the logo configuration process in ABP Angular applications had several disadvantages:
+
+1. **Theme Dependency**: The `provideLogo` function was a part of the `@volo/ngx-lepton-x.core` package, so the developers had to depend on LeptonX theme packages even when they were using a different theme or wanted to extend the logo behavior.
+
+2. **Inflexibility**: The fact that the logo provider had to adhere to a specific theme package brought about an undesirable tight coupling of logo configuration and theme implementation.
+
+3. **Discoverability Issues**: Developers looking for logo configuration features would likely look in core ABP packages, but the provider was hidden in a theme-specific package, which made it harder to discover.
+
+4. **Migration Issues**: During theme changes or theme package updates, logo setting could get corrupted or require additional tuning.
+
+These made a basic operation like altering the application logo more challenging than it should be, especially for teams using custom themes or wanting to maintain theme independence.
+
+## Solution
+
+We moved the `provideLogo` function from `@volo/ngx-lepton-x.core` to `@abp/ng.theme.shared` package. This solution offers:
+
+- **Theme Independence**: Works with any ABP-compatible theme
+- **Single Source of Truth**: Logo configuration is centralized in the environment file
+- **Standard Approach**: Follows ABP's provider-based configuration pattern
+- **Easy Migration**: Simple import path change for existing applications
+- **Better Discoverability**: Located in a core ABP package where developers expect it
+
+This approach maintains ABP's philosophy of providing flexible, reusable solutions while reducing unnecessary dependencies.
+
+## Implementation
+
+Let's walk through how logo configuration works with the new approach.
+
+### Step 1: Configure Logo URL in Environment
+
+First, define your logo URL in the `environment.ts` file:
+
+```typescript
+export const environment = {
+ production: false,
+ application: {
+ baseUrl: 'http://localhost:4200',
+ name: 'MyApplication',
+ logoUrl: 'https://your-domain.com/assets/logo.png',
+ },
+ // ... other configurations
+};
+```
+
+The `logoUrl` property accepts any valid URL, allowing you to use:
+- Absolute URLs (external images)
+- Relative paths to assets folder (`/assets/logo.png`)
+- Data URLs for embedded images
+- CDN-hosted images
+
+### Step 2: Provide Logo Configuration
+
+In your `app.config.ts` (or `app.module.ts` for module-based apps), import and use the logo provider:
+
+```typescript
+import { provideLogo, withEnvironmentOptions } from '@abp/ng.theme.shared';
+import { environment } from './environments/environment';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ // ... other providers
+ provideLogo(withEnvironmentOptions(environment)),
+ ],
+};
+```
+
+**Important Note**: If you're migrating from an older version where the logo provider was in `@volo/ngx-lepton-x.core`, simply update the import statement:
+
+```typescript
+// Old (before migration)
+import { provideLogo, withEnvironmentOptions } from '@volo/ngx-lepton-x.core';
+
+// New (current approach)
+import { provideLogo, withEnvironmentOptions } from '@abp/ng.theme.shared';
+```
+
+### How It Works Under the Hood
+
+The `provideLogo` function registers a logo configuration service that:
+1. Reads the `logoUrl` from environment configuration
+2. Provides it to theme components through Angular's dependency injection
+3. Allows themes to access and render the logo consistently
+
+The `withEnvironmentOptions` helper extracts the relevant configuration from your environment object, ensuring type safety and proper configuration structure.
+
+### Example: Complete Configuration
+
+Here's a complete example showing both environment and provider configuration:
+
+**environment.ts:**
+```typescript
+export const environment = {
+ production: false,
+ application: {
+ baseUrl: 'http://localhost:4200',
+ name: 'E-Commerce Platform',
+ logoUrl: 'https://cdn.example.com/brand/logo-primary.svg',
+ },
+ oAuthConfig: {
+ issuer: 'https://localhost:44305',
+ clientId: 'MyApp_App',
+ // ... other OAuth settings
+ },
+ // ... other settings
+};
+```
+
+**app.config.ts:**
+```typescript
+import { ApplicationConfig } from '@angular/core';
+import { provideRouter } from '@angular/router';
+import { provideLogo, withEnvironmentOptions } from '@abp/ng.theme.shared';
+import { environment } from './environments/environment';
+import { routes } from './app.routes';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideRouter(routes),
+ provideLogo(withEnvironmentOptions(environment)),
+ // ... other providers
+ ],
+};
+```
+
+## Advanced: Logo Component Replacement
+
+For more advanced customization scenarios where you need complete control over the logo component's structure, styling, or behavior, ABP provides a component replacement mechanism. This approach allows you to replace the entire logo component with your custom implementation.
+
+### When to Use Component Replacement
+
+Consider using component replacement when:
+- You need custom HTML structure around the logo
+- You want to add interactive elements (e.g., dropdown menu, animations)
+- You need to implement complex responsive behavior
+- The simple `logoUrl` configuration doesn't meet your requirements
+
+### How to Replace the Logo Component
+
+#### Step 1: Generate a New Logo Component
+
+Run the following command in your Angular folder to create a new component:
+
+```bash
+ng generate component custom-logo --inline-template --inline-style
+```
+
+#### Step 2: Implement Your Custom Logo
+
+Open the generated `custom-logo.component.ts` and implement your custom logo:
+
+```typescript
+import { Component } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+@Component({
+ selector: 'app-custom-logo',
+ standalone: true,
+ imports: [RouterModule],
+ template: `
+
+
+
+ `,
+ styles: [`
+ .navbar-brand {
+ padding: 0.5rem 1rem;
+ }
+
+ .navbar-brand img {
+ transition: opacity 0.3s ease;
+ }
+
+ .navbar-brand:hover img {
+ opacity: 0.8;
+ }
+ `]
+})
+export class CustomLogoComponent {}
+```
+
+#### Step 3: Register the Component Replacement
+
+Open your `app.config.ts` and register the component replacement:
+
+```typescript
+import { ApplicationConfig } from '@angular/core';
+import { provideRouter } from '@angular/router';
+import { ReplaceableComponentsService } from '@abp/ng.core';
+import { eThemeBasicComponents } from '@abp/ng.theme.basic';
+import { CustomLogoComponent } from './custom-logo/custom-logo.component';
+import { environment } from './environments/environment';
+import { routes } from './app.routes';
+
+export const appConfig: ApplicationConfig = {
+ providers: [
+ provideRouter(routes),
+ // ... other providers
+ {
+ provide: 'APP_INITIALIZER',
+ useFactory: (replaceableComponents: ReplaceableComponentsService) => {
+ return () => {
+ replaceableComponents.add({
+ component: CustomLogoComponent,
+ key: eThemeBasicComponents.Logo,
+ });
+ };
+ },
+ deps: [ReplaceableComponentsService],
+ multi: true,
+ },
+ ],
+};
+```
+
+Alternatively, if you're using a module-based application, you can register it in `app.component.ts`:
+
+```typescript
+import { Component, OnInit } from '@angular/core';
+import { ReplaceableComponentsService } from '@abp/ng.core';
+import { eThemeBasicComponents } from '@abp/ng.theme.basic';
+import { CustomLogoComponent } from './custom-logo/custom-logo.component';
+
+@Component({
+ selector: 'app-root',
+ template: '',
+})
+export class AppComponent implements OnInit {
+ constructor(private replaceableComponents: ReplaceableComponentsService) {}
+
+ ngOnInit() {
+ this.replaceableComponents.add({
+ component: CustomLogoComponent,
+ key: eThemeBasicComponents.Logo,
+ });
+ }
+}
+```
+
+### Component Replacement vs Logo URL Configuration
+
+Here's a comparison to help you choose the right approach:
+
+| Feature | Logo URL Configuration | Component Replacement |
+|---------|------------------------|----------------------|
+| **Simplicity** | Very simple, one-line configuration | Requires creating a new component |
+| **Flexibility** | Limited to image URL | Full control over HTML/CSS/behavior |
+| **Use Case** | Standard logo display | Complex customizations |
+| **Maintenance** | Minimal | Requires component maintenance |
+| **Migration** | Easy to change | Requires code changes |
+| **Recommended For** | Most applications | Advanced customization needs |
+
+For most applications, the simple `logoUrl` configuration in the environment file is sufficient and recommended. Use component replacement only when you need advanced customization that goes beyond a simple image.
+
+### Benefits of This Approach
+
+1. **Separation of Concerns**: Logo configuration is separate from theme implementation
+2. **Environment-Based**: Different logos for development, staging, and production
+3. **Type Safety**: TypeScript ensures correct configuration structure
+4. **Testing**: Easy to mock and test logo configuration
+5. **Consistency**: Same logo appears across all theme components automatically
+6. **Flexibility**: Choose between simple configuration or full component replacement based on your needs
+
+## Conclusion
+
+In this article, we explored how ABP Framework simplified logo configuration in Angular applications by moving the logo provider from `@volo/ngx-lepton-x.core` to `@abp/ng.theme.shared`. This change eliminates unnecessary theme dependencies and makes logo customization more straightforward and theme-agnostic.
+
+The solution we implemented allows developers to configure their application logo simply by setting a URL in the environment file and providing the logo configuration in their application setup. For advanced scenarios requiring complete control over the logo component, ABP's component replacement mechanism provides a powerful alternative. This approach maintains flexibility while reducing complexity and improving discoverability.
+
+We developed this improvement while working on ABP Framework to enhance developer experience and reduce common friction points. By sharing this solution, we hope to help teams implement consistent branding across their ABP Angular applications more easily, regardless of which theme they choose to use.
+
+If you're using an older version of ABP with logo configuration in LeptonX packages, migrating to this new approach requires only a simple import path change, making it a smooth upgrade path for existing applications.
+
+## See Also
+
+- [Component Replacement Documentation](https://abp.io/docs/latest/framework/ui/angular/component-replacement)
+- [ABP Angular UI Customization Guide](https://abp.io/docs/latest/framework/ui/angular/customization)
diff --git a/docs/en/Community-Articles/2025-10-10-Using-Transfer-State-with-Angular-SSR/cover.png b/docs/en/Community-Articles/2025-10-10-Using-Transfer-State-with-Angular-SSR/cover.png
new file mode 100644
index 0000000000..2a0bcf52e9
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-10-Using-Transfer-State-with-Angular-SSR/cover.png differ
diff --git a/docs/en/Community-Articles/2025-10-10-Using-Transfer-State-with-Angular-SSR/post.md b/docs/en/Community-Articles/2025-10-10-Using-Transfer-State-with-Angular-SSR/post.md
new file mode 100644
index 0000000000..3110a8e1be
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-10-Using-Transfer-State-with-Angular-SSR/post.md
@@ -0,0 +1,267 @@
+# From Server to Browser — the Elegant Way: Angular TransferState Explained
+
+## Introduction
+
+When building Angular applications with Server‑Side Rendering (SSR), a common performance pitfall is duplicated data fetching: the server loads data to render HTML, then the browser bootstraps Angular and fetches the same data again. That’s wasteful, increases Time‑to‑Interactive, and can hammer your APIs.
+
+Angular’s built‑in **TransferState** lets you transfer the data fetched on the server to the browser during hydration so the client can reuse it instead of calling the API again. It’s simple, safe for serializable data, and makes SSR feel instant for users.
+
+This article explains what TransferState is, and how to implement it in your Angular SSR app.
+
+---
+
+## What Is TransferState?
+
+TransferState is a key–value store that exists for a single SSR render. On the server, you put serializable data into the store. Angular serializes it into the HTML as a small script tag. When the browser hydrates, Angular reads that payload back and makes it available to your app. You can then consume it and skip duplicate HTTP calls.
+
+Key points:
+
+- Works only across the SSR → browser hydration boundary (not a general cache).
+- Data is cleaned up after bootstrapping (no stale data).
+- Stores JSON‑serializable data only (if you need to use Date/Functions/Map; serialize it).
+- Data is set on the server and read on the client.
+
+---
+
+## When Should You Use It?
+
+- Data fetched during SSR that is also be needed on the client.
+- Data that doesn’t change between server render and immediate client hydration.
+- Expensive or slow API endpoints where a second request is visibly costly.
+
+Avoid using it for:
+
+- Highly dynamic data that changes frequently.
+- Sensitive data (never put secrets/tokens in TransferState).
+- Large payloads (keep the serialized state small to avoid bloating HTML).
+
+---
+
+## Prerequisites
+
+- An Angular app with SSR enabled (Angular ≥16: `ng add @angular/ssr`).
+- `HttpClient` configured. The examples below show both manual TransferState use and the build in solutions.
+
+---
+
+## Option A — Using TransferState Manually
+
+This approach gives you full control over what to cache and when. It's straightforward and works in both module‑based and standalone‑based apps.
+
+Service example that fetches books and uses TransferState:
+
+```ts
+// books.service.ts
+import {
+ Injectable,
+ PLATFORM_ID,
+ makeStateKey,
+ TransferState,
+ inject,
+} from '@angular/core';
+import { isPlatformServer } from '@angular/common';
+import { HttpClient } from '@angular/common/http';
+import { Observable, of } from 'rxjs';
+import { tap } from 'rxjs/operators';
+
+export interface Book {
+ id: number;
+ name: string;
+ price: number;
+}
+
+@Injectable({ providedIn: 'root' })
+export class BooksService {
+ BOOKS_KEY = makeStateKey('books:list');
+ readonly httpClient = inject(HttpClient);
+ readonly transferState = inject(TransferState);
+ readonly platformId = inject(PLATFORM_ID);
+
+ getBooks(): Observable {
+ // If browser and we have the data that already fetched on the server, use it and remove from TransferState
+ if (this.transferState.hasKey(this.BOOKS_KEY)) {
+ const cached = this.transferState.get(this.BOOKS_KEY, []);
+ this.transferState.remove(this.BOOKS_KEY); // remove to avoid stale reads
+ return of(cached);
+ }
+
+ // Otherwise fetch data. If running on the server, write into TransferState
+ return this.httpClient.get('/api/books').pipe(
+ tap(list => {
+ if (isPlatformServer(this.platformId)) {
+ this.transferState.set(this.BOOKS_KEY, list);
+ }
+ })
+ );
+ }
+}
+
+```
+
+Use it in a component:
+
+```ts
+// books.component.ts
+import { Component, inject, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { BooksService, Book } from './books.service';
+
+@Component({
+ selector: 'app-books',
+ imports: [CommonModule],
+ template: `
+
Books
+
+ @for (book of books; track book.id) {
+
{{ book.name }} — {{ book.price | currency }}
+ }
+
+ `,
+})
+export class BooksComponent implements OnInit {
+ private booksService = inject(BooksService);
+ books: Book[] = [];
+
+ ngOnInit() {
+ this.booksService.getBooks().subscribe(data => (this.books = data));
+ }
+}
+
+```
+
+Route resolver variant (keeps templates simple and aligns with SSR prefetching):
+
+```ts
+// src/app/routes.ts
+
+export const routes: Routes = [
+ {
+ path: 'books',
+ component: BooksComponent,
+ resolve: {
+ books: () => inject(BooksService).getBooks(),
+ },
+ },
+];
+```
+
+Then read `books` from the `ActivatedRoute` data in your component.
+
+---
+
+## Option B — Using HttpInterceptor to Automate TransferState
+
+Like Option A, but less boilerplate. This approach uses an **HttpInterceptor** to automatically cache HTTP GET (also POST/PUT request but not recommended) responses in TransferState. You can determine which requests to cache based on URL patterns.
+
+Example interceptor that caches GET requests:
+
+```ts
+import { inject, makeStateKey, PLATFORM_ID, TransferState } from '@angular/core';
+import {
+ HttpEvent,
+ HttpHandlerFn,
+ HttpInterceptorFn,
+ HttpRequest,
+ HttpResponse,
+} from '@angular/common/http';
+import { Observable, of } from 'rxjs';
+import { isPlatformBrowser, isPlatformServer } from '@angular/common';
+import { tap } from 'rxjs/operators';
+
+export const transferStateInterceptor: HttpInterceptorFn = (
+ req: HttpRequest,
+ next: HttpHandlerFn,
+): Observable> => {
+ const transferState = inject(TransferState);
+ const platformId = inject(PLATFORM_ID);
+
+ // Only cache GET requests. You can customize this to match specific URLs if needed.
+ if (req.method !== 'GET') {
+ return next(req);
+ }
+
+ // Create a unique key for this request
+ const stateKey = makeStateKey>(req.urlWithParams);
+
+ // If browser, check if we have the response in TransferState
+ if (isPlatformBrowser(platformId)) {
+ const storedResponse = transferState.get>(stateKey, null);
+ if (storedResponse) {
+ transferState.remove(stateKey); // remove to avoid stale reads
+ return of(new HttpResponse({ body: storedResponse, status: 200 }));
+ }
+ }
+
+ return next(req).pipe(
+ tap(event => {
+ // If server, store the response in TransferState
+ if (isPlatformServer(platformId) && event instanceof HttpResponse) {
+ transferState.set(stateKey, event.body);
+ }
+ }),
+ );
+};
+
+```
+
+Add the interceptor to your app module or bootstrap function:
+
+````ts
+ provideHttpClient(withFetch(), withInterceptors([transferStateInterceptor]))
+````
+
+
+---
+
+## Option C — Using Angular's Built-in HTTP Transfer Cache
+
+This is the simplest option if you want to HTTP requests that without custom logic.
+
+Angular docs: https://angular.dev/api/platform-browser/withHttpTransferCacheOptions
+
+
+Usage examples:
+
+```ts
+ // Only cache GET requests that have no headers
+ provideClientHydration(withHttpTransferCacheOptions({}))
+
+ // Also cache POST requests (not recommended for most cases)
+ provideClientHydration(withHttpTransferCacheOptions({
+ includePostRequests: true
+ }))
+
+ // Cache requests that have auth headers (e.g., JWT tokens)
+ provideClientHydration(withHttpTransferCacheOptions({
+ includeRequestsWithAuthHeaders: true
+ }))
+```
+
+To see all options, check the Angular docs: https://angular.dev/api/common/http/HttpTransferCacheOptions
+
+## Best Practices and Pitfalls
+
+- Keep payloads small: only put what’s needed for initial paint.
+- Serialize explicitly if needed: for Dates or complex types, convert to strings and reconstruct on the client.
+- Don’t transfer secrets: never place tokens or sensitive user data in TransferState.
+- Per‑request isolation: state is scoped to a single SSR request; it is not a global cache.
+
+---
+
+## Debugging Tips
+
+- Log on server vs browser: use `isPlatformServer` and `isPlatformBrowser` checks to confirm where code runs.
+- DevTools inspection: view the page source after SSR; you’ll see a small script tag that embeds the transfer state.
+- Count requests: put a console log in your service to verify the second HTTP call is gone on the client.
+
+---
+
+## Measurable Impact
+
+On content‑heavy pages, TransferState typically removes 1–3 duplicate API calls during hydration, shaving 100–500 ms from the critical path on average networks. It’s a low‑effort, high‑impact win for SSR apps.
+
+---
+
+## Conclusion
+
+If you already have SSR, enabling TransferState is one of the easiest ways to make hydration feel instant. You can use it built‑in HTTP caching or manually control what to cache. Either way, it eliminates redundant data fetching, speeds up Time‑to‑Interactive, and improves user experience with minimal effort.
diff --git a/docs/en/Community-Articles/2025-10-15-angular-library-linking-made-easy-paths-workspaces-and-symlinks/POST.md b/docs/en/Community-Articles/2025-10-15-angular-library-linking-made-easy-paths-workspaces-and-symlinks/POST.md
new file mode 100644
index 0000000000..52601e8624
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-15-angular-library-linking-made-easy-paths-workspaces-and-symlinks/POST.md
@@ -0,0 +1,244 @@
+# Angular Library Linking Made Easy: Paths, Workspaces, and Symlinks
+
+Managing local libraries and path references in Angular projects has evolved significantly with the introduction of the new Angular application builder. What once required manual path mappings, fragile symlinks, and `node_modules` references is now more structured, predictable, and aligned with modern TypeScript and workspace practices. This guide walks through how path mapping works, how it has changed, and the best ways to link and manage your local libraries in brand new Angular ecosystem.
+
+### Understanding TypeScript Path Mapping
+
+Path aliases is a powerful feature in TypeScript that helps developers simplify and organize their import statements. Instead of dealing with long and error-prone relative paths like `../../../components/button`, you can define a clear and descriptive alias that points directly to a specific directory or module.
+
+This configuration is managed through the `paths` property in the TypeScript configuration file (`tsconfig.json`), allowing you to map custom names to local folders or compiled outputs. For example:
+
+```json
+// tsconfig.json
+{
+ "compilerOptions": {
+ "paths": {
+ "@my-package": ["./dist/my-package"],
+ "@my-second-package": ["./projects/my-second-package/src/public-api.ts"]
+ }
+ }
+}
+```
+
+In this setup, `@my-package` serves as a shorthand reference to your locally built library. Once configured, you can import modules using `@my-package` instead of long relative paths, which greatly improves readability and maintainability across large projects.
+
+When working with multiple subdirectories or a more complex folder structure, you can also use wildcards to create flexible and dynamic mappings. This pattern is especially useful for modular libraries or mono-repos that contain multiple sub-packages:
+
+```json
+// tsconfig.json
+{
+ "compilerOptions": {
+ "paths": {
+ "@my-package/*": ["./dist/my-package/*"]
+ }
+ }
+}
+```
+
+With this approach, imports like `@my-package/utils` or `@my-package/components/button` will automatically resolve to the corresponding directories in your build output. This makes your codebase more maintainable, portable, and consistent. This is useful especially when collaborating across teams or working with multiple libraries in the same workspace.
+
+---
+
+### Step-by-Step Examples of Path Configuration
+
+As this example provides a glimpse for the path mapping, this is not the only way for the aliases. Here are the other ways to utilize this feature.
+
+1. **Using `package.json` Exports for Library Mapping**
+
+ When developing internal libraries within a mono-repo, another option is to use the `exports` field in each library’s `package.json`
+
+ This allows Node and modern bundlers to resolve imports cleanly when consuming the library, without depending solely on TypeScript configuration.
+
+ ```json
+ // dist/my-lib/package.json
+ {
+ "name": "@my-org/my-lib",
+ "version": "1.0.0",
+ "exports": {
+ ".": "./index.js",
+ "./utils": "./utils/index.ts"
+ }
+ }
+ ```
+
+ ```tsx
+ import { formatDate } from "@my-org/my-lib/utils";
+ ```
+
+ This approach becomes especially powerful when publishing your libraries or integrating them into larger Angular mono-repos. Because, it aligns both runtime (Node) and compile-time (TypeScript) resolution.
+
+2. **Linking Local Libraries via Symlinks**
+
+ If you want to use a local library that is not yet published to npm, you can create a symbolic link between your library’s `dist` output and your consuming app.
+
+ This is useful when testing or developing multiple packages in parallel.
+
+ You can create a symlink using npm or yarn:
+
+ ```bash
+ # Inside your library folder
+ npm link
+
+ # Inside your consuming app
+ npm link @my-org/my-lib
+ ```
+
+ This effectively tells Node to resolve `@my-org/my-lib` from your local file system instead of the npm registry.
+
+ However, note that symlinks can sometimes lead to path resolution issues with certain Angular build configurations, especially before the new application builder. With the latest builder improvements, this approach is becoming more stable and predictable.
+
+3. **Combining Path Mapping with Workspace Configuration**
+
+ In a structured Angular workspace, especially one created with **Nx** or **Angular CLI** using multiple projects, you can combine the approaches above.
+
+ For instance, your `tsconfig.base.json` can define local references for in-repo libraries, while each library’s `package.json` provides external mappings for reuse outside the workspace.
+
+ This hybrid setup ensures that:
+
+ - The workspace remains easy to navigate and refactor locally.
+ - External consumers (or CI builds) can still resolve imports correctly once libraries are built.
+
+ For larger Angular projects or mono-repos, **Workspaces** (supported by both **Yarn** and **npm**) offer a clean way to manage multiple local packages within the same repository. Workspaces automatically link internal libraries together, so you can reference them by name instead of using manual `file:` paths or complex TypeScript aliases. This approach keeps dependencies consistent, simplifies cross-project development, and scales well for enterprise or multi-package setups.
+
+Each of these methods has its strengths:
+
+- **TypeScript paths:** This is great for local development and quick imports.
+- **`package.json` exports:** This is ideal for libraries meant to be distributed.
+- **Symlinks:** These are convenient for local testing between projects.
+
+Choosing the right one, or even combining them depends on the scale of your project and whether you are building internal libraries, or a full mono-repo setup.
+
+---
+
+### How Path References Worked Before the New Angular Application Builder
+
+Angular used to support path aliases to the locally installed packages by referencing to the `node_modules` folder like this:
+
+```json
+// tsconfig.json
+{
+ "compilerOptions": {
+ "paths": {
+ "@angular/*": ["./node_modules/@angular/*"]
+ }
+ }
+}
+```
+
+However, this approach is not recommended, hence not supported, by the TypeScript. You can find detailed guidance on this topic in the TypeScript documentation, which notes that paths should not reference mono-repo packages or those inside **node_modules**: [Paths should not point to monorepo packages or node_modules packages](https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages).
+
+Giving a real life example would explain the situation better. Suppose that you have such structure:
+
+- Amain angular app that consumes several npm dependencies and holds registered local paths that reference to another library locally like this:
+
+ ```json
+ // angular/tsconfig.json
+ {
+ "compileOnSave": false,
+ "compilerOptions": {
+ "paths": {
+ "@abp/ng.identity": [
+ "../modules/Volo.Abp.Identity/angular/projects/identity/src/public-api.ts"
+ ],
+ "@abp/ng.identity/config": [
+ "../modules/Volo.Abp.Identity/angular/projects/identity/config/src/public-api.ts"
+ ],
+ "@abp/ng.identity/proxy": [
+ "../modules/Volo.Abp.Identity/angular/projects/identity/proxy/src/public-api.ts"
+ ]
+ }
+ }
+ }
+ ```
+
+ This simply references to this package physically https://github.com/abpframework/abp/tree/dev/npm/ng-packs/packages/identity
+
+- This library is also using these dependencies
+
+ ```json
+ // npm/ng-packs/packages/identity/package.json
+ {
+ "name": "@abp/ng.identity",
+ "version": "10.0.0-rc.1",
+ "homepage": "https://abp.io",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/abpframework/abp.git"
+ },
+ "dependencies": {
+ "@abp/ng.components": "~10.0.0-rc.1",
+ "@abp/ng.permission-management": "~10.0.0-rc.1",
+ "@abp/ng.theme.shared": "~10.0.0-rc.1",
+ "tslib": "^2.0.0"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+ }
+ ```
+
+ As these libraries also have their own dependencies, the identity package needs to consume them in itself. Before the [application builder migration](https://angular.dev/tools/cli/build-system-migration), you could register the path configuration like this
+
+ ```json
+ // angular/tsconfig.json
+ {
+ "compileOnSave": false,
+ "compilerOptions": {
+ "paths": {
+ "@angular/*": ["node_modules/@angular/*"],
+ "@abp/*": ["node_modules/@abp/*"],
+ "@swimlane/*": ["node_modules/@swimlane/*"],
+ "@ngx-validate/core": ["node_modules/@ngx-validate/core"],
+ "@ng-bootstrap/ng-bootstrap": [
+ "node_modules/@ng-bootstrap/ng-bootstrap"
+ ],
+ "@abp/ng.identity": [
+ "../modules/Volo.Abp.Identity/angular/projects/identity/src/public-api.ts"
+ ],
+ "@abp/ng.identity/config": [
+ "../modules/Volo.Abp.Identity/angular/projects/identity/config/src/public-api.ts"
+ ],
+ "@abp/ng.identity/proxy": [
+ "../modules/Volo.Abp.Identity/angular/projects/identity/proxy/src/public-api.ts"
+ ]
+ }
+ }
+ }
+ ```
+
+ However, the latest builder forces more strict rules. So, it does not resolve the paths that reference to the `node_modules` causing a common DI error as mentioned here:
+
+ - https://github.com/angular/angular-cli/issues/31395
+ - https://github.com/angular/angular-cli/issues/26901
+ - https://github.com/angular/angular-cli/issues/27176
+
+In this case, we recommend using a symlink script. You can reach them through this example application: [🔗 Angular Sample Path Reference](https://github.com/sumeyyeKurtulus/AbpPathReferenceExamples)
+
+These scripts help you share dependencies from the main Angular app to local library projects via symlinks:
+
+- `symlink-config.ps1` centralizes which library directories to touch (e.g., ../../modules/Volo.Abp.Identity/angular/projects/identity) and which packages to link (e.g., @angular, @abp, rxjs)
+- `setup-symlinks.ps1` reads that config and, for each library, creates a `node_modules` folder if needed and symlinks only the listed packages from the `node_modules` of the app to avoid duplicate installs
+- `remove-symlinks.ps1` cleans up by deleting those library `node_modules` directories so they can use their own local deps again
+- In `angular/package.json`, the `symlinks:setup` and `symlinks:remove` npm scripts simply run those two PowerShell scripts so you can execute them conveniently with your package manager.
+
+---
+
+### Best Practices and Recommendations
+
+As we have explained each way of path mapping, this part of the article aims to summarize the best practices. Here are the points you need to consider:
+
+- Prefer **workspace references** for large projects and mono-repos.
+- Use **TypeScript path aliases** only for local development convenience.
+- Strictly avoid referencing `node_modules` directly; let the Angular builder manage package resolution.
+- Maintain **consistent library structures** with clear `package.json` exports for reusable libraries.
+- Automate **symlink creation/removal** if needed to reduce manual errors.
+
+Here is the list of common pitfalls and how you could troubleshoot them:
+
+- **DI errors after path configurations for typescript config**: Ensure that only one copy of each library is resolved. Avoid duplicate modules by checking `node_modules` and symlinks.
+- **IDE not recognizing aliases**: Confirm that `tsconfig.json` or `tsconfig.base.json` includes the correct `paths` configuration and that your IDE is using the correct tsconfig.
+- **Build errors with old paths**: Migrate paths pointing to `node_modules` to either workspace references or local library paths.
+- **Symlink issues in CI/CD**: Use automated scripts to create/remove symlinks consistently; do not rely on manual linking.
+- **Module resolution conflicts**: Check library dependencies for mismatched versions and align them using a package manager workspace strategy.
+
+As Angular’s build system continues to mature, developers are encouraged to move away from outdated path configurations and manual symlink setups. By embracing workspace references, consistent library exports, and TypeScript path mapping, teams can build scalable, maintainable applications without wrestling with complex import paths or dependency conflicts. With the right configuration, local development becomes faster, cleaner, and far more reliable.
diff --git a/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/POST.md b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/POST.md
new file mode 100644
index 0000000000..e6c0eb4601
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/POST.md
@@ -0,0 +1,88 @@
+# 5 Things You Should Keep in Mind When Deploying to a Clustered Environment
+
+Let’s be honest — moving from a single server to a cluster sounds simple on paper.
+You just add a few more machines, right?
+In practice, it’s the moment when small architectural mistakes start to grow legs.
+Below are a few things that experienced engineers usually double-check before pressing that “Deploy” button.
+
+---
+
+## 1️⃣ Managing State the Right Way
+
+Each request in a cluster might hit a different machine.
+If your application keeps user sessions or cache in memory, that data probably won’t exist on the next node.
+That’s why many teams decide to push state out of the app itself.
+
+
+
+**A few real-world tips:**
+- Keep sessions in **Redis** or something similar instead of local memory.
+- Design endpoints so they don’t rely on earlier requests.
+- Don’t assume the same server will handle two requests in a row — it rarely does.
+
+---
+
+## 2️⃣ Shared Files and Where to Put Them
+
+Uploading files to local disk? That’s going to hurt in a cluster.
+Other nodes can’t reach those files, and you’ll spend hours wondering why images disappear.
+
+
+
+**Better habits:**
+- Push uploads to **S3**, **Azure Blob**, or **Google Cloud Storage**.
+- Send logs to a shared location instead of writing to local files.
+- Keep environment configs in a central place so each node starts with the same settings.
+
+---
+
+## 3️⃣ Database Connections Aren’t Free
+
+Every node opens its own database connections.
+Ten nodes with twenty connections each — that’s already two hundred open sessions.
+The database might not love that.
+
+
+
+**What helps:**
+- Put a cap on your connection pools.
+- Avoid keeping transactions open for too long.
+- Tune indexes and queries before scaling horizontally.
+
+---
+
+## 4️⃣ Logging and Observability Matter More Than You Think
+
+When something breaks in a distributed system, it’s never obvious which server was responsible.
+That’s why observability isn’t optional anymore.
+
+
+
+**Consider this:**
+- Stream logs to **ELK**, **Datadog**, or **Grafana Loki**.
+- Add a **trace ID** to every incoming request and propagate it across services.
+- Watch key metrics with **Prometheus** and visualize them in Grafana dashboards.
+
+---
+
+## 5️⃣ Background Jobs and Message Queues
+
+If more than one node runs the same job, you might process the same data twice — or delete something by mistake.
+You don’t want that kind of excitement in production.
+
+
+
+**A few precautions:**
+- Use a **distributed lock** or **leader election** system.
+- Make jobs **idempotent**, so running them twice doesn’t break data.
+- Centralize queue consumers or use a proper task scheduler.
+
+---
+
+## Wrapping Up
+
+Deploying to a cluster isn’t only about scaling up — it’s about staying stable when you do.
+Systems that handle state, logging, and background work correctly tend to age gracefully.
+Everything else eventually learns the hard way.
+
+> A cluster doesn’t fix design flaws — it magnifies them.
diff --git a/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/all.png b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/all.png
new file mode 100644
index 0000000000..71cbe984c4
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/all.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/background.png b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/background.png
new file mode 100644
index 0000000000..4d802e409d
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/background.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/cover-image.png b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/cover-image.png
new file mode 100644
index 0000000000..be4c03fda0
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/cover-image.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/database.png b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/database.png
new file mode 100644
index 0000000000..4a54b6f031
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/database.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/dev-to.md b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/dev-to.md
new file mode 100644
index 0000000000..d6df7eea53
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/dev-to.md
@@ -0,0 +1,27 @@
+# 5 Things You Should Keep in Mind When Deploying to a Clustered Environment
+
+Let’s be honest — moving from a single server to a cluster sounds simple on paper.
+You just add a few more machines, right?
+In practice, it’s the moment when small architectural mistakes start to grow legs.
+Below are a few things that experienced engineers usually double-check before pressing that “Deploy” button.
+
+---
+
+## 1️⃣ Managing State the Right Way
+---
+
+## 2️⃣ Shared Files and Where to Put Them
+---
+
+## 3️⃣ Database Connections Aren’t Free
+---
+
+## 4️⃣ Logging and Observability Matter More Than You Think
+---
+
+## 5️⃣ Background Jobs and Message Queues
+---
+
+
+
+👉 Read the full guide here: [5 Things You Should Keep in Mind When Deploying to a Clustered Environment](https://abp.io/community/articles/)
\ No newline at end of file
diff --git a/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/logging.png b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/logging.png
new file mode 100644
index 0000000000..c3100a672a
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/logging.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/shared.png b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/shared.png
new file mode 100644
index 0000000000..0331ce4a6a
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/shared.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/stateless.png b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/stateless.png
new file mode 100644
index 0000000000..6b12c03db8
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-5-Things-Deploy-Clustered-Environment/stateless.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/1.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/1.png
new file mode 100644
index 0000000000..55d5add034
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/1.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/10.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/10.png
new file mode 100644
index 0000000000..0e788ac942
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/10.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11.png
new file mode 100644
index 0000000000..86fd6a4b1f
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11_1.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11_1.png
new file mode 100644
index 0000000000..a438e6f9d8
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11_1.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/2.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/2.png
new file mode 100644
index 0000000000..cd517ae96e
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/2.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/3.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/3.png
new file mode 100644
index 0000000000..0760bc5f52
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/3.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/4.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/4.png
new file mode 100644
index 0000000000..a91b301825
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/4.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/5.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/5.png
new file mode 100644
index 0000000000..a1d3e366d1
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/5.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/6.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/6.png
new file mode 100644
index 0000000000..6dbc4a1b31
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/6.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/7.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/7.png
new file mode 100644
index 0000000000..37b364e931
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/7.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/8.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/8.png
new file mode 100644
index 0000000000..4af2381387
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/8.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/9.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/9.png
new file mode 100644
index 0000000000..14fe5473d7
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/9.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post.md b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post.md
new file mode 100644
index 0000000000..02790fde8b
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post.md
@@ -0,0 +1,251 @@
+# Optimize Your .NET App for Production (Complete Checklist)
+
+I see way too many .NET apps go to prod like it’s still “F5 on my laptop.” Here’s the checklist I wish someone shoved me years ago. It’s opinionated, pragmatic, copy-pasteable.
+
+------
+
+## 1) Publish Command and CSPROJ Settings
+
+
+
+Never go to production with debug build! See the below command which publishes properly a .NET app for production.
+
+```bash
+dotnet publish -c Release -o out -p:PublishTrimmed=true -p:PublishSingleFile=true -p:ReadyToRun=true
+```
+
+`csproj` for the optimum production publish:
+
+```xml
+
+ true
+ true
+ true
+ true
+
+```
+
+- **PublishTrimmed** It's trimmimg assemblies. What's that!? It removes unused code from your application and its dependencies, hence it reduces the output files.
+
+- **PublishReadyToRun** When you normally build a .NET app, your C# code is compiled into **IL** (Intrmediate Language). When your app runs, the JIT Compiler turns that IL code into native CPU commands. But this takes much time on startup. When you enable `PublishReadyToRun`, the build process precompiles your IL into native code and it's called AOT (Ahead Of Time). Hence your app starts faster... But the downside is; the output files are now a bit bigger. Another thing; it'll compile only for a specific OS like Windows and will not run on Linux anymore.
+
+- **Self-contained** When you publish your .NET app this way, it ncludes the .NET runtime inside your app files. It will run even on a machine that doesn’t have .NET installed. The output size gets larger, but the runtime version is exactly what you built with.
+
+
+
+------
+
+## 2) Kestrel Hosting
+
+
+
+By default, ASP.NET Core app listen only `localhost`, it means it accepts requests only from inside the machine. When you deploy to Docker or Kubernetes, the container’s internal network needs to expose the app to the outside world. To do this you can set it via environment variable as below:
+
+```bash
+ASPNETCORE_URLS=http://0.0.0.0:8080
+```
+
+Also if you’re building an internall API or a containerized microservice which is not multilngual, then add also the below setting. it disables operating system's globalization to reduce image size and dependencies..
+
+```bash
+DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
+```
+
+Clean `Program.cs` startup!
+Here's a minimal `Program.cs` which includes just the essential middleware and settings:
+
+```csharp
+var builder = WebApplication.CreateBuilder(args);
+
+builder.Logging.ClearProviders();
+builder.Logging.AddConsole();
+
+builder.Services.AddResponseCompression();
+builder.Services.AddResponseCaching();
+builder.Services.AddHealthChecks();
+
+var app = builder.Build();
+
+if (!app.Environment.IsDevelopment())
+{
+ app.UseExceptionHandler("/error");
+ app.UseHsts();
+}
+
+app.UseResponseCompression();
+app.UseResponseCaching();
+
+app.MapHealthChecks("/health");
+app.MapGet("/error", () => Results.Problem(statusCode: 500));
+
+app.Run();
+```
+
+
+
+------
+
+## 3) Garbage Collection and ThreadPool
+
+
+
+
+
+### GC Memory Cleanup Mode
+
+GC (Garbage Collection) is how .NET automatically frees memory. There are two main modes:
+
+- **Workstation GC:** good for desktop apps (focuses on responsiveness)
+- **Server GC:** good for servers (focuses on throughput)
+
+The below environment variable is telling the .NET runtime to use the *Server Garbage Collector (Server GC)* instead of the *Workstation GC*. Because our ASP.NET Core app must be optmized for servers not personal computers.
+
+```bash
+COMPlus_gcServer=1
+```
+
+### GC Limit Memory Usage
+
+Use at max 60% of the total available memory for the managed heap (the memory that .NET’s GC controls). So if your container or VM has, let's say 4 GB of RAM, .NET will try to keep the GC heap below 2.4 GB (60% of 4 GB). Especially when you run your app in containers, don’t let the GC assume host memory:
+
+```bash
+COMPlus_GCHeapHardLimitPercent=60
+```
+
+### Thread Pool Warm-up
+
+When your .NET app runs, it uses a thread pool. This is for handling background work like HTTP requests, async tasks, I/O things... By default, the thread pool starts small and grows dynamically as load increases. That’s good for desktop apps but for server apps it's too slow! Because during sudden peek of traffic, the app might waste time creating threads instead of handling requests. So below code keeps at least 200 worker threads and 200 I/O completion threads ready to go even if they’re idle.
+
+```csharp
+ThreadPool.SetMinThreads(200, 200);
+```
+
+
+
+------
+
+## 4) HTTP Performance
+
+
+
+### HTTP Response Compression
+
+`AddResponseCompression()` enables HTTP response compression. It shrinks your outgoing responses before sending them to the client. Making smaller payloads for faster responses and uses less bandwidth. Default compression method is `Gzip`. You can also add `Brotli` compression. `Brotli` is great for APIs returning JSON or text. If your CPU is already busy, keep the default `Gzip` method.
+
+```csharp
+builder.Services.AddResponseCompression(options =>
+{
+ options.Providers.Add();
+ options.EnableForHttps = true;
+});
+```
+
+
+
+### HTTP Response Caching
+
+Use caching for GET endpoints where data doesn’t change often (e.g., configs, reference data). `ETags` and `Last-Modified` headers tell browsers or proxies skip downloading data that hasn’t changed.
+
+- **ETag** = a version token for your resource.
+- **Last-Modified** = timestamp of last change.
+
+If a client sends `If-None-Match: "abc123"` and your resource’s `ETag` hasn’t changed, .NET automatically returns `304 Not Modified`.
+
+
+
+### HTTP/2 or HTTP/3
+
+These newer protocols make web requests faster and smoother. It's good for microservices or frontends making many API calls.
+
+- **HTTP/2** : multiplexing (many requests over one TCP connection).
+- **HTTP/3** : uses QUIC (UDP) for even lower latency.
+
+You can enable them on your reverse proxy (Nginx, Caddy, Kestrel)...
+.NET supports both out of the box if your environment allows it.
+
+
+
+### Minimal Payloads with DTOs
+
+The best practise here is; Never send/recieve your entire database entity, use DTOs. In the DTOs include only the fields the client actually needs by doing so you will keep the responses smaller and even safer. Also, prefer `System.Text.Json` (now it’s faster than `Newtonsoft.Json`) and for very high-traffic APIs, use source generation to remove reflection overhead.
+
+```csharp
+//define your entity DTO
+[JsonSerializable(typeof(MyDto))]
+internal partial class MyJsonContext : JsonSerializerContext { }
+
+//and simply serialize like this
+var json = JsonSerializer.Serialize(dto, MyJsonContext.Default.MyDto)
+```
+
+------
+
+## 5) Data Layer (Mostly Where Most Apps Slow Down!)
+
+
+
+### Reuse `DbContext` via Factory (Pooling)
+
+Creating a new `DbContext` for every query is expensive! Use `IDbContextFactory`, it gives you pooled `DbContext` instances from a pool that reuses objects instead of creating them from scratch.
+
+```csharp
+services.AddDbContextFactory(options =>
+ options.UseSqlServer(connectionString));
+```
+
+Then inject the factory:
+
+```csharp
+using var db = _contextFactory.CreateDbContext();
+```
+
+Also, ensure your database server (SQL Server, PostgreSQL....) has **connection pooling enabled**.
+
+------
+
+### N+1 Query Problem
+
+The N+1 problem occurs when your app runs **one query for the main data**, then **N more queries for related entities**. That kills performance!!!
+
+**Bad-Practise:**
+
+```csharp
+var users = await context.Users.Include(u => u.Orders).ToListAsync();
+```
+
+**Good-Practise:**
+Project to DTOs using `.Select()` so EF-Core generates a single optimized SQL query:
+
+```csharp
+var users = await context.Users.Select(u => new UserDto
+ {
+ Id = u.Id,
+ Name = u.Name,
+ OrderCount = u.Orders.Count
+ }).ToListAsync();
+```
+
+------
+
+### **Indexes**
+
+Use EF Core logging, SQL Server Profiler, or `EXPLAIN` (Postgres/MySQL) to find slow queries. Add missing indexes **only** where needed. For example [at this page](https://blog.sqlauthority.com/2011/01/03/sql-server-2008-missing-index-script-download/), he wrote an SQL query which lists missing index list (also there's another version at [Microsoft Docs](https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-db-missing-index-details-transact-sql?view=sql-server-ver17)). This perf improvement is mostly applied after running the app for a period of time.
+
+
+
+------
+
+### Migrations
+
+In production run migrations manually, never do it on app startup. That way you can review schema changes, back up data and avoid breaking the live DB.
+
+
+
+------
+
+### Resilience with Polly
+
+Use [Polly](https://www.pollydocs.org/) for retries, timeouts and circuit breakers for your DB or HTTP calls. Handles short outages gracefully
+
+*To keep the article short and for the better readability I spitted it into 2 parts 👉 [Continue with the second part here](https://abp.io/community/articles/optimize-your-dotnet-app-for-production-for-any-.net-app-2-78xgncpi)...*
+
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post2.md b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post2.md
new file mode 100644
index 0000000000..8d5aca4a1a
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/Post2.md
@@ -0,0 +1,267 @@
+*If you’ve landed directly on this article, note that it’s part-2 of the series. You can read part-1 here: [Optimize Your .NET App for Production (Part 1)](https://abp.io/community/articles/optimize-your-dotnet-app-for-production-for-any-.net-app-wa24j28e)*
+
+## 6) Telemetry (Logs, Metrics, Traces)
+
+
+
+The below code adds `OpenTelemetry` to collect app logs, metrics, and traces in .NET.
+
+```csharp
+builder.Services.AddOpenTelemetry()
+ .UseOtlpExporter()
+ .WithMetrics(m => m.AddAspNetCoreInstrumentation().AddHttpClientInstrumentation())
+ .WithTracing(t => t.AddAspNetCoreInstrumentation().AddHttpClientInstrumentation());
+```
+
+- `UseOtlpExporter()` Tells it where to send telemetry. Usually that’s an OTLP collector (like Grafana , Jaeger, Tempo, Azure Monitor). So you can visualize metrics and traces in dashboards.
+- `WithMetrics()` means it'll collects metrics. These metrics are Request rate (RPS), Request duration (latency), GC pauses, Exceptions, HTTP client timings.
+- `.WithTracing(...)` means it'll collect distributed traces. That's useful when your app calls other APIs or microservices. You can see the full request path from one service to another with timings and bottlenecks.
+
+### .NET Diagnostic Tools
+
+When your app is on-air, you should know about the below tools. You know in airplanes there's _black box recorder_ which is used to understand why the airplane crashed. For .NET below are our *black box recorders*. They capture what happened without attaching a debugger.
+
+| Tool | What It Does | When to Use |
+| --------------------- | --------------------------------------- | ---------------------------- |
+| **`dotnet-counters`** | Live metrics like CPU, GC, request rate | Monitor running apps |
+| **`dotnet-trace`** | CPU sampling & performance traces | Find slow code |
+| **`dotnet-gcdump`** | GC heap dumps (allocations) | Diagnose memory issues |
+| **`dotnet-dump`** | Full process dumps | Investigate crashes or hangs |
+| **`dotnet-monitor`** | HTTP service exposing all the above | Collect telemetry via API |
+
+
+
+------
+
+## 7) Build & Run .NET App in Docker the Right Way
+
+
+
+A multi-stage build is a Docker technique where you use one image for building your app and another smaller image for running it. Why we do multi-stage build, because the .NET SDK image is big but has all the build tools. The .NET Runtime image is small and optimized for production. You copy only the published output from the build stage into the runtime stage.
+
+```dockerfile
+# build
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
+WORKDIR /src
+COPY . .
+RUN dotnet restore
+RUN dotnet publish -c Release -o /app/out -p:PublishTrimmed=true -p:PublishSingleFile=true -p:ReadyToRun=true
+
+# run
+FROM mcr.microsoft.com/dotnet/aspnet:9.0
+WORKDIR /app
+ENV ASPNETCORE_URLS=http://+:8080
+EXPOSE 8080
+COPY --from=build /app/out .
+ENTRYPOINT ["./YourApp"] # or ["dotnet","YourApp.dll"]
+```
+
+I'll explain what these Docker file commands;
+
+**Stage1: Build**
+
+* `FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build`
+ Uses the .NET SDK image including compilers and tools. The `AS build` name lets you reference this stage later.
+
+* `WORKDIR /src`
+ Sets the working directory inside the container.
+
+* `COPY . .`
+ Copies your source code into the container.
+
+* `RUN dotnet restore`
+ Restores NuGet packages.
+
+* `RUN dotnet publish ...`
+ Builds the project in **Release** mode, optimizes it for production, and outputs it to `/app/out`.
+ The flags;
+ * `PublishTrimmed=true` -> removes unused code
+ * `PublishSingleFile=true` -> bundles everything into one file
+ * `ReadyToRun=true` -> precompiles code for faster startup
+
+**Stage 2: Run**
+
+- `FROM mcr.microsoft.com/dotnet/aspnet:9.0`
+ Uses a lighter runtime image which no compiler, just the runtime.
+- `WORKDIR /app`
+ Where your app will live inside the container.
+- `ENV ASPNETCORE_URLS=http://+:8080`
+ Makes the app listen on port 8080 (and all network interfaces).
+- `EXPOSE 8080`
+ Documents the port your container uses (for Docker/K8s networking).
+- `COPY --from=build /app/out .`
+ Copies the published output from the **build stage** to this final image.
+- `ENTRYPOINT ["./YourApp"]`
+ Defines the command that runs when the container starts. If you published as a single file, it’s `./YourApp`. f not, use `dotnet YourApp.dll`.
+
+
+
+------
+
+## 8) Security
+
+
+
+### HTTPS Everywhere Even Behind Proxy
+
+Even if your app runs behind a reverse proxy like Nginx, Cloudflare or a load balancer, always enforce HTTPS. Why? Because internal traffic can still be captured if you don't use SSL and also cookies, HSTS, browser APIs require HTTPS. In .NET, you can easily enforce HTTPS like this:
+
+```csharp
+app.UseHttpsRedirection();
+```
+
+
+
+### Use HSTS in Production
+
+HSTS (HTTP Strict Transport Security) tells browsers:
+
+> Always use HTTPS for this domain — don’t even try HTTP again!
+
+Once you set, browsers cache this rule, so users can’t accidentally hit the insecure version. You can easily enforce this as below:
+
+```csharp
+if (!app.Environment.IsDevelopment())
+{
+ app.UseHsts();
+}
+```
+
+When you use HSTS, it sends browser this HTTP header: ` Strict-Transport-Security: max-age=31536000; includeSubDomains`. Browser will remember this setting for 1 year (31,536,000 seconds) that this site must only use HTTPS. And `includeSubDomains` option applies the rule to all subdomains as well (eg: `api.abp.io`, `cdn.abp.io`, `account.abp.io` etc..)
+
+### Store Secrets on Environment Variables or Secret Stores
+
+Never store passwords, connection strings, or API keys in your code or Git. Then where should we keep them?
+
+- Best/practical way is **Environment variables**. You can easily sett an environment variable in a Unix-like system as below:
+
+ - ```bash
+ export ConnectionStrings__Default="Server=...;User Id=...;Password=..."
+ ```
+
+- And you can easily access these environment variables from your .NET app like this:
+
+ - ```csharp
+ var conn = builder.Configuration.GetConnectionString("Default");
+ ```
+
+Or **Secret stores** like: Azure Key Vault, AWS Secrets Manager, HashiCorp Vault
+
+
+
+### Add Rate-Limiting to Public Endpoints
+
+Don't forget there'll be not naive guys who will use your app! We've many times faced this issue in the past on our public front-facing websites. So protect your public APIs from abuse, bots, and DDoS. Use rate-limiting!!! Stop brute-force attacks, prevent your resources from exhaustion...
+
+In .NET, there's a built-in rate-limit feature for .NET (System.Threading.RateLimiting):
+
+```csharp
+builder.Services.AddRateLimiter(_ => _
+ .AddFixedWindowLimiter("default", options =>
+ {
+ options.PermitLimit = 100;
+ options.Window = TimeSpan.FromMinutes(1);
+ }));
+
+app.UseRateLimiter();
+```
+
+- Also there's an open-source rate-limiting library -> [github.com/stefanprodan/AspNetCoreRateLimit](https://github.com/stefanprodan/AspNetCoreRateLimit)
+- Another one -> [nuget.org/packages/Polly.RateLimiting](https://www.nuget.org/packages/Polly.RateLimiting)
+
+### Secure Cookies
+
+Cookies are often good targets for attacks. You must secure them properly otherwise you can face cookie stealing or CSRF attack.
+
+```csharp
+options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
+options.Cookie.SameSite = SameSiteMode.Strict; // or Lax
+```
+
+- **`SecurePolicy = Always`** -> only send cookies over HTTPS
+- **`SameSite=Lax/Strict`** -> prevent CSRF (Cross-Site Request Forgery)
+ - `Strict` = safest
+ - `Lax` = good balance for login sessions
+
+
+
+------
+
+## 9) Startup/Cold Start
+
+
+
+### Keep Tiered JIT On
+
+The **JIT (Just-In-Time) compiler** converts your app’s Intermediate Language (IL) into native CPU instructions when the code runs. _Tiered JIT_ means the runtime uses 2 stages of compilation. Actually this setting is enabled by default in modern .NET. So just keep it on.
+
+1. **Tier 0 (Quick JIT):**
+ Fast, low-optimization compile → gets your app running ASAP.
+ (Used at startup.)
+2. **Tier 1 (Optimized JIT):**
+ Later, the runtime re-compiles *hot* methods (frequently used ones) with deeper optimizations for speed.
+
+
+
+### Use PGO (Profile-Guided Optimization)
+
+PGO lets .NET learn from real usage of your app. It profiles which functions are used most often, then re-optimizes the build for that pattern. You can think of it as the runtime saying:
+
+> I’ve seen what your app actually does... I’ll rearrange and optimize code paths accordingly.
+
+In .NET 8+, you don’t have to manually enable PGO (Profile-Guided Optimization). The JIT collects runtime profiling data (e.g. which types are common, branch predictions) and uses it to generate more optimized code later. In .NET 9, PGO has been improved: the JIT uses PGO data for more patterns (like type checks / casts) and makes better decisions.
+
+
+
+------
+
+## 10) Graceful Shutdown
+
+
+
+When we break up with our lover, we often argue and regret it later. When an application breaks up with an operating system, it should be done well 😘 ...
+When your app stops, maybe you deploy a new version or Kubernetes restarts a pod... the OS sends a signal called `SIGTERM` (terminate).
+A **graceful shutdown** means handling that signal properly, finishing what’s running, cleaning up, and exiting cleanly (like an adult)!
+
+```csharp
+var app = builder.Build();
+var lifetime = app.Services.GetRequiredService();
+lifetime.ApplicationStopping.Register(() =>
+{
+ // stop accepting, finish in-flight, flush telemetry
+});
+app.Run();
+```
+
+On K8s, set `terminationGracePeriodSeconds` and wire **readiness**/startup probes.
+
+------
+
+## 11) Load Test
+
+
+
+Sometimes arguing with our lover is good. We can see her/his face before marrying 😀 Use **k6** or **bombardier** and test with realistic payloads and prod-like limits. Don't be surprise later when your app is running on prod! These topics should be tested: `CPU %` , `Time in GC` , `LOH Allocations` , `ThreadPool Queue Length` and `Socket Exhaustion`.
+
+### About K6
+
+- A modern load testing tool, using Go and JavaScript.
+
+- 29K stars on GitHub
+- GitHub address: https://github.com/grafana/k6
+
+### About Bombardier
+
+- Fast cross-platform HTTP benchmarking tool written in Go.
+
+- 7K stars on GitHub
+- GitHub address: https://github.com/codesenberg/bombardier
+
+[](https://trends.google.com/trends/explore?cat=31&q=bombardier%20%2B%20benchmarking,k6%20%2B%20benchmarking)
+
+## Summary
+
+In summary, I listed 11 items for optimizing a .NET application for production; Covering build configuration, hosting setup, runtime behavior, data access, telemetry, containerization, security, startup performance and reliability under load. By applying the checklist from Part 1 and Part 2 of this series, leveraging techniques like trimmed releases, server GC, minimal payloads, pooled `DbContexts`, OpenTelemetry, multi-stage Docker builds, HTTPS enforcement, and proper shutdown handling—you’ll improve your app’s durability, scalability and maintainability under real-world traffic and production constraints. Each item is a checkpoint and you’ll be able to deliver a robust, high-performing .NET application ready for live users.
+
+🎉 Want top-tier .NET performance without the headaches? Try [ABP Framework](https://abp.io?utm_source=alper-ebicoglu-performance-article) for best-performance and skip all the hustles of .NET app development.
+
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/cover-2.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/cover-2.png
new file mode 100644
index 0000000000..4f466fd11c
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/cover-2.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/cover.png b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/cover.png
new file mode 100644
index 0000000000..f9935df03c
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/cover.png differ
diff --git a/docs/en/Community-Articles/2025-10-17-Top-10-Exception-Handling-Mistakes-in-DotNET/post.md b/docs/en/Community-Articles/2025-10-17-Top-10-Exception-Handling-Mistakes-in-DotNET/post.md
new file mode 100644
index 0000000000..3360fd0e20
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-17-Top-10-Exception-Handling-Mistakes-in-DotNET/post.md
@@ -0,0 +1,356 @@
+# 💥 Top 10 Exception Handling Mistakes in .NET (and How to Actually Fix Them)
+
+Every .NET developer has been there it's 3 AM, production just went down, and the logs are flooding in.
+You open the error trace, only to find… nothing useful. The stack trace starts halfway through a catch block, or worse it's empty. Somewhere, an innocent-looking `throw ex;` or a swallowed background exception has just cost hours of sleep.
+
+Exception handling is one of those things that seems simple on the surface but can quietly undermine an entire system if done wrong. Tiny mistakes like catching `Exception`, forgetting an `await`, or rethrowing incorrectly don't just break code; they break observability. They hide root causes, produce misleading logs, and make even well-architected applications feel unpredictable.
+
+In this article, we'll go through the most common exception handling mistakes developers make in .NET and more importantly, how to fix them. Along the way, you'll see how small choices in your code can mean the difference between a five-minute fix and a full-blown production nightmare.
+
+----------
+
+## 🧨 1. Catching `Exception` (and Everything Else)
+
+**The mistake:**
+
+```csharp
+try
+{
+ // Some operation
+}
+catch (Exception ex)
+{
+ // Just to be safe
+}
+
+```
+
+**Why it's a problem:**
+Catching the base `Exception` type hides all context including `OutOfMemoryException`, `StackOverflowException`, and other runtime-level issues that you should never handle manually. It also makes debugging painful since you lose the ability to treat specific failures differently.
+
+**The right way:**
+Catch only what you can handle:
+
+```csharp
+catch (SqlException ex)
+{
+ // Handle DB issues
+}
+catch (IOException ex)
+{
+ // Handle file issues
+}
+
+```
+
+If you really must catch all exceptions (e.g., at a system boundary), **log and rethrow**:
+
+```csharp
+catch (Exception ex)
+{
+ _logger.LogError(ex, "Unexpected error occurred");
+ throw;
+}
+
+```
+
+> 💡 **ABP Tip:** In ABP-based applications, you rarely need to catch every exception at the controller or service level.
+> The framework's built-in `AbpExceptionFilter` already handles unexpected exceptions, logs them, and returns standardized JSON responses automatically keeping your controllers clean and consistent.
+
+----------
+
+## 🕳️ 2. Swallowing Exceptions Silently
+
+**The mistake:**
+
+```csharp
+try
+{
+ DoSomething();
+}
+catch
+{
+ // ignore
+}
+
+```
+
+**Why it's a problem:**
+Silent failures make debugging nearly impossible. You lose stack traces, error context, and sometimes even awareness that something failed at all.
+
+**The right way:**
+Always log or rethrow, unless you have a very specific reason not to:
+
+```csharp
+try
+{
+ _cache.Remove(key);
+}
+catch (Exception ex)
+{
+ _logger.LogWarning(ex, "Failed to clear cache key {Key}", key);
+}
+
+```
+
+> 💡 **ABP Tip:** Since ABP automatically logs all unhandled exceptions, it's often better to let the framework handle them. Only catch exceptions when you want to enrich logs or add custom business logic before rethrowing.
+
+----------
+
+## 🌀 3. Using `throw ex;` Instead of `throw;`
+
+**The mistake:**
+
+```csharp
+catch (Exception ex)
+{
+ Log(ex);
+ throw ex;
+}
+
+```
+
+**Why it's a problem:**
+Using `throw ex;` resets the stack trace you lose where the exception actually occurred. This is one of the biggest causes of misleading production logs.
+
+**The right way:**
+
+```csharp
+catch (Exception ex)
+{
+ Log(ex);
+ throw; // preserves stack trace
+}
+
+```
+
+----------
+
+## ⚙️ 4. Wrapping Everything in Try/Catch
+
+**The mistake:**
+Developers sometimes wrap _every function_ in try/catch “just to be safe.”
+
+**Why it's a problem:**
+This clutters your code and hides the real source of problems. Exception handling should happen at **system boundaries**, not in every method.
+
+**The right way:**
+Handle exceptions at higher levels (e.g., middleware, controllers, background jobs). Let lower layers throw naturally.
+
+> 💡 **ABP Tip:** The ABP Framework provides a top-level exception pipeline via filters and middleware. You can focus purely on your business logic ABP automatically translates unhandled exceptions into standardized API responses.
+
+----------
+
+## 📉 5. Using Exceptions for Control Flow
+
+**The mistake:**
+
+```csharp
+try
+{
+ var user = GetUserById(id);
+}
+catch (UserNotFoundException)
+{
+ user = CreateNewUser();
+}
+
+```
+
+**Why it's a problem:**
+Exceptions are expensive and should represent _unexpected_ states, not normal control flow.
+
+**The right way:**
+
+```csharp
+var user = GetUserByIdOrDefault(id) ?? CreateNewUser();
+
+```
+
+----------
+
+## 🪓 6. Forgetting to Await Async Calls
+
+**The mistake:**
+
+```csharp
+try
+{
+ DoSomethingAsync(); // missing await!
+}
+catch (Exception ex)
+{
+ ...
+}
+
+```
+
+**Why it's a problem:**
+Without `await`, the exception happens on another thread, outside your `try/catch`. It never gets caught.
+
+**The right way:**
+
+```csharp
+try
+{
+ await DoSomethingAsync();
+}
+catch (Exception ex)
+{
+ _logger.LogError(ex, "Error during async operation");
+}
+
+```
+
+----------
+
+## 🧵 7. Ignoring Background Task Exceptions
+
+**The mistake:**
+
+```csharp
+Task.Run(() => SomeWork());
+
+```
+
+**Why it's a problem:**
+Unobserved task exceptions can crash your process or vanish silently, depending on configuration.
+
+**The right way:**
+
+```csharp
+_ = Task.Run(async () =>
+{
+ try
+ {
+ await SomeWork();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Background task failed");
+ }
+});
+
+```
+
+----------
+
+## 📦 8. Throwing Generic Exceptions
+
+**The mistake:**
+
+```csharp
+throw new Exception("Something went wrong");
+
+```
+
+**Why it's a problem:**
+Generic exceptions carry no semantic meaning. You can't catch or interpret them specifically later.
+
+**The right way:**
+Use more descriptive types:
+
+```csharp
+throw new InvalidOperationException("Order is already processed");
+
+```
+
+> 💡 **ABP Tip:** In ABP applications, you can throw a `BusinessException` or `UserFriendlyException` instead.
+> These support structured data, error codes, localization, and automatic HTTP status mapping:
+>
+> ```csharp
+> throw new BusinessException("App:010046")
+> .WithData("UserName", "john");
+>
+> ```
+>
+> This integrates with ABP's localization system, letting your error messages be translated automatically based on the error code.
+
+----------
+
+## 🪞 9. Losing Inner Exceptions
+
+**The mistake:**
+
+```csharp
+catch (Exception ex)
+{
+ throw new CustomException("Failed to process order");
+}
+
+```
+
+**Why it's a problem:**
+You lose the inner exception and its stack trace the real reason behind the failure.
+
+**The right way:**
+
+```csharp
+catch (Exception ex)
+{
+ throw new CustomException("Failed to process order", ex);
+}
+
+```
+
+> 💡 **ABP Tip:** ABP automatically preserves and logs inner exceptions (for example, inside `BusinessException` chains). You don't need to add boilerplate to capture nested errors just throw them properly.
+
+----------
+
+## 🧭 10. Missing Global Exception Handling
+
+**The mistake:**
+Catching exceptions manually in every controller.
+
+**Why it's a problem:**
+It creates duplicated logic, inconsistent responses, and gaps in logging.
+
+**The right way:**
+Use middleware or a global exception filter:
+
+```csharp
+app.UseExceptionHandler("/error");
+
+```
+
+> 💡 **ABP Tip:** ABP already includes a complete global exception system that:
+>
+> - Logs exceptions automatically
+>
+> - Returns a standard `RemoteServiceErrorResponse` JSON object
+>
+> - Maps exceptions to correct HTTP status codes (e.g., 403 for business rules, 404 for entity not found, 400 for validation)
+>
+> - Allows customization through `AbpExceptionHttpStatusCodeOptions`
+> You can even implement an `ExceptionSubscriber` to react to certain exceptions (e.g., send notifications or trigger audits).
+>
+
+----------
+
+## 🧩 Bonus: Validation Is Not an Exception
+
+**The mistake:**
+Throwing exceptions for predictable user input errors.
+
+**The right way:**
+Use proper validation instead:
+
+```csharp
+[Required]
+public string UserName { get; set; }
+
+```
+
+> 💡 **ABP Tip:** ABP automatically throws an `AbpValidationException` when DTO validation fails.
+> You don't need to handle this manually ABP formats it into a structured JSON response with `validationErrors`.
+
+----------
+
+## 🧠 Final Thoughts
+
+Exception handling isn't just about preventing crashes it's about making your failures **observable, meaningful, and recoverable**.
+When done right, your logs tell a story: _what happened, where, and why_.
+When done wrong, you're left staring at a 3 AM mystery.
+
+By avoiding these common pitfalls and taking advantage of frameworks like ABP that handle the heavy lifting you'll spend less time chasing ghosts and more time building stable, predictable systems.
+
diff --git a/docs/en/Community-Articles/2025-10-20-The-ASP-DotNET-Core-Dependency-Injection System/post.md b/docs/en/Community-Articles/2025-10-20-The-ASP-DotNET-Core-Dependency-Injection System/post.md
new file mode 100644
index 0000000000..0a3959b44f
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-20-The-ASP-DotNET-Core-Dependency-Injection System/post.md
@@ -0,0 +1,1174 @@
+# The ASP.NET Core Dependency Injection System
+
+## Article Overview
+
+This article provides a guide to **ASP.NET Core Dependency Injection**, a fundamental element of .NET development. We'll examine the built in Inversion of Control (IoC) container, examining the critical differences between service lifecycles (scoped, singleton, or transient), and comparing constructor injection to property injection.
+
+You'll learn how to effectively register your services with patterns like `TryAdd` methods and the **Options Pattern**, how to adhere to established best practices like avoiding captive dependencies and asynchronous constructor logic, how to understand patterns like decorators and explicit generics, how to leverage manual scope management with `IServiceScopeFactory`, how to implement proper asynchronous disposal with `IAsyncDisposable`, and how to analyze the performance impact of your DI strategy, including the new compile time source generation features that enable native AOT support in .NET 9. Ultimately, you'll have the knowledge to create loosely coupled, maintainable, and testable applications using the advanced dependency injection patterns in .NET 9. Of course, the explanations here are general, if you'd like to delve deeper, you can check out the references section.
+
+## Introduction to Dependency Injection
+
+Dependency Injection (DI) is a design pattern used to implement Inversion of Control (IoC), in which control of object creation and binding is transferred from the object itself to another container or framework. In the context of ASP.NET Core, DI is a tool integrated into the framework for managing the lifecycle and creation of application components.
+
+### The Evolution from .NET Framework to .NET Core and .NET 9
+
+The journey of dependency injection in the .NET ecosystem represents a sweeping architectural shift. .NET Framework applications (prior to 2016) typically relied on third party IoC containers such as
+
+- **Unity** (Microsoft's own container, often used in enterprise applications)
+- **Autofac** (popular for its advanced features and fluent API)
+- **Ninject** (known for its simplicity)
+- **StructureMap** (one of the earliest .NET IoC containers)
+- **Castle Windsor** (powerful but complex)
+
+Many legacy applications have fallen back to anti patterns like the **Service Locator pattern**, which hides dependencies and makes testing difficult.
+
+When ASP.NET Core was released in 2016, Microsoft made a decision to integrate dependency injection directly into the runtime. This meant:
+
+- **Standardization:** Creating a consistent DI approach across all .NET Core applications.
+- **Performance:** Creating a lightweight, optimized container designed for workloads.
+- **Simplicity:** No need to choose third party containers for basic scenarios.
+- **Cloud Native Ready:** Designed for microservices, containers, and serverless architectures.
+
+Now, with **.NET 9**, the DI container has become even more advanced as follows:
+
+- **Source generated DI** for faster startup and AOT compatibility.
+- **Keyed services** for advanced solution scenarios.
+- **Lifetime validation** to catch common errors during development.
+
+Unlike .NET Framework applications, which required installing these containers as third-party packages and often present issues with consistency, in ASP.NET Core, and now in .NET 9, dependency injection is a fundamental part of the architecture.
+
+### Why is Dependency Injection important?
+
+The key benefits of adopting a DI strategy would be.
+
+ * **Loose Coupling:** Components don't create their dependencies directly. Instead, they get them from the DI container. This means you can change the implementation of a dependency without changing the component that uses it.
+ * **Testability:** Once dependencies are added, you can easily replace them with mocks or mock implementations in your unit tests. This will allow you to test components in isolation.
+ * **Maintenance and Scalability:** A loosely coupled architecture is easier to manage, refactor, and extend. New features can be added with minimal changes to existing code.
+
+This article provides a guide for developers covering the basic mechanisms of Dependency Injection in .NET and the performance models available in .NET 9.
+
+## The Built in IoC Container in ASP.NET Core
+
+ASP.NET Core ships with the lightweight yet comprehensive **ASP.NET Core IoC container**. It's not designed to have all the features of third party tools, but it provides the basic functionality needed for most applications.
+
+The two basic interfaces representing the structure are as follows:
+
+ * `IServiceCollection`: This is the "registration" side of the structure. When the application starts up, you add your services or dependencies to this collection.
+ * `IServiceProvider`: This is the "resolving" side of the structure. After the application is created, `IServiceProvider` is used to retrieve instances of registered services.
+
+### Comparison with Third Party Tools
+
+While the internal structure is sufficient for many scenarios, you can easily modify it if you need more features, such as:
+
+ * **Automatic registration / Assembly Scan:** Automatically register types based on contracts.
+ * **Interception / Decorators:** Providing more support for packaging services with cross cutting concerns.
+ * **Child Containers:** Some tools, such as Autofac, allow you to create nested sub containers with their own lifetimes, which can be useful for isolating components in complex applications. The built in framework uses a simpler scoping mechanism.
+
+
+## Service Lifetimes in ASP.NET Core
+
+When registering a service, you must specify its lifetime. The lifetime determines how long a service instance will be valid. Understanding the difference between **scoped, singleton, and transient** is important for building stable and optimized applications.
+
+### Transient
+
+A new instance of a transient service is created **each time** it is requested from the container.
+
+ * **When to use:** For lightweight, stateless services.
+ * `builder.Services.AddTransient();`
+
+### Scoped
+
+A single instance of a scoped service is created once per client request (or per scope). The same instance is shared within that single request.
+
+ * **When to use:** It is more appropriate to use it for services that need to maintain state within a single request, such as `DbContext` or Unit of Work.
+ * `builder.Services.AddScoped();`
+
+### Singleton
+
+A single instance of the service is created once during the entire application lifetime.
+
+ * **When to use:** Commonly used for stateless services that are source intensive to create or need to share their state extensively, such as application configuration or caching services.
+ * `builder.Services.AddSingleton();`
+
+> **Considered Best Practice: Avoid Captive Dependencies**
+> A common mistake is injecting a deep, scoped service (for example, `MyDbContext`) into a singleton service. Because the singleton service lives forever, it will keep the scoped service in the container structure for the lifetime of the application, converting it to a singleton service. This can lead to memory leaks and erratic behavior across requests. ASP.NET Core throws an exception at runtime to help you detect this during development.
+
+### Manual Scope Management with `IServiceScopeFactory`
+
+In scenarios where you need to manually create and manage scopes (background workers, singleton services, or long running tasks), you can use `IServiceScopeFactory` to create scopes.
+
+This would be particularly useful when properly controlling when a singleton service needs to use scoped dependencies without causing captive dependency problems.
+
+Within continuously running services, you must not directly inject objects that require short lifespans, such as database connections. This code example solves this problem by creating a temporary workspace for each task using a "throw away" approach. The environment and necessary services are created when the process starts, and all are automatically cleaned up when the task ends. This method utilizes sources efficiently and prevents memory leaks.
+
+```csharp
+public class DataProcessingService
+{
+ private readonly IServiceScopeFactory _scopeFactory;
+
+ public DataProcessingService(IServiceScopeFactory scopeFactory)
+ {
+ _scopeFactory = scopeFactory;
+ }
+
+ public async Task ProcessDataAsync()
+ {
+ // Create a new scope for this unit of work
+ await using (var scope = _scopeFactory.CreateAsyncScope())
+ {
+ var dbContext = scope.ServiceProvider.GetRequiredService();
+ var repository = scope.ServiceProvider.GetRequiredService();
+
+ // Perform scoped work
+ var data = await repository.GetPendingDataAsync();
+ await dbContext.SaveChangesAsync();
+ }
+ // Scope is disposed here, releasing all scoped services
+ }
+}
+```
+
+**Key Points:**
+- We should use `CreateAsyncScope()` when working with asynchronous disposal.
+- It would be logical to use `CreateScope()` for synchronous scenarios.
+- Always destroying scopes appropriately using `using` or `await using` statements is important for scope management and optimization.
+
+
+Here is the detailed explanation, incorporating your text and adding the requested details for property injection.
+
+## Constructor Injection vs. Property Injection
+
+There are several ways a class can receive its dependencies. The two most common patterns are **constructor** and **property** injection.
+
+### Constructor Injection
+
+With constructor injection, a class retrieves its dependencies from the container via constructor parameters. With dependency injection (DI), the container will be responsible for creating instances of these dependencies and fetching them when the class is generated. This is one of the most common and recommended approaches to **ASP.NET Core Dependency Injection**.
+
+```csharp
+// Primary Constructors
+public class OrderService(IOrderRepository orderRepository, ILogger logger)
+{
+ private readonly IOrderRepository _orderRepository = orderRepository;
+
+ private readonly ILogger _logger = logger;
+ public async Task GetOrderAsync(int orderId)
+ {
+ _logger.LogInformation("Fetching order {OrderId}", orderId);
+ return await _orderRepository.GetByIdAsync(orderId);
+ }
+}
+
+// Traditional Class Constructor
+public class OrderService
+{
+ private readonly IOrderRepository _orderRepository;
+ private readonly ILogger _logger;
+
+ public OrderService(IOrderRepository orderRepository, ILogger logger)
+ {
+ _orderRepository = orderRepository;
+ _logger = logger;
+ }
+
+ public async Task GetOrderAsync(int orderId)
+ {
+ _logger.LogInformation("Fetching order {OrderId}", orderId);
+ return await _orderRepository.GetByIdAsync(orderId);
+ }
+}
+```
+
+#### Pros:
+
+ * **Explicit Dependencies:** The constructor's signature explicitly states all **required** dependencies. A developer will immediately see what the class needs to function when calling it.
+ * **Immutability:** Dependencies can be assigned to `readonly` fields so that they cannot be changed after the object is created. This will lead to more stable and predictable class behavior.
+ * **Availability:** The class is guaranteed to have the required dependencies when created. It will not need to perform null checks on required services.
+ * **Startup Validation:** If a required dependency is not registered in the DI container, the application will fail *on startup* (at runtime), making errors easy to detect early.
+
+> **Best Practice: Avoid Asynchronous Operations in Constructors**
+> A constructor is expected to be simple and fast. We should not perform asynchronous operations (`await`) or long running tasks within a constructor. This can lead to deadlocks and unpredictable application startup behavior. Using asynchronous factory patterns or `IHostedService` for asynchronous startup logic will fix this issue in most scenarios.
+
+
+### Property Injection
+
+With property injection (also known as "setter injection"), dependencies are provided through publicly settable properties on the class. The dependency is injected after the class is created.
+
+This pattern is less common in ASP.NET Core because the built in DI container will not support it out of the box (other third party containers like Autofac or Ninject do support it).
+
+Property injection is almost exclusively used for **optional dependencies**, which would be services that the class could use but doesn't need to perform its core functionality.
+
+```csharp
+public class ProductService
+{
+ private readonly IProductRepository _productRepository;
+
+ // Injected via a public property
+ public ILogger? Logger { get; set; }
+
+ // Still injected via the constructor
+ public ProductService(IProductRepository productRepository)
+ {
+ _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository));
+ }
+
+ public async Task GetProductAsync(int productId)
+ {
+ // Must check if the optional dependency was injected before using it
+ Logger?.LogInformation("Fetching product {ProductId}", productId);
+
+ return await _productRepository.GetByIdAsync(productId);
+ }
+}
+```
+
+Since the built in container doesn't automatically set the `Logger` property, you would either have to use a different container or set it manually (which partially defeats the purpose of DI). This is why it's strongly discouraged for *required* dependencies.
+
+#### Pros:
+
+ * **Optional Dependencies:** Can be used to provide optional services. The class can function without the dependency, but if a dependency is provided, its behavior needs to be improved.
+ * **Decoupling:** It can help to break up large classes or prevent over injection in the constructor (constructors with too many parameters), but this usually indicates that the class is doing too much (Single Responsibility Principle).
+
+#### Cons:
+
+ * **Hidden Dependencies:** It won't be immediately obvious from the constructor what the class might depend on. Because of the way it's implemented, this means a developer will need to examine the class's properties.
+ * **Mutability:** This means that the dependency will not be readonly and can be changed at any time, which may lead to unforeseen situations and changes.
+ * **Null Check:** The class should always check if the optional dependency is `null` before using it.
+ * **No Container Support:** The default ASP.NET Core container will not inject properties. This makes this pattern unusable unless you use a different container or manually add dependencies.
+
+
+## Registering Services in ASP.NET Core
+
+Services are registered in the DI container in `Program.cs`. This means adding the services to the `IServiceCollection`.
+
+### Basic and Factory based Registrations
+
+You can add an interface to a concrete class or use a factory based registration style for complex initialization.
+
+**In Program.cs**
+```csharp
+var builder = WebApplication.CreateBuilder(args);
+
+// Simple registration
+builder.Services.AddScoped();
+
+// Factory based registration
+builder.Services.AddScoped(provider =>
+{
+ // Resolve other service
+ var logger = provider.GetRequiredService>();
+ var someValue = "CalculatedOrRetrievedValue";
+
+ // Manually build with dependencies
+ return new SomeComplexService(logger, someValue);
+});
+```
+
+### Conditional `TryAdd` Registrations
+
+When developing reusable libraries or building dependent applications, you may want to register a service only if another application has not already registered it, and you may want to check for it. The `TryAdd` method is used for this scenario.
+
+**Available Methods:**
+- `TryAddSingleton()` Adds the singleton if it is not already registered
+- `TryAddScoped()` Adds scoped if not already registered.
+- `TryAddTransient()` Adds a transient if not already registered.
+- `TryAddEnumerable()` Adds to a service collection (for `IEnumerable` resolution).
+
+```csharp
+builder.Services.AddSingleton();
+
+builder.Services.TryAddSingleton();
+
+// CustomLogger is used because it was registered first
+// TryAdd* only adds if the service type isn't already registered
+```
+
+### The Options Pattern (`IOptions`, `IOptionsSnapshot`, `IOptionsMonitor`)
+
+The **Options Pattern** is the recommended way to add configuration to your services. It provides type safe access to configuration sections and integrates with DI.
+
+**Three different options:**
+
+1. **`IOptions`** Singleton, will be loaded once at startup.
+2. **`IOptionsSnapshot`** Scoped, will be reloaded per request. (useful for multi tenant scenarios.)
+3. **`IOptionsMonitor`** Individually triggered changes will be reloaded when the configuration changes.
+
+```csharp
+public class ApiSettings
+{
+ public string BaseUrl { get; set; } = string.Empty;
+ public string ApiKey { get; set; } = string.Empty;
+ public int TimeoutSeconds { get; set; } = 30;
+}
+```
+
+**In appsettings.json**
+```json
+{
+ "ExternalApi": {
+ "BaseUrl": "https://api.example.com",
+ "ApiKey": "your-api-key",
+ "TimeoutSeconds": 60
+ }
+}
+```
+
+**Inject and use in a service**
+```csharp
+public class ExternalApiClient
+{
+ private readonly ApiSettings _settings;
+ private readonly ILogger _logger;
+ private readonly HttpClient _httpClient;
+
+ // Use IOptions for singleton services
+ public ExternalApiClient(
+ IOptions options,
+ ILogger logger,
+ HttpClient httpClient)
+ {
+ _settings = options.Value;
+ _logger = logger;
+ _httpClient = httpClient;
+
+ _httpClient.BaseAddress = new Uri(_settings.BaseUrl);
+ _httpClient.DefaultRequestHeaders.Add("X-API-Key", _settings.ApiKey);
+ _httpClient.Timeout = TimeSpan.FromSeconds(_settings.TimeoutSeconds);
+ }
+
+ public async Task FetchDataAsync()
+ {
+ return await _httpClient.GetStringAsync("/data");
+ }
+}
+
+public class DynamicConfigService
+{
+ private readonly IOptionsMonitor _optionsMonitor;
+
+ public DynamicConfigService(IOptionsMonitor optionsMonitor)
+ {
+ _optionsMonitor = optionsMonitor;
+
+ _optionsMonitor.OnChange(settings =>
+ {
+ Console.WriteLine($"Configuration changed! New URL: {settings.BaseUrl}");
+ });
+ }
+
+ public ApiSettings GetCurrentSettings() => _optionsMonitor.CurrentValue;
+}
+```
+
+**In Program.cs**
+```csharp
+
+builder.Services.Configure(builder.Configuration.GetSection("ExternalApi"));
+builder.Services.AddHttpClient();
+```
+
+**When to use each:**
+- **`IOptions`:** Used for settings that do not change during runtime.
+- **`IOptionsSnapshot`:** Used in scoped services where the configuration may differ per request.
+- **`IOptionsMonitor`:** Used when you need to react to configuration changes without restarting the application.
+
+### Automating Registration with Assembly Scanning
+
+In large projects, manually registering each service can be time consuming and error prone. While the built in container doesn't offer native assembly scanning, you can use reflection based utilities or third party libraries like **Scrutor** to automate service registration based on conventions.
+
+**Example: Using Scrutor**
+
+```csharp
+using Scrutor;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// It will scan the services according to the contract and automatically register them.
+builder.Services.Scan(scan => scan
+ .FromAssemblyOf() // Scan the current assembly
+ .AddClasses(classes => classes.Where(type =>
+ type.Name.EndsWith("Service"))) // Find all classes ending with "Service"
+ .AsImplementedInterfaces() // Register them by their interfaces
+ .WithScopedLifetime()); // Use scoped lifetime
+
+// More specific scanning
+builder.Services.Scan(scan => scan
+ .FromAssemblies(typeof(IRepository<>).Assembly)
+ .AddClasses(classes => classes.AssignableTo(typeof(IRepository<>)))
+ .AsImplementedInterfaces()
+ .WithTransientLifetime());
+```
+
+**Example: Custom reflection based scanning (without external library).**
+
+```csharp
+namespace MyApp.Services;
+
+using System.Reflection;
+
+public static class ServiceCollectionExtensions
+{
+ public static IServiceCollection AddApplicationServices(this IServiceCollection services)
+ {
+ var assembly = Assembly.GetExecutingAssembly();
+
+ // Find all classes implementing IService marker interface
+ var serviceTypes = assembly.GetTypes()
+ .Where(t => t is { IsClass: true, IsAbstract: false }
+ && t.GetInterfaces().Any(i => i.Name == "IService"));
+
+ foreach (var serviceType in serviceTypes)
+ {
+ var interfaceType = serviceType.GetInterfaces()
+ .FirstOrDefault(i => i.Name == $"I{serviceType.Name}");
+
+ if (interfaceType != null)
+ {
+ services.AddScoped(interfaceType, serviceType);
+ }
+ }
+
+ return services;
+ }
+}
+
+// Usage in Program.cs
+builder.Services.AddApplicationServices();
+```
+
+**Best Practices:**
+- Using assembly scanning will be easier in large projects where many services are used in accordance with the rules.
+- Your naming conventions should be clearly documented (for example, all classes ending in "Service" are automatically registered).
+- In performance critical scenarios, the assembly scan should be performed carefully to avoid potential problems, as this may result in startup costs.
+- For true reflection overhead in .NET 9, consider using source generators.
+
+
+## Best Practices and Common Mistakes
+
+### Design for Explicit Dependencies
+
+This principle states that parent modules should not depend directly on lower level modules (such as services for data access, sending email, or specific API clients). Instead, both should depend on abstractions (interfaces).
+
+This reverses the normal flow of dependencies, decoupling your code and making it more flexible and testable.
+
+#### Example
+
+##### Bad: Violates DIP (Tight Coupling)
+
+Here, the top level `NotificationService` depends directly on the low level, concrete `EmailSender` class.
+
+```csharp
+// Low level service
+public class EmailSender
+{
+ public void SendEmail(string message)
+ {
+ Console.WriteLine($"Sending email: {message}");
+ }
+}
+
+// High level service
+public class NotificationService
+{
+ // A direct dependency on a CONCRETE class
+ private readonly EmailSender _emailSender;
+
+ public NotificationService()
+ {
+ // The top level class is responsible for creating its own dependencies.
+ _emailSender = new EmailSender();
+ }
+
+ public void NotifyUser(string message)
+ {
+ _emailSender.SendEmail(message);
+ }
+}
+```
+
+**Problems:**
+
+1. **Difficult to Test:** You will not be able to test `NotificationService` without sending an email.
+2. **Not Flexible:** But what if you want to send an SMS instead? You will need to modify the `NotificationService` class.
+
+##### Good: Following DIP (Loose Coupling)
+
+Here both classes depend on the `IMessageSender` interface.
+
+```csharp
+// The Abstraction (Interface)
+public interface IMessageSender
+{
+ void Send(string message);
+}
+
+// Low level service (depends on the abstraction)
+public class EmailSender : IMessageSender
+{
+ public void Send(string message)
+ {
+ Console.WriteLine($"Sending email: {message}");
+ }
+}
+
+// Another low level service
+public class SmsSender : IMessageSender
+{
+ public void Send(string message)
+ {
+ Console.WriteLine($"Sending SMS: {message}");
+ }
+}
+
+// High level service (also depends on the abstraction)
+public class NotificationService
+{
+ // Dependency is on the Interface, not a concrete class
+ private readonly IMessageSender _messageSender;
+
+ // The dependency is injected via the constructor
+ public NotificationService(IMessageSender messageSender)
+ {
+ _messageSender = messageSender;
+ }
+
+ public void NotifyUser(string message)
+ {
+ _messageSender.Send(message);
+ }
+}
+```
+
+**Benefits:**
+
+ * **Flexible:** `NotificationService` doesn't care whether it is `EmailSender` or `SmsSender`. The DI container can be configured to provide both because it is dependent on an interface.
+ * **Testable:** You can create a `MockMessageSender` class that implements `IMessageSender` to use in your unit tests without sending a real message and perform your operations without needing any real information.
+
+### Service Disposal and `IAsyncDisposable`
+
+If your service contains disposable sources (such as network connections or file streams), it must implement `IDisposable` or `IAsyncDisposable`. The DI container will automatically call `Dispose` or `DisposeAsync` for you at the end of the service's lifetime. This is an important behavior to prevent source issues.
+
+In .NET 9, asynchronous disposal is the preferred model for services that perform I/O operations during cleanup. The container manages both asynchronous and synchronous disposal operations in a controlled manner.
+
+In this example, `MyNetworkService` gets `HttpClient` via DI (which it will not dispose of) but also creates its own `FileStream` resource, which it is responsible for disposing of asynchronously.
+
+```csharp
+public class MyNetworkService : IAsyncDisposable
+{
+ private readonly HttpClient _httpClient;
+
+ private readonly FileStream _logStream;
+ private bool _disposed = false;
+
+ public MyNetworkService(HttpClient httpClient)
+ {
+ _httpClient = httpClient;
+
+ _logStream = new FileStream($"log_{Guid.NewGuid()}.txt",
+ FileMode.CreateNew, FileAccess.Write, FileShare.None,
+ 4096, useAsync: true);
+ }
+
+ public async Task FetchDataAsync()
+ {
+ var data = await _httpClient.GetStringAsync("https://api.example.com/data");
+ await _logStream.WriteAsync(System.Text.Encoding.UTF8.GetBytes(data));
+ return data;
+ }
+
+ // The container calls this automatically when the scope ends
+ public async ValueTask DisposeAsync()
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ // Asynchronous cleanup for resources WE OWN
+ // We do NOT dispose of _httpClient here.
+ await _logStream.FlushAsync();
+ await _logStream.DisposeAsync();
+
+ _disposed = true;
+ GC.SuppressFinalize(this);
+ }
+}
+```
+
+**Using `await using` for Manual disposal:**
+
+When you manually create service instances outside of the DI container, you should use the `await using` syntax to ensure proper asynchronous disposal.
+
+```csharp
+// Assume HttpClient is coming from somewhere
+public async Task ProcessDataAsync(HttpClient httpClient)
+{
+ await using var service = new MyNetworkService(httpClient);
+ await service.FetchDataAsync();
+ // DisposeAsync() is called automatically here
+}
+```
+
+**Best Practices:**
+- If your cleanup operation involves asynchronous operations (file I/O, database connections, network calls), it would be more appropriate to implement `IAsyncDisposable`.
+- If your service can be used in both synchronous and asynchronous contexts, you can implement both `IDisposable` and `IAsyncDisposable`.
+- The DI container will call `DisposeAsync()` if present; otherwise it will fallback to `Dispose()`.
+- It is recommended to always call `GC.SuppressFinalize(this)` at the end of your disposal method to avoid unnecessary terminations.
+
+### Handling Circular Dependencies
+A circular dependency occurs when Service A depends on Service B, and Service B, in turn, depends on Service A. The ASP.NET Core container automatically detects this situation during object resolution (at parse time) and throws an `InvalidOperationException` to prevent a stack overflow, usually with a message detailing the dependency loop.
+
+To resolve this, you must refactor your design to break the circular reference. The most common solution is to introduce a new intermediary abstraction (like an interface) that one of the services can depend on, breaking the direct loop.
+
+**You Should Avoid Asynchronous Logic in Constructors**
+- Constructors must be fast and synchronous. You should not perform `await` or long running operations.
+- Asynchronous operation in constructors can lead to deadlocks and unpredictable initialization behavior.
+
+For asynchronous initialization you should use `IHostedService`, factory patterns or lazy initialization.
+
+```csharp
+// Bad: Async work in constructor
+public class BadService
+{
+ public BadService(IDataService dataService)
+ {
+ // This will deadlock or fail!
+ var data = dataService.GetDataAsync().Result;
+ }
+}
+
+// Good: Use IHostedService for async initialization
+public class GoodInitializationService : IHostedService
+{
+ private readonly IDataService _dataService;
+
+ public GoodInitializationService(IDataService dataService)
+ {
+ _dataService = dataService;
+ }
+
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ // Proper async initialization
+ var data = await _dataService.GetDataAsync();
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
+}
+```
+
+**Captive Dependency Issues**
+- It is created by injecting a shorter lived service (Scoped) into a longer lived service (Singleton).
+- The scoped service becomes "captive" and lives as long as the singleton service, which can lead to stale data and memory leaks.
+- The container's **ValidateScopes** option will detect this at runtime.
+
+```csharp
+// Bad: Scoped service captured by singleton
+builder.Services.AddSingleton(); // Holds DbContext forever!
+builder.Services.AddScoped();
+
+// Good: Use IServiceScopeFactory in singletons
+public class MySingletonService
+{
+ private readonly IServiceScopeFactory _scopeFactory;
+
+ public MySingletonService(IServiceScopeFactory scopeFactory)
+ {
+ _scopeFactory = scopeFactory;
+ }
+
+ public async Task DoWorkAsync()
+ {
+ await using var scope = _scopeFactory.CreateAsyncScope();
+ var dbContext = scope.ServiceProvider.GetRequiredService();
+ // Use dbContext safely within this scope
+ }
+}
+```
+
+**Avoiding Static Shared State in Singleton Services**
+- Singleton services should be stateless or have thread safe state management.
+- Avoid using static fields or shared mutable states that can cause race conditions.
+
+For immutable objects, the `ConcurrentDictionary` or appropriate locking mechanisms must be used.
+
+```csharp
+// Bad: Shared mutable state in singleton
+public class BadCacheService
+{
+ private Dictionary _cache = new(); // Not thread safe!
+
+ public void Add(string key, string value) => _cache[key] = value;
+}
+
+// Good: Thread safe state management
+public class GoodCacheService
+{
+ private readonly ConcurrentDictionary _cache = new();
+
+ public void Add(string key, string value) => _cache[key] = value;
+}
+```
+
+### Testing, Isolation, and Readability
+
+One of the primary goals of DI is testability. In integration tests, you can use the WebApplicationFactory to override service registrations with mock applications.
+
+```csharp
+await using var application = new WebApplicationFactory()
+ .WithWebHostBuilder(builder =>
+ {
+ builder.ConfigureTestServices(services =>
+ {
+ services.AddScoped();
+ });
+ });
+```
+
+## Performance Considerations
+
+The performance of **Dependency injection** in ASP.NET Core is adequate for most applications, but it's worth being aware of the mechanics.
+
+### Resolution Cost, Service Graph Caching, and Object Pooling
+
+ * **Service Graph Caching:** When a service graph is first parsed, the container creates and caches an execution plan. This plan includes the entire dependency tree and how each object will be created. Subsequent solutions will use this cached plan, making them extremely fast.
+ * **Transient and Singleton Resolving:** Transient services have a slightly higher creation cost because a new instance is created each time. However, this cost is generally negligible unless you are resolving thousands of transient services per request.
+ * **Object Pool:** For high performance scenarios, it would be beneficial for performance management to consider using `ObjectPool` from `Microsoft.Extensions.ObjectPool` to reuse expensive objects instead of creating new transient instances.
+
+### Benchmarking DI Performance
+
+Here is an example of a minimum benchmark comparing transient and singleton resolution times using `BenchmarkDotNet`.
+
+```csharp
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Running;
+using Microsoft.Extensions.DependencyInjection;
+
+public class DependencyInjectionBenchmark
+{
+ private ServiceProvider _serviceProvider = null!;
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ var services = new ServiceCollection();
+ services.AddTransient();
+ services.AddSingleton();
+ services.AddScoped();
+ _serviceProvider = services.BuildServiceProvider();
+ }
+
+ [Benchmark]
+ public ITransientService ResolveTransient()
+ {
+ return _serviceProvider.GetRequiredService();
+ }
+
+ [Benchmark]
+ public ISingletonService ResolveSingleton()
+ {
+ return _serviceProvider.GetRequiredService();
+ }
+
+ [Benchmark]
+ public IScopedService ResolveScoped()
+ {
+ using var scope = _serviceProvider.CreateScope();
+ return scope.ServiceProvider.GetRequiredService();
+ }
+}
+
+public interface ITransientService { }
+public class TransientService : ITransientService { }
+public interface ISingletonService { }
+public class SingletonService : ISingletonService { }
+public interface IScopedService { }
+public class ScopedService : IScopedService { }
+
+// Results:
+// | Method | Mean | Error | StdDev |
+// |----------------- |----------:|---------:|---------:|
+// | ResolveSingleton | 3.5 ns | 0.02 ns | 0.02 ns | ← Fastest (cached instance)
+// | ResolveTransient | 45.2 ns | 0.31 ns | 0.29 ns | ← Allocation overhead
+// | ResolveScoped | 78.4 ns | 0.52 ns | 0.48 ns | ← Scope creation + resolution
+```
+
+**Key Points:**
+- Singleton resolution is almost instantaneous (cached instance invocation).
+- Transient solution requires cost but is still fast.
+- Scoped solution includes the overhead of creating scope.
+
+For most applications, these differences are not noticeable. It should only be optimized if profiling reveals that DI is a bottleneck.
+
+
+### Startup Time and Compile Time DI
+
+Application startup time is the primary driver of performance. .NET uses **Source Generated Dependency Injection** to move dependency graph resolution from runtime to compile time.
+
+**Benefits:**
+ - **Faster Startup:** There is no runtime reflection to create the service graph.
+ - **Reduced Memory Usage:** It produces smaller runtime.
+ - **AOT Friendly:** Provides support for Native AOT compilation, which is critical for cloud native and containerized applications.
+ - **Compile Time Validation:** Allows catching missing service records at compile time rather than runtime.
+
+**How to Enable**
+
+**1. For Core Dependency Injection (DI) Generation**
+
+This is used as the main constructor that creates the optimized service provider for `AddScoped`, `AddSingleton`, etc.
+
+ * **Activation** This will be automatically enabled when you publish with native AOT.
+ * **Project file**
+ ```xml
+
+ true
+
+ ```
+
+**2. For Configuration Binding Generation**
+
+This is used to bind settings from sources like `appsettings.json` to your C# classes (`Bind`, `Configure`).
+
+ * **Project file:**
+ ```xml
+
+ true
+
+ ```
+
+**Example Code (using all generators):**
+
+```csharp
+var builder = WebApplication.CreateBuilder(args);
+
+// This call is optimized by 'EnableConfigurationBindingGenerator'
+builder.Services.Configure(builder.Configuration.GetSection("MyOptions"));
+
+// These calls are optimized by the Core DI generator (when PublishAot=true)
+builder.Services.AddScoped();
+var app = builder.Build();
+```
+
+When all generators are enabled, the compiler generates optimized service registration and parsing code, eliminating the reflection overhead.
+
+**When to Use:**
+
+ - Microservices and serverless functions (when it is desired to minimize cold start time).
+ - Native AOT scenarios (e.g. containerized applications, edge computing).
+ - Large applications with complex dependency graphs.
+
+## Advanced Dependency Injection Patterns in .NET
+
+### Keyed Services
+
+Keyed services, introduced in .NET 8, allow you to register multiple implementations of an interface and resolve a specific implementation using a key. This will be a useful feature for polymorphic scenarios where you need to choose a strategy at runtime.
+
+```csharp
+// Registration
+builder.Services.AddKeyedSingleton("email");
+builder.Services.AddKeyedSingleton("sms");
+
+// Resolution in a consumer class
+public class NotificationController([FromKeyedServices("email")] INotificationService emailService)
+{
+ // ...
+}
+```
+
+### Open Generic Registrations
+
+To avoid manually registering each generic implementation (e.g., `IRepository`, `IRepository`), you can use an explicit global registration.
+
+```csharp
+// This single line registers the Repository for any T requested via IRepository
+builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
+```
+
+### The Decorator Pattern
+
+Decorators allow you to add functionality to a service without modifying it. This is a perfect example of the Open/Closed Principle. You can register a decorator that wraps the original service and adds cross cutting functionality like logging, caching, or validation.
+
+**Without third party libraries (manual approach):**
+
+```csharp
+// Original service interface
+public interface IOrderProcessor
+{
+ Task ProcessOrderAsync(Order order);
+}
+
+// Base implementation
+public class OrderProcessor : IOrderProcessor
+{
+ public async Task ProcessOrderAsync(Order order)
+ {
+ await Task.Delay(100);
+ Console.WriteLine($"Order {order.Id} processed.");
+ }
+}
+
+// Logging decorator
+public class LoggingOrderProcessorDecorator : IOrderProcessor
+{
+ private readonly IOrderProcessor _inner;
+ private readonly ILogger _logger;
+
+ public LoggingOrderProcessorDecorator(IOrderProcessor inner, ILogger logger)
+ {
+ _inner = inner;
+ _logger = logger;
+ }
+
+ public async Task ProcessOrderAsync(Order order)
+ {
+ _logger.LogInformation("Processing order {OrderId}...", order.Id);
+ try
+ {
+ await _inner.ProcessOrderAsync(order);
+ _logger.LogInformation("Order {OrderId} processed successfully.", order.Id);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to process order {OrderId}.", order.Id);
+ throw;
+ }
+ }
+}
+
+// Manual registration (layering decorators)
+builder.Services.AddScoped();
+builder.Services.AddScoped(provider =>
+{
+ var baseProcessor = provider.GetRequiredService();
+ var logger = provider.GetRequiredService>();
+ return new LoggingOrderProcessorDecorator(baseProcessor, logger);
+});
+```
+
+**With Scrutor library (recommended for complex scenarios):**
+
+```csharp
+builder.Services.AddScoped();
+builder.Services.Decorate();
+// Add more decorators
+builder.Services.Decorate();
+```
+
+**Middleware Integration Context**
+
+Decorators work in a similar way with ASP.NET Core middleware. While the middleware operates at the HTTP pipeline level, decorators operate at the service level, allowing you to apply cross cutting concerns to business logic independent of HTTP concerns.
+
+### Conditional Registrations
+
+You can conditionally register services based on runtime configuration or environment.
+
+```csharp
+var builder = WebApplication.CreateBuilder(args);
+
+// You can register different applications depending on the environment
+if (builder.Environment.IsDevelopment())
+{
+ builder.Services.AddScoped();
+}
+else
+{
+ builder.Services.AddScoped();
+}
+
+// Register based on configuration
+var useRedis = builder.Configuration.GetValue("UseRedisCache");
+if (useRedis)
+{
+ builder.Services.AddStackExchangeRedisCache(options => { /* ... */ });
+}
+else
+{
+ builder.Services.AddDistributedMemoryCache();
+}
+```
+
+### Child Containers and Nested Scopes
+
+While the built in ASP.NET Core container doesn't support "subcontainers" like Autofac or other third party containers, you can achieve similar isolation using scopes.
+
+It's important to differentiate this from the Service Locator anti pattern, which involves directly injecting IServiceProvider to manually resolve dependencies. Instead, the correct approach (especially within Singleton services) is to inject `IServiceScopeFactory`.
+
+**Comprehensive embedded approach**
+```csharp
+public class ParentService
+{
+ private readonly IServiceScopeFactory _scopeFactory;
+
+ public ParentService(IServiceScopeFactory scopeFactory)
+ {
+ _scopeFactory = scopeFactory;
+ }
+
+ public async Task DoIsolatedWorkAsync()
+ {
+ await using var scope = _scopeFactory.CreateAsyncScope();
+
+ // Resolve services from the new scope's provider
+ var isolatedService = scope.ServiceProvider.GetRequiredService();
+ await isolatedService.DoWorkAsync();
+ // All services resolved from 'scope.ServiceProvider' are disposed here
+ }
+}
+```
+
+**Third party containers (Autofac example)**
+```csharp
+// Autofac supports real subcontainers with invalid records
+var childLifetimeScope = container.BeginLifetimeScope(builder =>
+{
+ builder.RegisterType().As();
+});
+```
+
+The built in container's scoping mechanism is simpler but sufficient for most scenarios. You can use third party containers only when you need advanced features like property injection, assembly scanning with rules, or complex lifetime management.
+
+### Testing with DI and `ConfigureTestServices`
+
+One of DI's greatest strengths is testability. In integration tests, you can replace real services with mock or simulated services using WebApplicationFactory and ConfigureTestServices.
+
+```csharp
+using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+
+public class OrderControllerTests : IClassFixture>
+{
+ private readonly WebApplicationFactory _factory;
+
+ public OrderControllerTests(WebApplicationFactory factory)
+ {
+ _factory = factory;
+ }
+
+ [Fact]
+ public async Task ProcessOrder_ReturnsSuccess()
+ {
+ //Replace real service with mock
+ var client = _factory.WithWebHostBuilder(builder =>
+ {
+ builder.ConfigureTestServices(services =>
+ {
+ //Remove actual service
+ services.RemoveAll();
+
+ // Add mock service
+ services.AddScoped();
+
+ // Or use a mocking framework
+ var mockProcessor = new Mock();
+ mockProcessor.Setup(x => x.ProcessOrderAsync(It.IsAny()))
+ .ReturnsAsync(true);
+ services.AddScoped(_ => mockProcessor.Object);
+ });
+ }).CreateClient();
+
+ // Act
+ var response = await client.PostAsJsonAsync("/api/orders", new Order { Id = 1 });
+
+ // Assert
+ response.EnsureSuccessStatusCode();
+ }
+}
+```
+
+**Key Benefits:**
+- You can replace expensive external dependencies with in memory mocks.
+- You can test business logic in isolation.
+- You can run fast and accurate tests without needing external dependencies.
+
+## Example: A Background Service
+
+A common scenario where DI lifecycle management is critical is with singletons, such as background workers or IHostedServices. You cannot directly add a scoped service like DbContext to this service. Instead, you'd be better off adding an IServiceScopeFactory to manually create scopes.
+
+**Hosted Service (`OrderProcessorWorker.cs`):**
+
+```csharp
+public class OrderProcessorWorker : BackgroundService
+{
+ private readonly ILogger _logger;
+ private readonly IServiceScopeFactory _scopeFactory;
+
+ // Inject IServiceScopeFactory, not DbContext
+ public OrderProcessorWorker(ILogger logger, IServiceScopeFactory scopeFactory)
+ {
+ _logger = logger;
+ _scopeFactory = scopeFactory;
+ }
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ while (!stoppingToken.IsCancellationRequested)
+ {
+ _logger.LogInformation("Processing new orders...");
+
+ // Create a new scope for this unit of work
+ await using (var scope = _scopeFactory.CreateAsyncScope())
+ {
+ var orderRepository = scope.ServiceProvider.GetRequiredService();
+ var newOrders = await orderRepository.GetNewOrdersAsync();
+
+ foreach (var order in newOrders)
+ {
+ // Process order...
+ }
+
+ await orderRepository.SaveChangesAsync();
+ }
+
+ await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
+ }
+ }
+}
+```
+
+**Registration (`Program.cs`):**
+
+```csharp
+builder.Services.AddDbContext(/* ... */);
+builder.Services.AddScoped();
+builder.Services.AddHostedService();
+```
+
+This pattern ensures that each run of the worker uses a new `DbContext`, preventing problems such as memory leaks or stale data.
+
+> While this example uses a simple `Task.Delay` loop within the `BackgroundService`, a robust pattern for managing decoupled background tasks involves an in memory queue. You can learn how to build this system by following this guide: [How to Build an In Memory Background Job Queue in ASP.NET Core From Scratch](https://abp.io/community/articles/how-to-build-an-in-memory-background-job-queue-in-asp.net-core-from-scratch-pai2zmtr).
+
+## Conclusion
+
+Understanding the **ASP.NET Core Dependency Injection** framework is essential for any .NET developer. By understanding the built in IoC container, choosing the right service lifecycles, and opting for explicit constructor injection, you can create modular, testable, and maintainable applications.
+
+**.NET brings significant enhancements to the DI ecosystem**
+
+- **Source Generated DI** for faster startup and Native AOT support
+- **Keyed Services** for advanced polymorphic resolution scenarios
+- **Enhanced lifetime validation** catches captive dependencies at development time
+- **Improved `IAsyncDisposable`** support for proper source cleanup*
+- **Good integration with C# features** such as primary constructors
+
+By embracing these features and implementing patterns such as decorators, manual scoping with `IServiceScopeFactory`, the Option Pattern for configuration, and proper asynchronous disposal, you can solve complex architectural challenges cleanly and efficiently.
+
+**Key Points**
+
+- **Always inject dependencies via constructors** explicit, immutable, testable
+- **Understanding lifetime implications** avoid dependent dependencies, you can use `IServiceScopeFactory` on singletons
+- **Leverage the Option Pattern** type safe, validated configuration injection
+- **You can use TryAdd methods** create mergeable records
+- **Leverage DI in your tests** you can use `ConfigureTestServices` to inject mocks
+- **Measure performance first; don't assume DI is a bottleneck** The internal container is efficient. Use a profiler to find real slowdowns before trying to optimize DI.
+- **Consider source generation** for microservices, serverless and AOT scenarios
+
+The transition from legacy, fragmented DI environments to a unified, performant, and compile time optimized dependency injection system represents a significant development in the platform's history. Understanding and leveraging these capabilities is crucial for building high performance, cloud native .NET applications.
+
+### Further Reading
+
+- [ABP Dependency Injection](https://abp.io/docs/10.0/framework/fundamentals/dependency-injection)
+- [Official Microsoft Docs on Dependency Injection in ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection)
+- [Source Generators for Dependency Injection](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines)
+- [IHttpClientFactory with .NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/httpclient-factory)
+- [Keyed Services DI Container](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-9.0#keyed-services)
+- [Use Scoped Services Within a Scoped Service](https://learn.microsoft.com/en-us/dotnet/core/extensions/scoped-service)
+- [Scrutor](https://github.com/khellang/Scrutor)
diff --git a/docs/en/Community-Articles/2025-10-20-Uncovering-ABP-Hidden-Magic/Post.md b/docs/en/Community-Articles/2025-10-20-Uncovering-ABP-Hidden-Magic/Post.md
new file mode 100644
index 0000000000..c19af4d7b7
--- /dev/null
+++ b/docs/en/Community-Articles/2025-10-20-Uncovering-ABP-Hidden-Magic/Post.md
@@ -0,0 +1,102 @@
+# Uncovering ABP’s Hidden Magic: Supercharging ASP.NET Core Development
+Experienced back-end developers often approach new frameworks with healthy skepticism. But many who try the ABP Framework quickly notice something different: things “just work” with minimal boilerplate. There’s a good reason ABP can feel magical – it silently handles a host of tedious tasks behind the scenes. In this article, we’ll explore how ABP’s out-of-the-box features and modular architecture dramatically boost productivity. We’ll compare with plain ASP.NET Core where relevant, so you can appreciate what ABP is doing for you under the hood.
+
+## Beyond the Basics: Why ABP Feels Magical
+ABP isn’t a typical library; it’s a full application framework that goes beyond the basics. From the moment you start an ABP project, a lot is happening automatically. Have you ever built an ASP.NET Core app and spent time wiring up cross-cutting concerns like error handling, logging, security tokens, or multi-tenancy? With ABP, much of that comes pre-configured. You might find that you write just your business logic, and ABP has already enabled security, transactions, and even APIs for you by convention. This can be disorienting at first (“Where’s the code that does X?”) until you realize ABP’s design is doing it for you, in line with best practices.
+
+For example, ABP completely automates CSRF (anti-forgery) protection and it works out-of-the-box without any configuration. In a plain ASP.NET Core project, you’d have to add anti-forgery tokens to your views or enable a global filter and manually include the token in AJAX calls. ABP’s startup template already includes a global antiforgery filter and even sets up the client-side code to send the token on each request, without you writing a line. This kind of “invisible” setup is repeated across many areas. ABP’s philosophy is to take care of the plumbing – like unit of work, data filters, audit logging, etc. – so you can focus on the real code. It feels magical because things that would normally require explicit code or packages in ASP.NET Core are just handled. As we peel back the layers in the next sections, you’ll see how ABP pulls off these tricks.
+
+## Zero to Hero: Rapid Application Development with ABP
+One of the most striking benefits of ABP is how quickly you can go from zero to a fully functional application – it’s a true rapid application development platform. With ASP.NET Core alone, setting up a new project with identity management, localization, an API layer, and a clean architecture can be a day’s work or more. In contrast, ABP’s startup templates give you a solution with all those pieces pre-wired. You can create a new ABP project (using the ABP CLI or ABP Studio) and run it, and you already have: user login and registration, role-based permission management, an admin UI, a REST API layer with Swagger, and a clean domain-driven code structure. It’s essentially a jump-start that takes you from zero to hero in record time.
+
+Rapid development is further enabled by ABP’s coding model. Define an entity and an application service, and ABP can generate the REST API endpoints for you automatically (via Conventional Controllers). You don’t need to write repetitive controllers that just call the service; ABP’s conventions map your service methods to HTTP verbs and routes by naming convention. For instance, a method name `GetListAsync()` in an `AppService` becomes an HTTP `GET` to `/api/app/your-entity` without extra attributes. The result: you implement application logic once in the application layer, and ABP instantly exposes it as an API (and even provides client proxies for UI).
+
+The tooling in the ABP ecosystem multiplies this productivity. The ABP Suite tool, for example, allows you to visually design entities and then generate a full-stack CRUD page for your entities in seconds, complete with UI forms, validation, DTOs, application services, and even unit tests. The generated code follows ABP’s best practices (layered architecture, proper authorization checks, etc.), so you’re not creating a maintenance headache. You get a working feature out-of-the-box and can then tweak it to your needs. All these accelerators mean you can deliver features at a higher velocity than ever, turning a blank project into a real application with minimal grunt work.
+
+## Modular Architecture: Building Like Digital Lego
+Perhaps the greatest strength of ABP is its modular architecture. Think of modules as building blocks – “digital Lego” pieces – that you can snap together to compose your application. ABP itself is built on modules (for example, Identity, Audit Logging, Language Management, etc.), and you can develop your own modules as well. This design encourages separation of concerns and reusability. Need a certain functionality? Chances are, ABP has a module for it – just plug it in, and it works seamlessly with the others.
+
+With plain ASP.NET Core, setting up a modular system requires a lot of upfront design. ABP, however, “is born to be a modular application development structure”, where every feature is compatible with modular development by default. The framework ensures that each module can encapsulate its own domain, application services, database migrations, UI pages, etc., without tight coupling. For example, the ABP Identity module provides all the user and role management functionality (built atop ASP.NET Core Identity), the SaaS module provides multi-tenant management, the Audit Logging module records user activities, and so on. You can include these modules in your project, gaining enterprise-grade functionality in literally one line of configuration. As the official documentation puts it, ABP provides “a lot of re-usable application modules like payment, chat, file management, audit log reporting… All of these modules are easily installed into your solution and directly work.” This is a huge time saver – you’re not reinventing the wheel for common requirements.
+
+The Lego-like nature also means you can remove or swap pieces without breaking the whole. If a built-in module doesn’t meet your needs, you can extend it or replace it (we’ll talk about customization later). Modules can even be maintained as separate packages, enabling teams to develop features in isolation and share modules across projects. Ultimately, ABP’s modularity gives your architecture a level of flexibility and organization that plain ASP.NET Core doesn’t provide out-of-the-box. It’s a solid foundation for either monolithic applications or microservice systems, as you can start with a modular monolith and later split modules into services if needed. In short, ABP provides the architectural “bricks” – you design the house.
+
+## Out-of-the-Box Features that Save Weeks of Work
+Beyond the big building blocks, ABP comes with a plethora of built-in features that operate behind the scenes to save you time. These are things that, in a non-ABP project, you would likely spend days or weeks implementing and fine-tuning – but ABP gives them to you on Day 1. Here are some of the key hidden gems ABP provides out-of-the-box:
+
+- CSRF Protection: As mentioned earlier, ABP automatically enables anti-forgery tokens for you. You get robust CSRF/XSRF protection by default – the server issues a token cookie and expects a header on modify requests, all handled by ABP’s infrastructure without manual setup. This means your app is defended against cross-site request forgery with essentially zero effort on your part.
+- Automated Data Filtering: ABP uses data filters to transparently apply common query conditions. For example, if an entity implements `ISoftDelete`, it will not be retrieved in queries unless you explicitly ask for deleted data. ABP automatically sets `IsDeleted=true` instead of truly deleting and filters it out on queries, so you don’t accidentally show or modify soft-deleted records. Similarly, if an entity implements `IMultiTenant`, ABP will “silently in the background” filter all queries to the current tenant and fill the `TenantId` on new records – no need to manually add tenant clauses to every repository query. These filters (and others) are on by default and can be toggled when needed, giving you multi-tenancy and soft delete behavior out-of-the-box.
+- Concurrency Control: In enterprise apps, it’s important to handle concurrent edits to avoid clobbering data. ABP makes this easy with an optimistic concurrency system. If you implement `IHasConcurrencyStamp` on an entity, ABP will automatically set a GUID stamp on insert and check that stamp on updates to detect conflicts, throwing an exception if the record was changed by someone else. In ASP.NET Core EF you’d set up a RowVersion or concurrency token manually – ABP’s built-in approach is a ready-to-use solution to ensure data consistency.
+- Data Seeding: Most applications need initial seed data (like an admin user, initial roles, etc.). ABP provides a modular data seeding system that runs on application startup or during migration. You can implement an `IDataSeedContributor` and ABP will automatically discover and execute it as part of the seeding process. Different modules add their own seed contributors (for example, the Identity module seeds the admin user/role). This system is database-independent and even works in production deployments (the templates include a DbMigrator tool to apply migrations and seed data). It’s more flexible than EF Core’s native seeding and saves you writing custom seeding scripts.
+- Audit Logging: ABP has an integrated auditing mechanism that logs details of each web request. By default, an audit log is created for each API call or MVC page hit, recording who did what and when. It captures the URL and HTTP method, execution duration, the user making the call, the parameters passed to application services, any exceptions thrown, and even entity changes saved to the database during the request. All of this is saved automatically (for example, into the AbpAuditLogs table if using EF Core). The startup templates enable auditing by default, so you have an audit trail with no extra coding. In a vanilla ASP.NET Core app, you’d have to implement your own logging to achieve this level of detail.
+- Unit of Work & Transaction Management: ABP implements the Unit of Work pattern globally. When you call a repository or an application service method, ABP will automatically start a UOW (database transaction) for you if one isn’t already running. It will commit on success or roll back on error. By convention, all app service methods, controller actions, and repository methods are wrapped in a UOW – so you don’t explicitly call SaveChanges() or begin transactions in most cases. For example, if you create or update multiple entities in an app service method, they either all succeed or all fail as a unit. This behavior is there “for free”, whereas in raw ASP.NET Core you’d be writing try/catch and transaction code around such operations. (ABP even avoids opening transactions on read-only GET requests by default for performance.)
+- Global Exception Handling: No need to write a global exception filter – ABP provides one. If an unhandled exception occurs in an API endpoint, ABP’s exception handling system catches it and returns a standardized error response in JSON. It also maps known exception types to appropriate HTTP status codes and can localize error messages. This means your client applications always get a clean, consistent error format (with an error code, message, validation details, etc.) instead of ugly stack traces or HTML error pages. Internally, ABP logs the error details and hides the sensitive info from the client by default. Essentially, you get production-ready error handling without writing it yourself.
+- Localization & Multi-Language Support: ABP’s localization system is built on the .NET localization extension but adds convenient enhancements. It automatically determines the user’s language/culture for each request (by checking the browser or tenant settings) and you can define localization resources in JSON files easily. ABP supports database-backed translations via the Language Management module as well. From day one, your app is ready to be translated – even exception messages and validation errors are localization-friendly. The default project template sets up a default resource and uses it for all framework-provided texts, meaning things like error messages or menu items are already localized (and you can add new languages through the UI if you include the module). In short, ABP bakes in multi-lingual capabilities so you don’t have to internationalize your app from scratch.
+- Background Jobs: Need to run tasks in the background (e.g. send emails, generate reports) without blocking the user? ABP has a built-in background job infrastructure. You can simply implement a job class and enqueue it via `IBackgroundJobManager`. By default, jobs are persisted and executed, and ABP has providers to integrate with popular systems like Hangfire, RabbitMQ and Quartz if you need scalability. For example, sending an email after a user registers can be offloaded to a background job with one method call. ABP will handle retries on failure and storing the job info. This saves you the effort of configuring a separate job runner or scheduler – it’s part of the framework.
+- Security & Defaults: ABP comes with sensible security defaults. It’s integrated with ASP.NET Core Identity, so password policies, lockout on multiple failed logins, and other best practices are in place by default. The framework also adds standard security headers to HTTP responses (against XSS, clickjacking, etc.) through its startup configuration. Additionally, ABP’s permission system is pre-configured: every module brings its own permission definitions, and you can easily check permissions with an attribute or method call. There’s even a built-in Permission Management UI (if you include the module) where you can grant or revoke permissions per role or user at runtime. All these defaults mean a lot of the “boring” but critical security work is done for you.
+- Paging & Query Limiting: ABP encourages efficient data access patterns. For list endpoints, the framework DTOs usually include paging parameters (MaxResultCount, SkipCount), and if you don't specify them, ABP will assume default values (often 10). ABP also enforces an upper limit on how many records can be requested in a single call, preventing potential performance issues from overly large queries. This protects your application from accidentally pulling thousands of records in one go. Of course, you can configure or override these limits, but the safe defaults are there to protect your application.
+
+That’s a long list – and it’s not even exhaustive – but the pattern is clear. ABP spares you from writing a lot of infrastructure and “glue” code. And if you do need multi-tenancy (or any of these advanced features), the time savings grow even more. These out-of-the-box capabilities let you focus on your business logic, since the baseline features are already in place. Next, let’s zoom in on a couple of these areas (like multi-tenancy and security) that typically cause headaches in pure ASP.NET Core but are a breeze with ABP.
+
+## Seamless Multi-Tenancy: Scaling Without the Headaches
+Multi-tenant architecture – supporting multiple isolated customers (tenants) in one application – is notoriously tricky to implement from scratch. You have to partition data per tenant, ensure no cross-tenant data leaks, manage connection strings if using separate databases, and adapt authentication/authorization to be tenant-aware. ABP Framework makes multi-tenancy almost trivial in comparison.
+
+Out of the box, ABP supports both approaches to multi-tenancy: single database with tenant segregation and separate databases per tenant, or even a hybrid of the two. If you go the single database route, as many SaaS apps do for simplicity, ABP will ensure every entity that implements the tenant interface (`IMultiTenant`) gets a `TenantId` value and is automatically filtered. As we touched on earlier, you don’t have to manually add `.Where(t => t.TenantId == currentTenant.Id)` on every query – ABP’s data filter does that behind the scenes based on the logged-in user’s tenant. If a user from Tenant A tries to access Tenant B’s data by ID, they simply won’t find it, because the filter is in effect on all repositories. Similarly, when saving data, ABP sets the `TenantId` for you. This isolation is enforced at the ORM level by ABP’s infrastructure.
+
+For multiple databases, ABP’s SaaS (Software-as-a-Service) module handles tenant management. At runtime, the framework can switch the database connection string based on the tenant context. In the ABP startup template, there’s a “tenant management” UI that lets an admin add new tenants and specify their connection strings. If a connection string is provided, ABP will use that database for that tenant’s data. If not, it falls back to the default shared database. Remarkably, from a developer’s perspective, the code you write is the same in both cases – ABP abstracts the difference. In practice, you just write repository queries as usual; ABP will route those to the appropriate place and filter as needed.
+
+Another pain point that ABP solves is making other subsystems tenant-aware. For example, ASP.NET Core Identity (for user accounts) isn’t multi-tenant by default, and neither is Keycloak, IdentityServer or OpenIddict (for authentication). ABP takes care of configuring these to work in a tenant context. When a user logs in, they do so with a tenant domain or tenant selection, and the identity system knows about the tenant. Permissions in ABP are also tenant-scoped by default – a tenant admin can only manage roles/permissions within their tenant, for instance. ABP’s modules are built to respect tenant boundaries out-of-the-box.
+
+What does all this mean for you? It means you can offer a multi-tenant SaaS solution without writing the bulk of the isolation logic. Instead of spending weeks on multi-tenancy infrastructure, you essentially flip a switch in ABP (enable multi-tenancy, use the SaaS module) and focus on higher-level concerns.
+
+## Security That Works Without the Pain
+Security is one area you do not want to get wrong. With plain ASP.NET Core, you have great tools (Identity, etc.) at your disposal, but a lot of configuration and integration work to tie them together in a full application. ABP takes the sting out of implementing security by providing a comprehensive, pre-integrated security model.
+
+To start, ABP’s application templates include the Identity Module, which is a ready-made integration of ASP.NET Core Identity (the membership system) with ABP’s framework. You get user and role entities extended to fit in ABP’s domain model, and a UI for user and role management. All the heavy lifting of setting up identity tables, password hashing, email confirmation, two-factor auth, etc. is done. The moment you run an ABP application, you can log in with the seeded admin account and manage users and roles through a built-in administration page. This would take significant effort to wire up yourself in a new ASP.NET Core app; ABP gives it to you out-of-the-box.
+
+Permission management is another boon. In an ABP solution, you don’t have to hard-code what each role can do – instead, ABP provides a declarative way to define permissions and a UI to assign those permissions to roles or users. The Permission Management module’s UI allows dynamic granting/revoking of permissions. Under the hood, ABP’s authorization system will automatically check those permissions when you annotate your application services or controllers with [Authorize] and a policy name (the policy maps to a permission). For example, you might declare a permission Inventory.DeleteProducts. In your ProductAppService’s DeleteAsync method, you add [Authorize("Inventory.DeleteProducts")]. ABP will ensure the current user has that permission (through their roles or direct assignment) before allowing the method to execute. If not, it throws a standardized authorization exception. This is standard ASP.NET Core policy-based auth, but ABP streamlines defining and managing the policies by its permission system. The result: secure by default – it’s straightforward to enforce role-based access control throughout your application, and even non-developers (with access to the admin UI) can adjust permissions as requirements evolve.
+
+We already discussed CSRF protection, but it’s worth reiterating in the security context: ABP saves you from common web vulnerabilities by enabling defenses by default. Anti-forgery tokens are automatic, and output encoding (to prevent XSS) is naturally handled by using Razor Pages or Angular with proper binding (framework features that ABP leverages). ABP also sets up ASP.NET Core’s Data Protection API for things like cookie encryption and CSRF token generation behind the scenes in its startup, so you get a proper cryptographic key management for free.
+
+Another underappreciated aspect is exception shielding. In development, you want to see detailed errors, but in production you should not reveal internal details (stack traces, etc.) to the client. ABP’s exception filter will output a generic error message to the client while logging the detailed exception on the server. This prevents information leakage that attackers could exploit, without you having to configure custom middleware or filters.
+
+On the topic of authentication: ABP supports modern authentication scenarios too. If you want to build a microservice or single-page app (SPA) architecture, ABP provides modules for OpenID Connect and OAuth2 protocol implementations. The ABP Commercial version even provides an OpenIddict setup out-of-the-box for issuing JWTs to SPAs or mobile apps. This means you can stand up a secure token service and resource servers with minimal configuration. With ABP, much of the configuration (clients, scopes, grants) is abstracted by the framework.
+
+In short, ABP’s approach to security is holistic and follows the mantra of secure by default. New ABP developers are often pleasantly surprised that they didn’t have to spend days on user auth or protecting API endpoints – it’s largely handled. Of course, you still design your authorization logic (defining who can do what), but ABP provides the scaffolding to enforce it consistently. The painful parts of security – getting the plumbing right – are taken care of, so you can focus on the policies and rules that matter for your domain. This dramatically lowers the risk of security holes compared to rolling it all yourself.
+
+## Customization Without Chaos
+With all this magic happening automatically, you might wonder: “What if I need to do it differently? Can I customize or override ABP’s behavior?” The answer is a resounding yes. ABP is designed with extension points and configurability in mind, so you can change the defaults without hacking the framework. This is important for keeping your project maintainable – you get ABP’s benefits, but you’re not boxed in when requirements demand a change.
+
+One way ABP enables customization is through its powerful dependency injection system and the modular structure. Because each feature is delivered via services (interfaces and classes) in DI, you can replace almost any ABP service with your own implementation if needed. For example, if you want to change how the IdentityUserAppService (the service behind user management) works, you can create your own class inheriting or implementing the same interface, and register it with `Dependency(ReplaceServices = true)`. ABP will start using your class in place of the original. This is an elegant way to override behavior without modifying ABP’s source – keeping you on the upgrade path for new versions. ABP’s team intentionally makes most methods virtual to support overriding in derived classes. This means you can subclass an ABP application service or domain service and override just the specific method you need to change, rather than writing a whole service from scratch.
+
+
+Beyond swapping out services, ABP offers configuration options for its features. Virtually every subsystem has an options class you can configure in your module startup. Not liking the 10-item default page size? You can change the default MaxResultCount. Want to disable a filter globally? You can toggle, say, soft-delete filtering off by default using `AbpDataFilterOptions`. Need to turn off auditing for certain operations? Configure `AbpAuditingOptions` to ignore them. These options give you a lot of control to tweak ABP’s behavior. And because they’re central configurations, you aren’t scattering magic numbers or settings throughout your code – it’s a structured approach to customization.
+
+Another area is UI and theming. ABP’s UI (if you use the integrated UI) is also modular and replaceable. You can override Razor components or pages from a module by simply re-declaring them in your web project. For instance, if you want to modify the login page from the Account module, you can add a Razor page with the same path in your web layer – ABP will use yours instead of the default. The documentation has guidance on how to override views, JavaScript, CSS, etc., in a safe manner for Angular, Blazor, and MVC. The LeptonX theme that ABP uses can be customized via SCSS variables or entirely new theme derivations. The key point is, you’re never stuck with the “out-of-the-box” look or logic if it doesn’t fit your needs. ABP gives you the foundation, and you’re free to build on top of it or change it.
+
+The best part? These customizations stay clean and organized. ABP's extension patterns prevent your project from becoming a mess of patches. When ABP releases updates, your overrides remain intact – no more copy-pasting framework code or dealing with merge conflicts. You get ABP's smart defaults plus the freedom to customize when needed.
+
+## Ecosystem Power: ABP’s Tools, Templates, and Integrations
+ABP is more than just a runtime framework; it’s surrounded by an ecosystem of tools and libraries that amplify productivity. We’ve touched on a few (like the ABP Suite code generator), but let’s look at the broader ecosystem that comes with ABP.
+
+- Project Templates: ABP provides multiple startup templates (via the ABP CLI or Studio) for different architectures – from a simple monolithic web app to a layered modular monolith, or even a microservice-oriented solution with multiple projects pre-configured. These templates are not empty skeletons; they include working examples of authentication, a UI theme, navigation, and so on for your own modules. The microservice template, for instance, sets up separate identity, administration, and SaaS services with communication patterns already wired. Using these templates can save you a huge amount of setup time and ensure you follow best practices from the get-go.
+- ABP CLI: The command-line tool abp is a developer’s handy companion. With it, you can generate new solutions or modules, add package references, update your ABP version, and even client proxy generations with simple commands.
+- ABP Studio: It is a cross-platform desktop environment designed to make working with ABP solutions smoother and more insightful. It provides a unified UI to create, run, monitor, and manage your ABP projects – whether you're building a monolith or a microservice system. With features like a real-time Application Monitor, Solution Runner, and Kubernetes integration, it brings operational visibility and ease-of-use to development workflows. Studio also includes tools for managing modules, packages, and even launching integrated tools like ABP Suite – all from a single place. Think of it as a control center for your ABP solutions.
+- ABP Suite: It is a powerful visual tool (included in PRO licenses) that helps you generate full-stack CRUD pages in minutes. Define your entities, their relationships, and hit generate – ABP Suite scaffolds everything from the database model to the HTTP APIs, application services, and UI components. It supports one-to-many and many-to-many relationships, master-detail patterns, and even lets you generate from existing database tables. Developers can customize the generated code using predefined hook points that persist across regenerations.
+- 3rd-Party Integrations: Modern applications often need to integrate with messaging systems, distributed caching, search engines, etc. ABP recognizes this and provides integration packages for many common technologies. Want to use RabbitMQ for event bus or background jobs? ABP has you covered. The same goes for others: ABP has modules or packages for Redis caching, Kafka distributed event bus, SignalR real-time hubs, Twilio SMS, Stripe payments, and more. Each integration is done in a way that it feels like a natural extension of the ABP environment (for example, using the same configuration system and dependency injection). This saves you from writing repetitive integration code or dealing with each library’s nuances in every project.
+- UI Themes and Multi-UI Support: ABP comes with a modern default theme (LeptonX) for web applications, and it supports Angular, MVC/Razor Pages and Blazor out-of-the-box. If you prefer Angular for frontend, ABP offers an Angular UI package that works with the same backend. There’s also support for mobile via React Native or MAUI templates. The ability to switch UI front-ends (or even support multiple simultaneously, e.g. an Angular SPA and a Blazor server app using the same API) is facilitated by ABP’s API and authentication infrastructure. This dramatically reduces the friction when setting up a new client application – you don’t have to hand-roll API clients or auth flows.
+- Community and Samples: While not a tool per se, the ABP community is part of the ecosystem and adds a lot of value. There are official sample projects (like eShopOnAbp, a full microservice reference application) and many community-contributed modules on GitHub. The consistency of ABP’s structure means community modules or examples are easier to understand and plug in. Being in a community where “everyone follows similar coding styles and principles” means code and knowledge are highly transferable. Developers share open source ABP modules (for example, there are community modules for things like blob storage management, setting UI, React frontend support, etc., beyond the official ones). This network effect is an often overlooked part of the ecosystem: as ABP’s adoption grows, so do the resources you can draw on, from Q&A to reusable code.
+
+In summary, ABP’s ecosystem provides a full-platform experience. It’s not just the core framework, but also the tooling to work with that framework efficiently and the integrations to connect it with the wider tech world. By using ABP, you’re not piecing together disparate tools – you have a coherent set of solutions designed to work in concert. This is the kind of ecosystem that traditionally only large enterprises or opinionated tech stacks provided, but ABP makes it accessible in the .NET open-source space. It supercharges development in a way that goes beyond just writing code faster; it’s about having a robust infrastructure around your code, so you can deliver more value with less guesswork.
+
+## Developer Happiness: The Hidden Productivity Boost
+All these features and time-savers aren’t just about checking off technical boxes – they have a profound effect on developer happiness and productivity. When a framework handles the heavy lifting and enforces good practices, developers can spend more time on interesting problems (and less on boilerplate or bug-hunting). ABP’s “hidden” features – the things that work without you even noticing – contribute to a less stressful development experience.
+
+Think about the common sources of frustration in back-end development: security holes that come back to bite you, race conditions or transaction bugs, deployment issues because some configuration was missed, writing the same logging or exception handling code in every project… ABP’s approach preempts many of these. There’s confidence in knowing that the framework has built-in solutions for common pitfalls. For instance, you’re less likely to have a data inconsistency bug because ABP’s unit of work ensured all your DB operations were atomic. This confidence means developers can focus on delivering features rather than constantly firefighting or re-architecting core pieces.
+
+Another aspect of developer happiness is consistency. ABP provides a uniform structure – every module has the same layering (Domain, Application, etc.), every web endpoint returns a standard response, and so on. Once you learn the patterns, you can navigate and contribute to any part of an ABP application with ease. New team members or even outside contributors ramp up faster because the project structure is familiar (it’s the ABP structure). This reduces the bus factor and onboarding time on teams – a source of relief for developers and managers alike.
+
+Moreover, by taking away a lot of the “yak shaving” (the endless setup tasks), ABP lets you as a developer spend your energy on creative problem-solving and delivering value. It’s simply more fun to develop when you can swiftly implement a feature without being bogged down in plumbing code. The positive feedback loop of having working features quickly (thanks to things like ABP Suite, or just the rapid scaffolding of ABP) can be very motivating. It feels like you have an expert co-pilot who has already wired the security system, laid out the architecture, and packed the toolkit with everything you need – so you can drive the project forward confidently.
+
+Finally, the community support adds to this happiness. There’s a thriving Discord server and forum where ABP developers help each other. Since ABP standardizes a lot, advice from one person’s experience often applies directly to your scenario. That sense of not being alone when you hit a snag – because others likely encountered and solved it – reduces anxiety and speeds up problem resolution. It’s the kind of developer experience where things “just work,” and when they occasionally don’t, you have a clear path to figure it out (good docs, support, community). In the daily life of a software developer, this can make a huge difference.
+
+In conclusion, ABP’s multitude of behind-the-scenes features are not about making the framework look impressive on paper – they’re about making you, the developer, more productive and happier in your job. By handling the boring, complex, or repetitive stuff, ABP lets you focus on building great software. It’s like having a teammate who has already done half the work before you even start coding. When you combine that with ABP’s extensibility and strong foundation, you get a framework that not only accelerates development but also encourages you to do things the right way. For experienced engineers and newcomers alike, that can indeed feel a bit like magic. But now that we’ve uncovered the “magic tricks” ABP is doing under the hood, you can fully appreciate how it all comes together – and decide if this framework’s approach aligns with your goals of building applications faster, smarter, and with fewer headaches. Chances are, once you experience the productivity boost of ABP, you won’t want to go back. Happy coding!
diff --git a/docs/en/Community-Articles/2025-10-20-Uncovering-ABP-Hidden-Magic/cover-image.jpg b/docs/en/Community-Articles/2025-10-20-Uncovering-ABP-Hidden-Magic/cover-image.jpg
new file mode 100644
index 0000000000..0e1d537f72
Binary files /dev/null and b/docs/en/Community-Articles/2025-10-20-Uncovering-ABP-Hidden-Magic/cover-image.jpg differ
diff --git a/docs/en/apps/volo-docs.md b/docs/en/apps/volo-docs.md
index d33914f513..0178c1c6bb 100644
--- a/docs/en/apps/volo-docs.md
+++ b/docs/en/apps/volo-docs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "VoloDocs simplifies documentation creation with GitHub integration, supporting Markdown, versioning, and collaborative editing across platforms."
+}
+```
+
# VoloDocs
## What is VoloDocs?
diff --git a/docs/en/cli/build-command.md b/docs/en/cli/build-command.md
index d9620aa621..9fcff53e3c 100644
--- a/docs/en/cli/build-command.md
+++ b/docs/en/cli/build-command.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently build .NET projects with the ABP Framework's build command, handling complex dependencies and configurations seamlessly."
+}
+```
+
# Build Command
Building a .NET project is hard when the project references a project reference outside of the solution or even from a different GIT repository. This command builds a GIT repository and it's depending repositories or a single .NET solution File. In order ```build``` command to work, its **executing directory** or passed ```--working-directory``` parameter's directory must contain one of;
diff --git a/docs/en/cli/differences-between-old-and-new-cli.md b/docs/en/cli/differences-between-old-and-new-cli.md
index ee4e06a543..440b785797 100644
--- a/docs/en/cli/differences-between-old-and-new-cli.md
+++ b/docs/en/cli/differences-between-old-and-new-cli.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the differences between the old and new ABP CLI, including features and commands, to enhance your ABP development experience."
+}
+```
+
# Old ABP CLI vs New ABP CLI
ABP CLI (Command Line Interface) is a command line tool to perform some common operations for ABP based solutions or ABP Studio features. With **v8.2+**, the old/legacy ABP CLI has been replaced with a new [CLI](index.md) system to align with the new templating system and [ABP Studio](../studio/index.md). Also, some superior features/commands have been introduced with the new CLI, such as `kube-connect` and `kube-intercept` commands.
diff --git a/docs/en/cli/index.md b/docs/en/cli/index.md
index 415cef1878..7decaa658c 100644
--- a/docs/en/cli/index.md
+++ b/docs/en/cli/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to install and use the new ABP CLI for streamlined operations in ABP-based solutions, enhancing your development experience!"
+}
+```
+
# ABP CLI
ABP CLI (Command Line Interface) is a command line tool to perform some common operations for ABP based solutions or ABP Studio features.
@@ -288,30 +295,39 @@ abp new-package --name Acme.BookStore.Domain --template lib.domain
* `--template` or `-t`: Specifies the template name. This parameter doesn't have a default value and must be set. Available templates and their sub-options:
* `lib.class-library`
* `lib.domain-shared`
+ * `--add-localization`: Includes default localization configuration & language files.
* `lib.domain`
+ * `--add-settings`: Includes default settings configuration.
+ * `--add-db-properties`: Includes the default Database Properties class.
+ * `--add-domain-shared`: Includes an additional Domain Shared package.
* `lib.application-contracts`
* `lib.application`
- * `--with-automapper`: Adds automapper configuration.
+ * `--add-mapperly`: Adds Mapperly configuration.
+ * `--add-application-contracts`: Includes an additional contracts package.
* `lib.ef`
* `--include-migrations`: Allows migration operations on this package.
* `--connection-string-name`: Default value is the last part of the package's namespace (or package name simply).
- * `--connection-string`: Connection string value. Defaut value is null. You can set it alter. **Note:** When specifying the connection string, make sure to enclose it in double quotes, for example: `--connection-string "Server=localhost;Database=MyProjectName;Trusted_Connection=True"`.
+ * `--connection-string`: Connection string value. The default value is null. You can set it later. **Note:** When specifying the connection string, make sure to enclose it in double quotes, for example: `--connection-string "Server=localhost;Database=MyProjectName;Trusted_Connection=True"`.
* `lib.mongodb`
* `lib.http-api`
* `lib.http-api-client`
* `lib.mvc`
+ * `--add-mapperly`: Adds Mapperly configuration.
* `lib.blazor`
+ * `--add-mapperly`: Adds Mapperly configuration.
+ * `--add-menu-contributors`: Includes default menu contributors.
* `lib.blazor-wasm`
* `lib.blazor-server`
* `host.http-api`
- * `--with-serilog`: Includes Serilog configuration.
- * `--with-swagger`: Includes Swagger configuration.
+ * `--add-serilog`: Includes Serilog configuration.
+ * `--add-swagger`: Includes Swagger configuration.
* `host.mvc`
- * `--with-serilog`: Includes Serilog configuration.
- * `--with-swagger`: Includes Swagger configuration.
+ * `--add-serilog`: Includes Serilog configuration.
+ * `--add-swagger`: Includes Swagger configuration.
* `host.blazor-wasm`
* `--backend`: Name of the backend project in the module (not path).
* `host.blazor-server`
+ * `abp.console`
* `csharp.console`
* `csharp.library`
* `--module-file` or `-m`: If set, the new package will be added to the given module. Otherwise the new package will added to the closest module in the file system. If no module found, it will throw an error.
@@ -342,7 +358,7 @@ Note that this command can upgrade your solution from a previous version, and al
* `--solution-name` or `-sn`: Specify the solution name. Search `*.sln` files in the directory by default.
* `--check-all`: Check the new version of each package separately. Default is `false`.
* `--version` or `-v`: Specifies the version to use for update. If not specified, latest version is used.
-* * `--leptonx-version` or `-lv`: Specifies the LeptonX version to use for update. If not specified, latest version or the version that is compatible with `--version` argument is used.
+* `--leptonx-version` or `-lv`: Specifies the LeptonX version to use for update. If not specified, latest version or the version that is compatible with `--version` argument is used.
### clean
diff --git a/docs/en/cli/new-command-samples.md b/docs/en/cli/new-command-samples.md
index 2841f12575..60c53ed5f6 100644
--- a/docs/en/cli/new-command-samples.md
+++ b/docs/en/cli/new-command-samples.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore sample commands to create ABP solutions using the ABP CLI, including Angular projects and database options for developers."
+}
+```
+
# ABP CLI - New Solution Sample Commands
The `abp new` command creates an ABP solution or other artifacts based on an ABP template. [ABP CLI](../cli/index.md) has several parameters to create a new ABP solution. In this document we will show you some sample commands to create a new solution. All the project names are `Acme.BookStore`. Currently, the available mobile projects are `React Native` and `MAUI` mobile app (they are *available for* ***Team*** *or higher licenses*). Available database providers are `Entity Framework Core` and `MongoDB`. All the commands starts with `abp new`.
diff --git a/docs/en/contribution/angular-ui.md b/docs/en/contribution/angular-ui.md
index b39ee8ad0c..6aefa43fa8 100644
--- a/docs/en/contribution/angular-ui.md
+++ b/docs/en/contribution/angular-ui.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to set up and contribute to Angular UI in the ABP Framework with essential tools, commands, and guidelines for developers."
+}
+```
+
# Contribution Guide for the Angular UI
## Pre-requirements
diff --git a/docs/en/contribution/index.md b/docs/en/contribution/index.md
index 504078f09f..3a016890aa 100644
--- a/docs/en/contribution/index.md
+++ b/docs/en/contribution/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Join the ABP community! This guide outlines how to contribute code and articles to enhance the ABP Framework."
+}
+```
+
# Contribution Guide
ABP is an [open source](https://github.com/abpframework) and community driven project. This guide is aims to help anyone wants to contribute to the project.
diff --git a/docs/en/deployment/clustered-environment.md b/docs/en/deployment/clustered-environment.md
index 0c4aa3daca..8c99b7ad8d 100644
--- a/docs/en/deployment/clustered-environment.md
+++ b/docs/en/deployment/clustered-environment.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively deploy your ABP application in a clustered environment, ensuring smooth operation across multiple instances."
+}
+```
+
# Deploying to a Clustered Environment
This document explains the topics that you should consider when deploying your application to a clustered environment where multiple instances of your application run concurrently.
diff --git a/docs/en/deployment/configuring-openIddict.md b/docs/en/deployment/configuring-openIddict.md
index eb62f3ec3f..321d8503c9 100644
--- a/docs/en/deployment/configuring-openIddict.md
+++ b/docs/en/deployment/configuring-openIddict.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure OpenIddict in your AuthServer project for both Development and Production environments with this comprehensive guide."
+}
+```
+
# Configuring OpenIddict
This document introduces how to configure `OpenIddict` in the `AuthServer` project.
diff --git a/docs/en/deployment/configuring-production.md b/docs/en/deployment/configuring-production.md
index 1480f933fe..557b671614 100644
--- a/docs/en/deployment/configuring-production.md
+++ b/docs/en/deployment/configuring-production.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to optimize your ABP application for production with essential configurations and caching strategies for better performance."
+}
+```
+
# Configuring Your Application for Production Environments
ABP predefines the configurations for the best performance for common deployment scenarios.
diff --git a/docs/en/deployment/distributed-microservice.md b/docs/en/deployment/distributed-microservice.md
index 1a020b1e1b..5db2b4e660 100644
--- a/docs/en/deployment/distributed-microservice.md
+++ b/docs/en/deployment/distributed-microservice.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to deploy distributed and microservice solutions with ABP, ensuring seamless communication and effective application management."
+}
+```
+
# Deploying Distributed / Microservice Solutions
ABP is designed for distributed and microservice systems, where multiple applications and/or services communicate internally. All of its features are compatible with distributed scenarios. This document highlights some points you should consider when deploying your distributed or microservice solution.
diff --git a/docs/en/deployment/forwarded-headers.md b/docs/en/deployment/forwarded-headers.md
index b6b74205c3..54abd43bfc 100644
--- a/docs/en/deployment/forwarded-headers.md
+++ b/docs/en/deployment/forwarded-headers.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to handle common issues with reverse proxies in ASP.NET Core using forwarded headers middleware for your ABP applications."
+}
+```
+
# Forwarded Headers
Reverse proxies and load balancers play a crucial role in modern web application architectures. When an application is deployed behind these proxies and load balancers, several specific issues can arise. This document will discuss these issues in detail, explain how ASP.NET Core's forwarded headers middleware can address them, and provide a code example for configuring forwarded headers in an ABP application.
diff --git a/docs/en/deployment/index.md b/docs/en/deployment/index.md
index 245c8bdaf0..933da06de2 100644
--- a/docs/en/deployment/index.md
+++ b/docs/en/deployment/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively deploy your ABP applications with essential guides on SSL, OpenIddict, and best practices for .NET environments."
+}
+```
+
# Deployment
Deploying an ABP application is not different than deploying any .NET or ASP.NET Core application. You can deploy it to a cloud provider (e.g., Azure, AWS, Google Could) or an on-premise server, IIS or any other web server. ABP's documentation doesn't contain much information on deployment. You can refer to your provider's documentation.
diff --git a/docs/en/deployment/optimizing-production.md b/docs/en/deployment/optimizing-production.md
index d6689b77fe..c6b3e4b21e 100644
--- a/docs/en/deployment/optimizing-production.md
+++ b/docs/en/deployment/optimizing-production.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to optimize your ABP applications for production with caching strategies and best practices for maximum performance."
+}
+```
+
# Optimizing Your Application for Production Environments
ABP and the startup solution templates are configured well to get the maximum performance on production environments.
diff --git a/docs/en/deployment/ssl.md b/docs/en/deployment/ssl.md
index 27c83ea80f..515aac4c38 100644
--- a/docs/en/deployment/ssl.md
+++ b/docs/en/deployment/ssl.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to obtain and configure an SSL certificate for your application to enhance security, trust, and ownership verification."
+}
+```
+
# Configuring SSL certificate(HTTPS)
A website needs an SSL certificate to keep user data secure, verify ownership, prevent attackers from creating a fake version of the site, and gain user trust.
diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json
index 4969fe5430..6fa1f5e620 100644
--- a/docs/en/docs-nav.json
+++ b/docs/en/docs-nav.json
@@ -2343,6 +2343,10 @@
}
]
},
+ {
+ "text": "AI Management (Pro)",
+ "path": "modules/ai-management/index.md"
+ },
{
"text": "Audit Logging",
"path": "modules/audit-logging.md"
@@ -2641,6 +2645,10 @@
{
"text": "Optimizing for Production",
"path": "deployment/optimizing-production.md"
+ },
+ {
+ "text": "Configuring Forwarded Headers for Reverse Proxies",
+ "path": "deployment/forwarded-headers.md"
}
]
},
diff --git a/docs/en/framework/api-development/auto-controllers.md b/docs/en/framework/api-development/auto-controllers.md
index d52c5e4d7f..b40718b079 100644
--- a/docs/en/framework/api-development/auto-controllers.md
+++ b/docs/en/framework/api-development/auto-controllers.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to automatically create API controllers in ABP Framework, simplifying your application's REST API setup with minimal configuration."
+}
+```
+
# Auto API Controllers
Once you create an [application service](../architecture/domain-driven-design/application-services.md), you generally want to create an API controller to expose this service as an HTTP (REST) API endpoint. A typical API controller does nothing but redirects method calls to the application service and configures the REST API using attributes like [HttpGet], [HttpPost], [Route]... etc.
diff --git a/docs/en/framework/api-development/dynamic-csharp-clients.md b/docs/en/framework/api-development/dynamic-csharp-clients.md
index a5dc2ec1cf..d560b536eb 100644
--- a/docs/en/framework/api-development/dynamic-csharp-clients.md
+++ b/docs/en/framework/api-development/dynamic-csharp-clients.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use ABP's dynamic C# API client proxies for seamless HTTP service calls, simplifying authentication, serialization, and error handling."
+}
+```
+
# Dynamic C# API Client Proxies
ABP can dynamically create C# API client proxies to call your remote HTTP services (REST APIs). In this way, you don't need to deal with `HttpClient` and other low level details to call remote services and get results.
diff --git a/docs/en/framework/api-development/index.md b/docs/en/framework/api-development/index.md
index 1d9736388f..15dd6a824f 100644
--- a/docs/en/framework/api-development/index.md
+++ b/docs/en/framework/api-development/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore comprehensive guidance on building HTTP APIs with ABP, covering endpoints, versioning, auto controllers, and more."
+}
+```
+
# API Development
The following documents explain the concepts, infrastructure and integrations to build HTTP APIs with ABP:
diff --git a/docs/en/framework/api-development/integration-services.md b/docs/en/framework/api-development/integration-services.md
index 2514be37de..0bc532e643 100644
--- a/docs/en/framework/api-development/integration-services.md
+++ b/docs/en/framework/api-development/integration-services.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how Integration Services facilitate communication between microservices, enhancing your ABP Framework applications with seamless integration."
+}
+```
+
# Integration Services
The *Integration Service* concept was created to distinguish the [application services](../architecture/domain-driven-design/application-services.md) that are built for inter-module (or inter-microservice) communication from the application services that are intended to be consumed from a UI or a client application.
diff --git a/docs/en/framework/api-development/standard-apis/configuration.md b/docs/en/framework/api-development/standard-apis/configuration.md
index 11e754f214..3fcd22f6d9 100644
--- a/docs/en/framework/api-development/standard-apis/configuration.md
+++ b/docs/en/framework/api-development/standard-apis/configuration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use ABP's Application Configuration Endpoint to access user permissions, settings, and tenant info for your application."
+}
+```
+
# Application Configuration Endpoint
ABP provides a pre-built and standard endpoint that contains some useful information about the application/service. Here, is the list of some fundamental information at this endpoint:
diff --git a/docs/en/framework/api-development/standard-apis/index.md b/docs/en/framework/api-development/standard-apis/index.md
index 531d76bbd9..316151e765 100644
--- a/docs/en/framework/api-development/standard-apis/index.md
+++ b/docs/en/framework/api-development/standard-apis/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's standard HTTP API endpoints for easy access to application configuration and localization information."
+}
+```
+
# Standard HTTP API Endpoints
ABP provides some pre-built and standard endpoints that contains useful information about the application or service, such as localization entries and settings. Here, is the list of the pre-built endpoints:
diff --git a/docs/en/framework/api-development/standard-apis/localization.md b/docs/en/framework/api-development/standard-apis/localization.md
index 57e2e939c5..f98ee44aff 100644
--- a/docs/en/framework/api-development/standard-apis/localization.md
+++ b/docs/en/framework/api-development/standard-apis/localization.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize ABP's application localization endpoint to fetch localization resources and enhance your UI application effectively."
+}
+```
+
# Application Localization Endpoint
ABP provides a pre-built and standard endpoint that returns all the [localization](../../fundamentals/localization.md) resources and texts defined in the server.
diff --git a/docs/en/framework/api-development/static-csharp-clients.md b/docs/en/framework/api-development/static-csharp-clients.md
index b3cf80fcfc..7491f46d67 100644
--- a/docs/en/framework/api-development/static-csharp-clients.md
+++ b/docs/en/framework/api-development/static-csharp-clients.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create Static C# API client proxies with ABP for seamless HTTP service calls, simplifying authentication, serialization, and error handling."
+}
+```
+
# Static C# API Client Proxies
ABP can create C# API client proxy code to call your remote HTTP services (REST APIs). In this way, you don't need to deal with `HttpClient` and other low level details to call remote services and get results.
diff --git a/docs/en/framework/api-development/swagger.md b/docs/en/framework/api-development/swagger.md
index fb27bcf27b..03808d7869 100644
--- a/docs/en/framework/api-development/swagger.md
+++ b/docs/en/framework/api-development/swagger.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Swagger with ABP Framework for seamless REST API documentation and service connectivity with minimal setup."
+}
+```
+
# Swagger Integration
[Swagger (OpenAPI)](https://swagger.io/) is a language-agnostic specification for describing REST APIs. It allows both computers and humans to understand the capabilities of a REST API without direct access to the source code. Its main goals are to:
diff --git a/docs/en/framework/api-development/versioning.md b/docs/en/framework/api-development/versioning.md
index 9acdd5a888..3a46d63af8 100644
--- a/docs/en/framework/api-development/versioning.md
+++ b/docs/en/framework/api-development/versioning.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement API versioning in ABP Framework, enabling seamless integration with ASP.NET while supporting static client proxies."
+}
+```
+
# API Versioning System
ABP integrates the [ASPNET-API-Versioning](https://github.com/dotnet/aspnet-api-versioning/wiki) feature and adapts to C# and JavaScript Static Client Proxies and [Auto API Controller](./auto-controllers.md).
diff --git a/docs/en/framework/architecture/best-practices/application-layer-overview.md b/docs/en/framework/architecture/best-practices/application-layer-overview.md
index f834d02615..dc124911f8 100644
--- a/docs/en/framework/architecture/best-practices/application-layer-overview.md
+++ b/docs/en/framework/architecture/best-practices/application-layer-overview.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore best practices for implementing the application layer in your solution with Domain Driven Design principles."
+}
+```
+
# Best Practices: Application Layer
The following documents suggest some best-practices that you can use while implementing the application layer of your solution by following the Domain Driven Design principles:
diff --git a/docs/en/framework/architecture/best-practices/application-services.md b/docs/en/framework/architecture/best-practices/application-services.md
index efe937e956..4cbd453076 100644
--- a/docs/en/framework/architecture/best-practices/application-services.md
+++ b/docs/en/framework/architecture/best-practices/application-services.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore best practices for implementing Application Services in ABP Framework, ensuring effective use of Domain-Driven Design principles."
+}
+```
+
# Application Services Best Practices & Conventions
> This document offers best practices for implementing Application Services classes in your modules and applications based on Domain-Driven-Design principles.
diff --git a/docs/en/framework/architecture/best-practices/data-access-overview.md b/docs/en/framework/architecture/best-practices/data-access-overview.md
index 28dd6b274d..a782127157 100644
--- a/docs/en/framework/architecture/best-practices/data-access-overview.md
+++ b/docs/en/framework/architecture/best-practices/data-access-overview.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore best practices for data access in your solutions using Entity Framework Core and MongoDB, aligned with Domain Driven Design principles."
+}
+```
+
# Best Practices: Data Access
The following documents suggest some best-practices that you can use while implementing the database integration layer of your solution by following Domain Driven Design principles:
diff --git a/docs/en/framework/architecture/best-practices/data-transfer-objects.md b/docs/en/framework/architecture/best-practices/data-transfer-objects.md
index 96194b4adb..e3735168c7 100644
--- a/docs/en/framework/architecture/best-practices/data-transfer-objects.md
+++ b/docs/en/framework/architecture/best-practices/data-transfer-objects.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore best practices for implementing Data Transfer Objects in your applications, guided by Domain-Driven Design principles."
+}
+```
+
# Data Transfer Objects Best Practices & Conventions
> This document offers best practices for implementing Data Transfer Object classes in your modules and applications based on Domain-Driven-Design principles.
diff --git a/docs/en/framework/architecture/best-practices/domain-layer-overview.md b/docs/en/framework/architecture/best-practices/domain-layer-overview.md
index bfdd286c28..8abde65765 100644
--- a/docs/en/framework/architecture/best-practices/domain-layer-overview.md
+++ b/docs/en/framework/architecture/best-practices/domain-layer-overview.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover best practices for implementing the domain layer using Domain Driven Design principles, including entities, repositories, and domain services."
+}
+```
+
# Best Practices: Domain Layer
The following documents suggest some best-practices that you can use while implementing the domain layer of your solution by following the Domain Driven Design principles:
diff --git a/docs/en/framework/architecture/best-practices/domain-services.md b/docs/en/framework/architecture/best-practices/domain-services.md
index 55c731d207..2b068b1955 100644
--- a/docs/en/framework/architecture/best-practices/domain-services.md
+++ b/docs/en/framework/architecture/best-practices/domain-services.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn best practices for implementing Domain Services in your applications, guided by Domain-Driven Design principles."
+}
+```
+
# Domain Services Best Practices & Conventions
> This document offers best practices for implementing Domain Service classes in your modules and applications based on Domain-Driven-Design principles.
diff --git a/docs/en/framework/architecture/best-practices/entities.md b/docs/en/framework/architecture/best-practices/entities.md
index cc4b0e2a21..b96e9c1a9d 100644
--- a/docs/en/framework/architecture/best-practices/entities.md
+++ b/docs/en/framework/architecture/best-practices/entities.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore best practices for implementing Aggregate Root and Entity classes in your applications using Domain-Driven Design principles."
+}
+```
+
# Entity Best Practices & Conventions
> This document offers best practices for implementing Aggregate Root and Entity classes in your modules and applications based on Domain-Driven-Design principles.
diff --git a/docs/en/framework/architecture/best-practices/entity-framework-core-integration.md b/docs/en/framework/architecture/best-practices/entity-framework-core-integration.md
index 960e0e69e4..e95e2ccbb5 100644
--- a/docs/en/framework/architecture/best-practices/entity-framework-core-integration.md
+++ b/docs/en/framework/architecture/best-practices/entity-framework-core-integration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover best practices for integrating Entity Framework Core in your applications, ensuring optimal performance and maintainability."
+}
+```
+
# Entity Framework Core Integration Best Practices
> This document offers best practices for implementing Entity Framework Core integration in your modules and applications.
diff --git a/docs/en/framework/architecture/best-practices/index.md b/docs/en/framework/architecture/best-practices/index.md
index 1dc84838c6..aec04828ba 100644
--- a/docs/en/framework/architecture/best-practices/index.md
+++ b/docs/en/framework/architecture/best-practices/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore best practices for developing ABP Framework modules, focusing on Domain Driven Design, DBMS independence, and microservice compatibility."
+}
+```
+
# Module Development Best Practices & Conventions
This document describes the **best practices** and **conventions** for those who want to develop **modules** that satisfy the following specifications:
diff --git a/docs/en/framework/architecture/best-practices/module-architecture.md b/docs/en/framework/architecture/best-practices/module-architecture.md
index c168b77f87..345c7d65fd 100644
--- a/docs/en/framework/architecture/best-practices/module-architecture.md
+++ b/docs/en/framework/architecture/best-practices/module-architecture.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover best practices for structuring ABP modules with clear conventions on solution architecture, layered design, and package dependencies."
+}
+```
+
# Module Architecture Best Practices & Conventions
## Solution Structure
diff --git a/docs/en/framework/architecture/best-practices/mongodb-integration.md b/docs/en/framework/architecture/best-practices/mongodb-integration.md
index c39f6443a0..415ec51d66 100644
--- a/docs/en/framework/architecture/best-practices/mongodb-integration.md
+++ b/docs/en/framework/architecture/best-practices/mongodb-integration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn best practices for integrating MongoDB in your ABP Framework applications with clear guidelines on defining MongoDbContext."
+}
+```
+
# MongoDB Integration
> This document offers best practices for implementing MongoDB integration in your modules and applications.
diff --git a/docs/en/framework/architecture/best-practices/repositories.md b/docs/en/framework/architecture/best-practices/repositories.md
index 227c620f45..80d80cfc4d 100644
--- a/docs/en/framework/architecture/best-practices/repositories.md
+++ b/docs/en/framework/architecture/best-practices/repositories.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover best practices for implementing repository classes in your applications, grounded in Domain-Driven Design principles."
+}
+```
+
# Repository Best Practices & Conventions
> This document offers best practices for implementing Repository classes in your modules and applications based on Domain-Driven-Design principles.
diff --git a/docs/en/framework/architecture/domain-driven-design/application-layer.md b/docs/en/framework/architecture/domain-driven-design/application-layer.md
index 97b4cc718b..a4e1d6fb56 100644
--- a/docs/en/framework/architecture/domain-driven-design/application-layer.md
+++ b/docs/en/framework/architecture/domain-driven-design/application-layer.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Application Layer in Domain Driven Design, learn about its components, and how it facilitates application logic in ABP Framework."
+}
+```
+
# Domain Driven Design: Application Layer
Application Layer mediates between the Presentation and Domain Layers. Orchestrates business objects to perform specific application tasks and implements use cases as the application logic. Here, is the list of the building blocks of the Application Layer:
diff --git a/docs/en/framework/architecture/domain-driven-design/application-services.md b/docs/en/framework/architecture/domain-driven-design/application-services.md
index 968ceb434d..a0d0c2d5fc 100644
--- a/docs/en/framework/architecture/domain-driven-design/application-services.md
+++ b/docs/en/framework/architecture/domain-driven-design/application-services.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement application services in the ABP Framework to expose domain logic and streamline presentation layer interactions."
+}
+```
+
# Application Services
Application services are used to implement the **use cases** of an application. They are used to **expose domain logic to the presentation layer**.
diff --git a/docs/en/framework/architecture/domain-driven-design/data-transfer-objects.md b/docs/en/framework/architecture/domain-driven-design/data-transfer-objects.md
index 8816411a5b..716b53e027 100644
--- a/docs/en/framework/architecture/domain-driven-design/data-transfer-objects.md
+++ b/docs/en/framework/architecture/domain-driven-design/data-transfer-objects.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how Data Transfer Objects (DTOs) enhance data handling between application and presentation layers, ensuring clean architecture and abstraction."
+}
+```
+
# Data Transfer Objects
**Data Transfer Objects** (DTO) are used to transfer data between the **Application Layer** and the **Presentation Layer** or other type of clients.
diff --git a/docs/en/framework/architecture/domain-driven-design/domain-layer.md b/docs/en/framework/architecture/domain-driven-design/domain-layer.md
index 7a83b634b8..c14a6e91f6 100644
--- a/docs/en/framework/architecture/domain-driven-design/domain-layer.md
+++ b/docs/en/framework/architecture/domain-driven-design/domain-layer.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Domain Layer in Domain Driven Design, featuring essential building blocks like Entities, Value Objects, and Domain Services."
+}
+```
+
# Domain Driven Design: Domain Layer
Domain Layer contains business objects and the core (domain) business rules of the application and it's the heart of the application. Here, is the list of building blocks of the Domain Layer:
diff --git a/docs/en/framework/architecture/domain-driven-design/domain-services.md b/docs/en/framework/architecture/domain-driven-design/domain-services.md
index 36bd732a3c..9f13b2c605 100644
--- a/docs/en/framework/architecture/domain-driven-design/domain-services.md
+++ b/docs/en/framework/architecture/domain-driven-design/domain-services.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement Domain Services in ABP Framework for core business logic, enhancing your Domain Driven Design solutions effectively."
+}
+```
+
# Domain Services
In a [Domain Driven Design](../domain-driven-design) (DDD) solution, the core business logic is generally implemented in aggregates ([entities](./entities.md)) and the Domain Services. Creating a Domain Service is especially needed when;
diff --git a/docs/en/framework/architecture/domain-driven-design/entities.md b/docs/en/framework/architecture/domain-driven-design/entities.md
index 8be960c773..df727a61ba 100644
--- a/docs/en/framework/architecture/domain-driven-design/entities.md
+++ b/docs/en/framework/architecture/domain-driven-design/entities.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn about entities in DDD, their structure, and best practices for using GUID keys in the ABP Framework for effective data modeling."
+}
+```
+
# Entities
Entities are one of the core concepts of DDD (Domain Driven Design). Eric Evans describes it as "*An object that is not fundamentally defined by its attributes, but rather by a thread of continuity and identity*".
diff --git a/docs/en/framework/architecture/domain-driven-design/index.md b/docs/en/framework/architecture/domain-driven-design/index.md
index a15b9c11e0..938d25043a 100644
--- a/docs/en/framework/architecture/domain-driven-design/index.md
+++ b/docs/en/framework/architecture/domain-driven-design/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how ABP Framework simplifies Domain Driven Design (DDD) for developers with structured layers and collaboration for complex software needs."
+}
+```
+
# Domain Driven Design
## What is DDD?
diff --git a/docs/en/framework/architecture/domain-driven-design/repositories.md b/docs/en/framework/architecture/domain-driven-design/repositories.md
index 04848a59e8..a5753e3808 100644
--- a/docs/en/framework/architecture/domain-driven-design/repositories.md
+++ b/docs/en/framework/architecture/domain-driven-design/repositories.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use repositories in ABP Framework for effective data access and CRUD operations on domain objects."
+}
+```
+
# Repositories
"*Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects*" (Martin Fowler).
diff --git a/docs/en/framework/architecture/domain-driven-design/specifications.md b/docs/en/framework/architecture/domain-driven-design/specifications.md
index 68ff038b7e..e708bde95c 100644
--- a/docs/en/framework/architecture/domain-driven-design/specifications.md
+++ b/docs/en/framework/architecture/domain-driven-design/specifications.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement the Specification Pattern in your ABP projects for creating reusable and testable filters for your entities."
+}
+```
+
# Specifications
Specification Pattern is used to define **named, reusable, combinable and testable filters** for entities and other business objects.
diff --git a/docs/en/framework/architecture/domain-driven-design/unit-of-work.md b/docs/en/framework/architecture/domain-driven-design/unit-of-work.md
index 9b9931b210..697d7dba80 100644
--- a/docs/en/framework/architecture/domain-driven-design/unit-of-work.md
+++ b/docs/en/framework/architecture/domain-driven-design/unit-of-work.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how ABP's Unit of Work simplifies database transactions, ensuring consistency across operations in any application type."
+}
+```
+
# Unit of Work
ABP's Unit Of Work (UOW) implementation provides an abstraction and control on a **database connection and transaction** scope in an application.
diff --git a/docs/en/framework/architecture/domain-driven-design/value-objects.md b/docs/en/framework/architecture/domain-driven-design/value-objects.md
index aa0d75dc5a..125f5f96ac 100644
--- a/docs/en/framework/architecture/domain-driven-design/value-objects.md
+++ b/docs/en/framework/architecture/domain-driven-design/value-objects.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn about Value Objects in domain-driven design, how to implement them in your projects, and why they matter for clean architecture."
+}
+```
+
# Value Objects
> An object that represents a descriptive aspect of the domain with no conceptual identity is called a VALUE OBJECT.
diff --git a/docs/en/framework/architecture/index.md b/docs/en/framework/architecture/index.md
index 06df5bd78b..85e11631dd 100644
--- a/docs/en/framework/architecture/index.md
+++ b/docs/en/framework/architecture/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover ABP's opinionated yet flexible architecture for building enterprise software, featuring modularity and comprehensive tools for developers."
+}
+```
+
# ABP Architecture
ABP offers an **opinionated architecture** to build enterprise software solutions. In this way, the solution structure and development model is pretty well defined. All the solution templates, tooling, pre-built modules, guides and documentation are compatible to that development model.
diff --git a/docs/en/framework/architecture/microservices/index.md b/docs/en/framework/architecture/microservices/index.md
index eb3b2ccef6..c014190437 100644
--- a/docs/en/framework/architecture/microservices/index.md
+++ b/docs/en/framework/architecture/microservices/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore microservice architecture and learn how it enhances modularity, scalability, and continuous delivery for efficient application development."
+}
+```
+
# Microservice Architecture
*"Microservices are a software development technique—a variant of the **service-oriented architecture** (SOA) architectural style that structures an application as a collection of **loosely coupled services**. In a microservices architecture, services are **fine-grained** and the protocols are **lightweight**. The benefit of decomposing an application into different smaller services is that it improves **modularity**. This makes the application easier to understand, develop, test, and become more resilient to architecture erosion. It **parallelizes development** by enabling small autonomous teams to **develop, deploy and scale** their respective services independently. It also allows the architecture of an individual service to emerge through **continuous refactoring**. Microservices-based architectures enable **continuous delivery and deployment**."*
diff --git a/docs/en/framework/architecture/modularity/basics.md b/docs/en/framework/architecture/modularity/basics.md
index f7a69bbe7d..727c40f517 100644
--- a/docs/en/framework/architecture/modularity/basics.md
+++ b/docs/en/framework/architecture/modularity/basics.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to build modular applications with ABP Framework, including best practices, templates, and CLI support for seamless development."
+}
+```
+
# Modularity
ABP was designed to support to build fully modular applications and systems where every module may have entities, services, database integration, APIs, UI components and so on;
diff --git a/docs/en/framework/architecture/modularity/extending/customizing-application-modules-extending-entities.md b/docs/en/framework/architecture/modularity/extending/customizing-application-modules-extending-entities.md
index 034c5b6956..c46ec6d7b4 100644
--- a/docs/en/framework/architecture/modularity/extending/customizing-application-modules-extending-entities.md
+++ b/docs/en/framework/architecture/modularity/extending/customizing-application-modules-extending-entities.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to extend entities in ABP Framework by adding extra properties to seamlessly customize your application modules."
+}
+```
+
# Customizing the Application Modules: Extending Entities
In some cases, you may want to add some additional properties (and database fields) for an entity defined in a depended module. This section will cover some different approaches to make this possible.
diff --git a/docs/en/framework/architecture/modularity/extending/customizing-application-modules-guide.md b/docs/en/framework/architecture/modularity/extending/customizing-application-modules-guide.md
index 87a1ba0f4f..1d6c5ffe99 100644
--- a/docs/en/framework/architecture/modularity/extending/customizing-application-modules-guide.md
+++ b/docs/en/framework/architecture/modularity/extending/customizing-application-modules-guide.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize and reuse ABP's pre-built application modules for efficient and modular application development."
+}
+```
+
# Customizing the Existing Modules
ABP has been designed to support to build fully [modular applications](../../modularity/basics.md) and systems. It also provides some [pre-built application modules](../../../../modules) those are **ready to use** in any kind of application.
diff --git a/docs/en/framework/architecture/modularity/extending/customizing-application-modules-overriding-services.md b/docs/en/framework/architecture/modularity/extending/customizing-application-modules-overriding-services.md
index dbc2f48d5f..4327d99e55 100644
--- a/docs/en/framework/architecture/modularity/extending/customizing-application-modules-overriding-services.md
+++ b/docs/en/framework/architecture/modularity/extending/customizing-application-modules-overriding-services.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize ABP application modules by overriding services using dependency injection for tailored business logic."
+}
+```
+
# Customizing the Application Modules: Overriding Services
You may need to **change behavior (business logic)** of a depended module for your application. In this case, you can use the power of the [dependency injection system](../../../fundamentals/dependency-injection.md) to replace a service, controller or even a page model of the depended module by your own implementation.
diff --git a/docs/en/framework/architecture/modularity/extending/module-entity-extensions.md b/docs/en/framework/architecture/modularity/extending/module-entity-extensions.md
index ac041895d7..076238b444 100644
--- a/docs/en/framework/architecture/modularity/extending/module-entity-extensions.md
+++ b/docs/en/framework/architecture/modularity/extending/module-entity-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to extend existing entities in ABP Framework modules by adding new properties seamlessly across the entire system."
+}
+```
+
# Module Entity Extensions
Module entity extension system is a **high level** extension system that allows you to **define new properties** for existing entities of the depended modules. It automatically **adds properties to the entity, database, HTTP API and the user interface** in a single point.
diff --git a/docs/en/framework/architecture/modularity/extending/overriding-user-interface.md b/docs/en/framework/architecture/modularity/extending/overriding-user-interface.md
index 62e77e908c..3beb02fff8 100644
--- a/docs/en/framework/architecture/modularity/extending/overriding-user-interface.md
+++ b/docs/en/framework/architecture/modularity/extending/overriding-user-interface.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize and override the user interface for ABP Framework modules using various UI frameworks like ASP.NET Core, Angular, and Blazor."
+}
+```
+
# Overriding the User Interface
You may want to override a page, a component, a JavaScript, CSS or an image file of your depended module. Overriding the UI completely depends on the UI framework you're using. Select the UI framework to continue:
diff --git a/docs/en/framework/architecture/modularity/plugin-modules.md b/docs/en/framework/architecture/modularity/plugin-modules.md
index ce9e64f655..c447bb383f 100644
--- a/docs/en/framework/architecture/modularity/plugin-modules.md
+++ b/docs/en/framework/architecture/modularity/plugin-modules.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to load modules as plug-ins in your ABP Framework application, enabling flexible module management without direct assembly references."
+}
+```
+
# Plug-In Modules
[Modules](../modularity/basics.md) can also be loaded as plug-ins. This means that you don’t need to reference a module’s assembly directly in your solution; instead, you can load it during application startup in the same way as any other module.
diff --git a/docs/en/framework/architecture/multi-tenancy/index.md b/docs/en/framework/architecture/multi-tenancy/index.md
index 21bb054b6a..c58769e57e 100644
--- a/docs/en/framework/architecture/multi-tenancy/index.md
+++ b/docs/en/framework/architecture/multi-tenancy/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how ABP Framework enables developers to build powerful multi-tenant applications, optimizing resource sharing for SaaS solutions."
+}
+```
+
# Multi-Tenancy
Multi-Tenancy is a widely used architecture to create **SaaS applications** where the hardware and software **resources are shared by the customers** (tenants). ABP provides all the base functionalities to create **multi tenant applications**.
diff --git a/docs/en/framework/dapr/index.md b/docs/en/framework/dapr/index.md
index 8083cc8813..c83b4f65f9 100644
--- a/docs/en/framework/dapr/index.md
+++ b/docs/en/framework/dapr/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Dapr with ABP Framework for streamlined microservice communication and enhanced developer experience."
+}
+```
+
# ABP Dapr Integration
> This document assumes that you are already familiar with [Dapr](https://dapr.io/) and you want to use it in your ABP based applications.
diff --git a/docs/en/framework/data/dapper/index.md b/docs/en/framework/data/dapper/index.md
index 840246eb0f..d9a823714b 100644
--- a/docs/en/framework/data/dapper/index.md
+++ b/docs/en/framework/data/dapper/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Dapper with ABP Framework for high-performance data access, simplifying repository creation while leveraging EF Core."
+}
+```
+
# Dapper Integration
[Dapper](https://github.com/DapperLib/Dapper) is a simple and lightweight object mapper for .NET. A key feature of Dapper is its [high performance](https://github.com/DapperLib/Dapper#performance) compared to other ORMs.
diff --git a/docs/en/framework/data/entity-framework-core/index.md b/docs/en/framework/data/entity-framework-core/index.md
index e462662410..418c040565 100644
--- a/docs/en/framework/data/entity-framework-core/index.md
+++ b/docs/en/framework/data/entity-framework-core/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Entity Framework Core with ABP applications, including installation and configuration for seamless database management."
+}
+```
+
# Entity Framework Core Integration
This document explains how to integrate EF Core as an ORM provider to ABP based applications and how to configure it.
@@ -139,7 +146,7 @@ Configure(options =>
});
````
-Add actions for the `ConfigureConventions` and `OnModelCreating` methods of the `DbContext` as shown below:
+Add actions for the `ConfigureConventions`, `OnModelCreating` and `OnConfiguring` methods of the `DbContext` as shown below:
````csharp
Configure(options =>
@@ -163,6 +170,15 @@ Configure(options =>
{
// This action is called for OnModelCreating method of specific DbContext.
});
+
+ options.ConfigureDefaultOnConfiguring((dbContext, optionsBuilder) =>
+ {
+ // This action is called for OnConfiguring method of all DbContexts.
+ });
+ options.ConfigureOnConfiguring((dbContext, optionsBuilder) =>
+ {
+ // This action is called for OnConfiguring method of specific DbContext.
+ });
});
````
diff --git a/docs/en/framework/data/entity-framework-core/migrations.md b/docs/en/framework/data/entity-framework-core/migrations.md
index 93a5e3905f..173fc32d4b 100644
--- a/docs/en/framework/data/entity-framework-core/migrations.md
+++ b/docs/en/framework/data/entity-framework-core/migrations.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize database migrations in EF Core with the ABP Framework, enhancing your application's structure and management."
+}
+```
+
# EF Core Database Migrations
This document begins by **introducing the default structure** provided by [the application startup template](../../../solution-templates/layered-web-application) and **discusses various scenarios** you may want to implement for your own application.
diff --git a/docs/en/framework/data/entity-framework-core/mysql.md b/docs/en/framework/data/entity-framework-core/mysql.md
index 8f299bdee4..f5254e2419 100644
--- a/docs/en/framework/data/entity-framework-core/mysql.md
+++ b/docs/en/framework/data/entity-framework-core/mysql.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to switch your ABP Framework application to the MySQL database provider, replacing the default SQL Server setup effortlessly."
+}
+```
+
# Switch to EF Core MySQL Provider
> [ABP CLI](../../../cli/index.md) and the [Get Started](https://abp.io/get-started) page already provides an option to create a new solution with MySQL. See [that document](./other-dbms.md) to learn how to use. This document provides guidance for who wants to manually switch to MySQL after creating the solution.
@@ -25,11 +32,22 @@ Find `UseSqlServer()` calls in your solution. Check the following files:
Alternatively, you can use the [Pomelo.EntityFrameworkCore.MySql](https://www.nuget.org/packages/Pomelo.EntityFrameworkCore.MySql) provider. Replace the [Volo.Abp.EntityFrameworkCore.MySQL](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.MySQL) package with the [Volo.Abp.EntityFrameworkCore.MySQL.Pomelo](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.MySQL.Pomelo) package in your `.EntityFrameworkCore` project.
-Find ***YourProjectName*EntityFrameworkCoreModule** class inside the `.EntityFrameworkCore` project, replace `typeof(AbpEntityFrameworkCoreMySQLModule)` with `typeof(AbpEntityFrameworkCoreMySQLPomeloModule)` in the `DependsOn` attribute.
+To complete the switch to the Pomelo Provider, you'll need to update your module dependencies. To do that, find ***YourProjectName*EntityFrameworkCoreModule** class inside the `.EntityFrameworkCore` project, replace `typeof(AbpEntityFrameworkCoreMySQLModule)` with `typeof(AbpEntityFrameworkCoreMySQLPomeloModule)` in the `DependsOn` attribute.
-> Depending on your solution structure, you may find more code files need to be changed.
+Also, if you are switching from a provider other than ABP's MySQL provider, you need to call the `UseMySQL` method in the relevant places, as described in the next section.
+
+### UseMySQL()
+
+Find `UseSqlServer()` calls in your solution. Check the following files:
-The `UseMySQL()` method calls remain the same, no changes needed.
+* *YourProjectName*EntityFrameworkCoreModule.cs inside the `.EntityFrameworkCore` project. Replace `UseSqlServer()` with `UseMySql()`.
+* *YourProjectName*DbContextFactory.cs inside the `.EntityFrameworkCore` project. Replace `UseSqlServer()` with `UseMySql()`.
+
+You also need to specify the `ServerVersion`. See https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/wiki/Configuration-Options#server-version for more details.
+
+`UseMySql(configuration.GetConnectionString("Default"), ServerVersion.AutoDetect(configuration.GetConnectionString("Default")));` or `UseMySql(configuration.GetConnectionString("Default"), new MySqlServerVersion(new Version(8, 4, 6)));`
+
+> Depending on your solution structure, you may find more code files need to be changed.
## Change the Connection Strings
diff --git a/docs/en/framework/data/entity-framework-core/oracle-devart.md b/docs/en/framework/data/entity-framework-core/oracle-devart.md
index 01e9ce7cc2..2e0233958e 100644
--- a/docs/en/framework/data/entity-framework-core/oracle-devart.md
+++ b/docs/en/framework/data/entity-framework-core/oracle-devart.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to switch to the Oracle Devart provider for your ABP application, ensuring compatibility with Oracle v12.2+ for seamless database integration."
+}
+```
+
# Switch to EF Core Oracle Devart Provider
This document explains how to switch to the **Oracle** database provider for **[the application startup template](../../../solution-templates/layered-web-application)** which comes with SQL Server provider pre-configured.
diff --git a/docs/en/framework/data/entity-framework-core/oracle-official.md b/docs/en/framework/data/entity-framework-core/oracle-official.md
index 12509306db..b786b30ba8 100644
--- a/docs/en/framework/data/entity-framework-core/oracle-official.md
+++ b/docs/en/framework/data/entity-framework-core/oracle-official.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to switch your ABP application to use the EF Core Oracle provider, ensuring compatibility with Oracle version 12.2 and above."
+}
+```
+
# Switch to EF Core Oracle Provider
This document explains how to switch to the **Oracle** database provider for **[the application startup template](../../../solution-templates/layered-web-application)** which comes with SQL Server provider pre-configured.
diff --git a/docs/en/framework/data/entity-framework-core/oracle.md b/docs/en/framework/data/entity-framework-core/oracle.md
index 4d757260f8..9e855ea08e 100644
--- a/docs/en/framework/data/entity-framework-core/oracle.md
+++ b/docs/en/framework/data/entity-framework-core/oracle.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to switch your ABP application to use the Oracle database provider, with guidance on both official and commercial drivers."
+}
+```
+
# Switch to EF Core Oracle Provider
> [ABP CLI](../../../cli/index.md) and the [Get Started](https://abp.io/get-started) page already provides an option to create a new solution with Oracle. See [that document](other-dbms.md) to learn how to use. This document provides guidance for who wants to manually switch to Oracle after creating the solution.
diff --git a/docs/en/framework/data/entity-framework-core/other-dbms.md b/docs/en/framework/data/entity-framework-core/other-dbms.md
index a59328533b..e07a5fb122 100644
--- a/docs/en/framework/data/entity-framework-core/other-dbms.md
+++ b/docs/en/framework/data/entity-framework-core/other-dbms.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to switch your DBMS for Entity Framework Core in ABP Framework, allowing flexibility to choose your preferred database solution."
+}
+```
+
# Switch to Another DBMS for Entity Framework Core
[ABP CLI](../../../cli/index.md) provides a `-dbms` option to allow you to choose your Database Management System (DBMS) while creating a new solution. It accepts the following values:
diff --git a/docs/en/framework/data/entity-framework-core/postgresql.md b/docs/en/framework/data/entity-framework-core/postgresql.md
index e25cc2c5fb..5aae60671d 100644
--- a/docs/en/framework/data/entity-framework-core/postgresql.md
+++ b/docs/en/framework/data/entity-framework-core/postgresql.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to switch your ABP Framework application from SQL Server to PostgreSQL with step-by-step guidance for a smooth transition."
+}
+```
+
# Switch to EF Core PostgreSQL Provider
> [ABP CLI](../../../cli) and the [Get Started](https://abp.io/get-started) page already provides an option to create a new solution with PostgreSQL. See [that document](./other-dbms.md) to learn how to use. This document provides guidance for who wants to manually switch to PostgreSQL after creating the solution.
diff --git a/docs/en/framework/data/entity-framework-core/sqlite.md b/docs/en/framework/data/entity-framework-core/sqlite.md
index a837b2227a..4c5c7b81dc 100644
--- a/docs/en/framework/data/entity-framework-core/sqlite.md
+++ b/docs/en/framework/data/entity-framework-core/sqlite.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to switch your ABP Framework application to use the SQLite database provider with this step-by-step guide."
+}
+```
+
# Switch to EF Core SQLite Provider
> [ABP CLI](../../../cli) and the [Get Started](https://abp.io/get-started) page already provides an option to create a new solution with SQLite. See [that document](other-dbms.md) to learn how to use. This document provides guidance for who wants to manually switch to SQLite after creating the solution.
diff --git a/docs/en/framework/data/index.md b/docs/en/framework/data/index.md
index c6b1ba3d19..9c0ff7868a 100644
--- a/docs/en/framework/data/index.md
+++ b/docs/en/framework/data/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's database-agnostic data access, featuring repositories and unit of work for Entity Framework Core, MongoDB, and Dapper."
+}
+```
+
# Data Access
ABP was designed as database agnostic. It can work any type of data source by the help of the [repository](../architecture/domain-driven-design/repositories.md) and [unit of work](../architecture/domain-driven-design/unit-of-work.md) abstractions. Currently, the following providers are implemented as official:
diff --git a/docs/en/framework/data/mongodb/index.md b/docs/en/framework/data/mongodb/index.md
index d5bb4124aa..b609e22963 100644
--- a/docs/en/framework/data/mongodb/index.md
+++ b/docs/en/framework/data/mongodb/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate MongoDB with ABP applications, including installation and configuration steps for seamless database management."
+}
+```
+
# MongoDB Integration
This document explains how to integrate MongoDB as a database provider to ABP based applications and how to configure it.
diff --git a/docs/en/framework/fundamentals/application-startup.md b/docs/en/framework/fundamentals/application-startup.md
index e985048714..4c323c1c52 100644
--- a/docs/en/framework/fundamentals/application-startup.md
+++ b/docs/en/framework/fundamentals/application-startup.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively start your ABP application using templates, and understand the integration and configuration details for customization."
+}
+```
+
# ABP Application Startup
You typically use the [ABP CLI](../../cli)'s `abp new` command to [get started](../../get-started/layered-web-application.md) with one of the pre-built [startup solution templates](../../solution-templates). When you do that, you generally don't need to know the details of how the ABP is integrated with your application or how it is configured and initialized. The startup template also comes with the fundamental ABP packages and [application modules](../../modules) are pre-installed and configured for you.
diff --git a/docs/en/framework/fundamentals/authorization.md b/docs/en/framework/fundamentals/authorization.md
index 87c4776015..0dae7bbf13 100644
--- a/docs/en/framework/fundamentals/authorization.md
+++ b/docs/en/framework/fundamentals/authorization.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to leverage ABP Framework's enhanced authorization features, including permissions and policies, to secure your applications efficiently."
+}
+```
+
# Authorization
Authorization is used to check if a user is allowed to perform some specific operations in the application.
diff --git a/docs/en/framework/fundamentals/autofac-integration.md b/docs/en/framework/fundamentals/autofac-integration.md
index 02b6f8a1c5..ac0abfc3d8 100644
--- a/docs/en/framework/fundamentals/autofac-integration.md
+++ b/docs/en/framework/fundamentals/autofac-integration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Autofac with ABP Framework for advanced dependency injection features, enhancing your .NET applications effortlessly."
+}
+```
+
# Autofac Integration
[Autofac](https://autofac.org/) is one of the most used dependency injection frameworks for .NET. It provides advanced features compared to .Net Core's standard DI library, like dynamic proxying and property injection.
diff --git a/docs/en/framework/fundamentals/caching.md b/docs/en/framework/fundamentals/caching.md
index 75dab91543..f52cd9e07d 100644
--- a/docs/en/framework/fundamentals/caching.md
+++ b/docs/en/framework/fundamentals/caching.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement distributed caching in ABP Framework for efficient memory management and improved application performance."
+}
+```
+
# Distributed Caching
ABP extends the [ASP.NET Core distributed cache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) to provide a more comfortable and easy-to-use cache service.
diff --git a/docs/en/framework/fundamentals/configuration.md b/docs/en/framework/fundamentals/configuration.md
index 997d347d2a..ab77ffa0a4 100644
--- a/docs/en/framework/fundamentals/configuration.md
+++ b/docs/en/framework/fundamentals/configuration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore how to leverage ASP.NET Core's flexible configuration system with ABP Framework for effective application management and customization."
+}
+```
+
# Configuration
ASP.NET Core has an flexible and extensible key-value based configuration system. The configuration system is a part of Microsoft.Extensions libraries and it is independent from ASP.NET Core. That means it can be used in any type of application.
diff --git a/docs/en/framework/fundamentals/connection-strings.md b/docs/en/framework/fundamentals/connection-strings.md
index 0f1a5b4bc8..c791e6043f 100644
--- a/docs/en/framework/fundamentals/connection-strings.md
+++ b/docs/en/framework/fundamentals/connection-strings.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage connection strings in ABP for modular and multi-tenant applications, enabling flexible database configurations."
+}
+```
+
# Connection Strings
> Connection string system is especially needed when you want to create or use a modular system. If you have a monolithic application with a single database, you can go with the [ABP startup solution template](../../solution-templates/layered-web-application), which is properly configured for you.
diff --git a/docs/en/framework/fundamentals/dependency-injection.md b/docs/en/framework/fundamentals/dependency-injection.md
index 9dda3aef45..a1eef66761 100644
--- a/docs/en/framework/fundamentals/dependency-injection.md
+++ b/docs/en/framework/fundamentals/dependency-injection.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to leverage ABP's Dependency Injection system for modular service registration and dynamic proxying with best practices and tips."
+}
+```
+
# Dependency Injection
ABP's Dependency Injection system is developed based on Microsoft's [dependency injection extension](https://medium.com/volosoft/asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96) library (Microsoft.Extensions.DependencyInjection nuget package). So, its documentation is valid in ABP too.
diff --git a/docs/en/framework/fundamentals/dynamic-claims.md b/docs/en/framework/fundamentals/dynamic-claims.md
index f326ac444d..03ddc701cd 100644
--- a/docs/en/framework/fundamentals/dynamic-claims.md
+++ b/docs/en/framework/fundamentals/dynamic-claims.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement dynamic claims in ABP Framework to ensure real-time updates of claims in user sessions for enhanced security."
+}
+```
+
# Dynamic Claims
When a client authenticates and obtains an access token or an authentication cookie, the claims in that token or cookie are not changed unless it re-authenticates. That is not a problem for most claims since the claim values do not frequently change. However, for some claims, it may be required to immediately see the impact after the claim values change in the current session. For example, if a role is revoked from a user, you want to see its effect in the next request. Otherwise, the user will continue to use that role's permissions until re-login to the application.
diff --git a/docs/en/framework/fundamentals/exception-handling.md b/docs/en/framework/fundamentals/exception-handling.md
index a85ae58e24..73e5d055fe 100644
--- a/docs/en/framework/fundamentals/exception-handling.md
+++ b/docs/en/framework/fundamentals/exception-handling.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how ABP Framework simplifies exception handling with automatic formatting, localization, and HTTP status code mapping for seamless API responses."
+}
+```
+
# Exception Handling
ABP provides a built-in infrastructure and offers a standard model for handling exceptions.
diff --git a/docs/en/framework/fundamentals/fluent-validation.md b/docs/en/framework/fundamentals/fluent-validation.md
index 207cddcbd3..8270e65b72 100644
--- a/docs/en/framework/fundamentals/fluent-validation.md
+++ b/docs/en/framework/fundamentals/fluent-validation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate FluentValidation with ABP Framework for enhanced validation capabilities in your applications."
+}
+```
+
# FluentValidation Integration
ABP [Validation](./validation.md) infrastructure is extensible. [Volo.Abp.FluentValidation](https://www.nuget.org/packages/Volo.Abp.FluentValidation) NuGet package extends the validation system to work with the [FluentValidation](https://fluentvalidation.net/) library.
diff --git a/docs/en/framework/fundamentals/index.md b/docs/en/framework/fundamentals/index.md
index 8d35df9631..6aef484c41 100644
--- a/docs/en/framework/fundamentals/index.md
+++ b/docs/en/framework/fundamentals/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the essential building blocks of ABP Framework solutions, covering startup, authorization, caching, and more for efficient development."
+}
+```
+
# ABP Fundamentals: Overview
The following documents explains the fundamental building blocks to create ABP solutions:
diff --git a/docs/en/framework/fundamentals/localization.md b/docs/en/framework/fundamentals/localization.md
index 47c4ca564a..7a4fcf24ac 100644
--- a/docs/en/framework/fundamentals/localization.md
+++ b/docs/en/framework/fundamentals/localization.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively use ABP's localization system, enhancing your applications with features from Microsoft.Extensions.Localization."
+}
+```
+
# Localization
ABP's localization system is seamlessly integrated to the `Microsoft.Extensions.Localization` package and compatible with the [Microsoft's localization documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization). It adds some useful features and enhancements to make it easier to use in real life application scenarios.
diff --git a/docs/en/framework/fundamentals/logging.md b/docs/en/framework/fundamentals/logging.md
index 27c8d7ba19..94056400c7 100644
--- a/docs/en/framework/fundamentals/logging.md
+++ b/docs/en/framework/fundamentals/logging.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize ASP.NET Core's logging system in ABP Framework for effective application logging and monitoring."
+}
+```
+
# Logging
ABP doesn't implement any logging infrastructure. It uses the [ASP.NET Core's logging system](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging).
diff --git a/docs/en/framework/fundamentals/object-extensions.md b/docs/en/framework/fundamentals/object-extensions.md
index 87ece27f75..799513d7be 100644
--- a/docs/en/framework/fundamentals/object-extensions.md
+++ b/docs/en/framework/fundamentals/object-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how ABP's object extension system lets you add properties to existing objects effortlessly without altering the original class."
+}
+```
+
# Object Extensions
ABP provides an **object extension system** to allow you to **add extra properties** to an existing object **without modifying** the related class. This allows to extend functionalities implemented by a depended [application module](../../modules), especially when you want to [extend entities](../architecture/modularity/extending/customizing-application-modules-extending-entities.md) and [DTOs](../architecture/modularity/extending/customizing-application-modules-overriding-services.md) defined by the module.
diff --git a/docs/en/framework/fundamentals/options.md b/docs/en/framework/fundamentals/options.md
index 3602e5acee..d18c89c675 100644
--- a/docs/en/framework/fundamentals/options.md
+++ b/docs/en/framework/fundamentals/options.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the options pattern in ABP Framework to configure settings efficiently for your applications."
+}
+```
+
# Options
Microsoft has introduced [the options pattern](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options) that is used to configure a group of settings used by the framework services. This pattern is implemented by the [Microsoft.Extensions.Options](https://www.nuget.org/packages/Microsoft.Extensions.Options) NuGet package, so it is usable by any type of applications in addition to ASP.NET Core based applications.
diff --git a/docs/en/framework/fundamentals/redis-cache.md b/docs/en/framework/fundamentals/redis-cache.md
index 55d05fb942..efb2fd763f 100644
--- a/docs/en/framework/fundamentals/redis-cache.md
+++ b/docs/en/framework/fundamentals/redis-cache.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your ABP application with Redis Cache integration for improved performance and advanced caching capabilities."
+}
+```
+
# Redis Cache
ABP [Caching System](./caching.md) extends the [ASP.NET Core distributed cache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed). So, **any provider** supported by the standard ASP.NET Core distributed cache can be usable in your application and can be configured just like **documented by Microsoft**.
diff --git a/docs/en/framework/fundamentals/validation.md b/docs/en/framework/fundamentals/validation.md
index 600f93914f..50540b5625 100644
--- a/docs/en/framework/fundamentals/validation.md
+++ b/docs/en/framework/fundamentals/validation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how ABP Framework enhances ASP.NET Core validation with automatic checks, localization, and FluentValidation integration for better input handling."
+}
+```
+
# Validation
Validation system is used to validate the user input or client request for a particular controller action or service method.
diff --git a/docs/en/framework/infrastructure/audit-logging.md b/docs/en/framework/infrastructure/audit-logging.md
index 2e6dc83940..e559e5ed22 100644
--- a/docs/en/framework/infrastructure/audit-logging.md
+++ b/docs/en/framework/infrastructure/audit-logging.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover ABP's extensible audit logging system, enabling automated, configurable tracking of web request activities and changes for enhanced security."
+}
+```
+
# Audit Logging
[Wikipedia](https://en.wikipedia.org/wiki/Audit_trail): "*An audit trail (also called **audit log**) is a security-relevant chronological record, set of records, and/or destination and source of records that provide documentary evidence of the sequence of activities that have affected at any time a specific operation, procedure, or event*".
diff --git a/docs/en/framework/infrastructure/background-jobs/hangfire.md b/docs/en/framework/infrastructure/background-jobs/hangfire.md
index 8377f001c0..61408f303d 100644
--- a/docs/en/framework/infrastructure/background-jobs/hangfire.md
+++ b/docs/en/framework/infrastructure/background-jobs/hangfire.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Integrate Hangfire with the ABP Framework for efficient background job management, ensuring code independence and seamless functionality."
+}
+```
+
# Hangfire Background Job Manager
[Hangfire](https://www.hangfire.io/) is an advanced background job manager. You can integrate Hangfire with the ABP to use it instead of the [default background job manager](../background-jobs). In this way, you can use the same background job API for Hangfire and your code will be independent of Hangfire. If you like, you can directly use Hangfire's API, too.
diff --git a/docs/en/framework/infrastructure/background-jobs/index.md b/docs/en/framework/infrastructure/background-jobs/index.md
index 3b5628d39f..0d5e19442c 100644
--- a/docs/en/framework/infrastructure/background-jobs/index.md
+++ b/docs/en/framework/infrastructure/background-jobs/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement background jobs in ABP Framework for efficient task execution, ensuring persistence and reliability in your applications."
+}
+```
+
# Background Jobs
## Introduction
@@ -318,12 +325,12 @@ public override void PreConfigureServices(ServiceConfigurationContext context)
Set `DefaultQueueNamePrefix` and `DefaultDelayedQueueNamePrefix` properties in `AbpRabbitMqBackgroundJobOptions` to your application's name:
````csharp
-public override void PreConfigureServices(ServiceConfigurationContext context)
+public override void ConfigureServices(ServiceConfigurationContext context)
{
- PreConfigure(options =>
+ Configure(options =>
{
- options.DefaultQueueNamePrefix = context.Services.GetApplicationName()!.EndsWith('.') + options.DefaultQueueNamePrefix;
- options.DefaultDelayedQueueNamePrefix = context.Services.GetApplicationName()!.EndsWith('.') + options.DefaultDelayedQueueNamePrefix;
+ options.DefaultQueueNamePrefix = context.Services.GetApplicationName()!.EnsureEndsWith('.') + options.DefaultQueueNamePrefix;
+ options.DefaultDelayedQueueNamePrefix = context.Services.GetApplicationName()!.EnsureEndsWith('.') + options.DefaultDelayedQueueNamePrefix;
});
}
````
diff --git a/docs/en/framework/infrastructure/background-jobs/quartz.md b/docs/en/framework/infrastructure/background-jobs/quartz.md
index 1b18fd36ae..6fdf9467f0 100644
--- a/docs/en/framework/infrastructure/background-jobs/quartz.md
+++ b/docs/en/framework/infrastructure/background-jobs/quartz.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Quartz with ABP Framework for advanced background job management, enhancing your job processing capabilities effortlessly."
+}
+```
+
# Quartz Background Job Manager
[Quartz](https://www.quartz-scheduler.net/) is an advanced background job manager. You can integrate Quartz with the ABP to use it instead of the [default background job manager](../background-jobs). In this way, you can use the same background job API for Quartz and your code will be independent of Quartz. If you like, you can directly use Quartz's API, too.
diff --git a/docs/en/framework/infrastructure/background-jobs/rabbitmq.md b/docs/en/framework/infrastructure/background-jobs/rabbitmq.md
index ec84a92d4b..06ea241cc3 100644
--- a/docs/en/framework/infrastructure/background-jobs/rabbitmq.md
+++ b/docs/en/framework/infrastructure/background-jobs/rabbitmq.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to install and configure RabbitMQ for background job execution in your ABP Framework projects effectively."
+}
+```
+
# RabbitMQ Background Job Manager
RabbitMQ is an industry standard message broker. While it is typically used for inter-process communication (messaging / distributed events), it is pretty useful to store and execute background jobs in FIFO (First In First Out) order.
diff --git a/docs/en/framework/infrastructure/background-workers/hangfire.md b/docs/en/framework/infrastructure/background-workers/hangfire.md
index 7fec8be273..832084de4c 100644
--- a/docs/en/framework/infrastructure/background-workers/hangfire.md
+++ b/docs/en/framework/infrastructure/background-workers/hangfire.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Integrate Hangfire with ABP Framework to efficiently manage background jobs and leverage advanced scheduling for recurring tasks."
+}
+```
+
# Hangfire Background Worker Manager
[Hangfire](https://www.hangfire.io/) is an advanced background jobs and worker manager. You can integrate Hangfire with the ABP to use it instead of the [default background worker manager](../background-workers).
diff --git a/docs/en/framework/infrastructure/background-workers/index.md b/docs/en/framework/infrastructure/background-workers/index.md
index 498a52ed9b..6204857d8c 100644
--- a/docs/en/framework/infrastructure/background-workers/index.md
+++ b/docs/en/framework/infrastructure/background-workers/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and manage background workers in your application using the ABP Framework for efficient task automation."
+}
+```
+
# Background Workers
## Introduction
@@ -199,12 +206,12 @@ public override void PreConfigureServices(ServiceConfigurationContext context)
Set `DefaultQueueNamePrefix` and `DefaultDelayedQueueNamePrefix` properties in `AbpRabbitMqBackgroundJobOptions` to your application's name:
````csharp
-public override void PreConfigureServices(ServiceConfigurationContext context)
+public override void ConfigureServices(ServiceConfigurationContext context)
{
- PreConfigure(options =>
+ Configure(options =>
{
- options.DefaultQueueNamePrefix = context.Services.GetApplicationName()!.EndsWith('.') + options.DefaultQueueNamePrefix;
- options.DefaultDelayedQueueNamePrefix = context.Services.GetApplicationName()!.EndsWith('.') + options.DefaultDelayedQueueNamePrefix;
+ options.DefaultQueueNamePrefix = context.Services.GetApplicationName()!.EnsureEndsWith('.') + options.DefaultQueueNamePrefix;
+ options.DefaultDelayedQueueNamePrefix = context.Services.GetApplicationName()!.EnsureEndsWith('.') + options.DefaultDelayedQueueNamePrefix;
});
}
````
diff --git a/docs/en/framework/infrastructure/background-workers/quartz.md b/docs/en/framework/infrastructure/background-workers/quartz.md
index 909371adb0..7f591e0aeb 100644
--- a/docs/en/framework/infrastructure/background-workers/quartz.md
+++ b/docs/en/framework/infrastructure/background-workers/quartz.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Integrate Quartz as your background worker manager in ABP Framework with easy installation steps and enhance your application's performance."
+}
+```
+
# Quartz Background Worker Manager
[Quartz](https://www.quartz-scheduler.net/) is an advanced background worker manager. You can integrate Quartz with the ABP to use it instead of the [default background worker manager](../background-workers). ABP simply integrates quartz.
diff --git a/docs/en/framework/infrastructure/blob-storing/aliyun.md b/docs/en/framework/infrastructure/blob-storing/aliyun.md
index 97c8895886..57ff1ca3a5 100644
--- a/docs/en/framework/infrastructure/blob-storing/aliyun.md
+++ b/docs/en/framework/infrastructure/blob-storing/aliyun.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure Aliyun Blob storage with the ABP Framework for efficient BLOB storage in your applications."
+}
+```
+
# BLOB Storing Aliyun Provider
BLOB Storing Aliyun Provider can store BLOBs in [Aliyun Blob storage](https://help.aliyun.com/product/31815.html).
diff --git a/docs/en/framework/infrastructure/blob-storing/aws.md b/docs/en/framework/infrastructure/blob-storing/aws.md
index 4eac484e92..35293ec922 100644
--- a/docs/en/framework/infrastructure/blob-storing/aws.md
+++ b/docs/en/framework/infrastructure/blob-storing/aws.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure AWS as a BLOB storage provider in your ABP Framework project using the Volo.Abp.BlobStoring.Aws package."
+}
+```
+
# BLOB Storing Aws Provider
BLOB Storing Aws Provider can store BLOBs in [Amazon Simple Storage Service](https://aws.amazon.com/s3/).
diff --git a/docs/en/framework/infrastructure/blob-storing/azure.md b/docs/en/framework/infrastructure/blob-storing/azure.md
index ddaab1e08f..234c369ecd 100644
--- a/docs/en/framework/infrastructure/blob-storing/azure.md
+++ b/docs/en/framework/infrastructure/blob-storing/azure.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure Azure Blob storage for your project using the ABP Framework with this concise guide on the BLOB Storing Azure Provider."
+}
+```
+
# BLOB Storing Azure Provider
BLOB Storing Azure Provider can store BLOBs in [Azure Blob storage](https://azure.microsoft.com/en-us/services/storage/blobs/).
diff --git a/docs/en/framework/infrastructure/blob-storing/custom-provider.md b/docs/en/framework/infrastructure/blob-storing/custom-provider.md
index 1713d444b5..033dbdcfd7 100644
--- a/docs/en/framework/infrastructure/blob-storing/custom-provider.md
+++ b/docs/en/framework/infrastructure/blob-storing/custom-provider.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create a custom BLOB storage provider in ABP Framework with practical examples and implementation details."
+}
+```
+
# BLOB Storing: Creating a Custom Provider
This document explains how you can create a new storage provider for the BLOB storing system with an example.
diff --git a/docs/en/framework/infrastructure/blob-storing/database.md b/docs/en/framework/infrastructure/blob-storing/database.md
index 7d533b0d81..1b568c247c 100644
--- a/docs/en/framework/infrastructure/blob-storing/database.md
+++ b/docs/en/framework/infrastructure/blob-storing/database.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure BLOB storage in relational and non-relational databases using ABP Framework's database providers for seamless data management."
+}
+```
+
# BLOB Storing Database Provider
BLOB Storing Database Storage Provider can store BLOBs in a relational or non-relational database.
diff --git a/docs/en/framework/infrastructure/blob-storing/file-system.md b/docs/en/framework/infrastructure/blob-storing/file-system.md
index af15abf037..e9b8d90366 100644
--- a/docs/en/framework/infrastructure/blob-storing/file-system.md
+++ b/docs/en/framework/infrastructure/blob-storing/file-system.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure the BLOB Storing File System Provider in ABP Framework to efficiently store files locally with ease."
+}
+```
+
# BLOB Storing File System Provider
File System Storage Provider is used to store BLOBs in the local file system as standard files inside a folder.
diff --git a/docs/en/framework/infrastructure/blob-storing/google.md b/docs/en/framework/infrastructure/blob-storing/google.md
index bd7f7c1fbf..6b6670c018 100644
--- a/docs/en/framework/infrastructure/blob-storing/google.md
+++ b/docs/en/framework/infrastructure/blob-storing/google.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure BLOB storage in Google Cloud with ABP Framework, enhancing your project's cloud capabilities effortlessly."
+}
+```
+
# BLOB Storing Google Provider
BLOB Storing Google Provider can store BLOBs in [Google Cloud Storage](https://cloud.google.com/storage).
diff --git a/docs/en/framework/infrastructure/blob-storing/index.md b/docs/en/framework/infrastructure/blob-storing/index.md
index 676757ad80..3672e43387 100644
--- a/docs/en/framework/infrastructure/blob-storing/index.md
+++ b/docs/en/framework/infrastructure/blob-storing/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently store and manage BLOBs in your applications using ABP Framework's built-in storage solutions and abstractions."
+}
+```
+
# BLOB Storing
It is typical to **store file contents** in an application and read these file contents on need. Not only files, but you may also need to save various types of **large binary objects**, a.k.a. [BLOB](https://en.wikipedia.org/wiki/Binary_large_object)s, into a **storage**. For example, you may want to save user profile pictures.
diff --git a/docs/en/framework/infrastructure/blob-storing/minio.md b/docs/en/framework/infrastructure/blob-storing/minio.md
index 771b699278..bffba04b01 100644
--- a/docs/en/framework/infrastructure/blob-storing/minio.md
+++ b/docs/en/framework/infrastructure/blob-storing/minio.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure the MinIO BLOB Storing Provider in your ABP Framework project for efficient object storage."
+}
+```
+
# BLOB Storing Minio Provider
BLOB Storing Minio Provider can store BLOBs in [MinIO Object storage](https://min.io/).
@@ -31,6 +38,7 @@ Configure(options =>
minio.AccessKey = "your minio accessKey";
minio.SecretKey = "your minio secretKey";
minio.BucketName = "your minio bucketName";
+ minio.PresignedGetExpirySeconds = 3600;
});
});
});
@@ -53,6 +61,7 @@ Configure(options =>
* Buckets used with Amazon S3 Transfer Acceleration can't have dots (.) in their names. For more information about transfer acceleration, see Amazon S3 Transfer Acceleration.
* **WithSSL** (bool): Default value is `false`,Chain to MinIO Client object to use https instead of http.
* **CreateContainerIfNotExists** (bool): Default value is `false`, If a bucket does not exist in minio, `MinioBlobProvider` will try to create it.
+* **PresignedGetExpirySeconds** (int): Default value is `7 * 24 * 3600`, The expiration time of the pre-specified get url. The is valid within the range of 1 to 604800(corresponding to 7 days).
## Minio Blob Name Calculator
diff --git a/docs/en/framework/infrastructure/cancellation-token-provider.md b/docs/en/framework/infrastructure/cancellation-token-provider.md
index 957e90e7bc..75d42bf032 100644
--- a/docs/en/framework/infrastructure/cancellation-token-provider.md
+++ b/docs/en/framework/infrastructure/cancellation-token-provider.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the `ICancellationTokenProvider` in ABP Framework for efficient cooperative cancellation in your applications."
+}
+```
+
# Cancellation Token Provider
A [`CancellationToken`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken) enables cooperative cancellation between threads, thread pool work items, or `Task` objects. To handle the possible cancellation of the operation, ABP provides `ICancellationTokenProvider` to obtain the `CancellationToken` itself from the source.
diff --git a/docs/en/framework/infrastructure/concurrency-check.md b/docs/en/framework/infrastructure/concurrency-check.md
index 731750f306..356abafcde 100644
--- a/docs/en/framework/infrastructure/concurrency-check.md
+++ b/docs/en/framework/infrastructure/concurrency-check.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn about Concurrency Check in ABP Framework, focusing on Optimistic and Pessimistic approaches for maintaining data consistency."
+}
+```
+
# Concurrency Check
### Introduction
diff --git a/docs/en/framework/infrastructure/csrf-anti-forgery.md b/docs/en/framework/infrastructure/csrf-anti-forgery.md
index df36c4f985..f1ad1feb03 100644
--- a/docs/en/framework/infrastructure/csrf-anti-forgery.md
+++ b/docs/en/framework/infrastructure/csrf-anti-forgery.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how ABP Framework automates CSRF protection effortlessly, ensuring secure web applications with minimal configuration needed."
+}
+```
+
# CSRF/XSRF & Anti Forgery System
"*Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated*" ([OWASP](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet)).
@@ -17,7 +24,7 @@ Once you enable it;
Especially, the second point is a pain for your clients and unnecessarily consumes your server resources.
-> You can read more about the ASP.NET Core antiforgery system in its own [documentation](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery).
+> You can use any ASP.NET Core antiforgery features, like `ValidateAntiForgeryToken`, `AutoValidateAntiforgeryToken`, or `IgnoreAntiforgeryToken`, for more information, see the [official documentation](https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery).
## The Solution
diff --git a/docs/en/framework/infrastructure/current-user.md b/docs/en/framework/infrastructure/current-user.md
index aa1974ab92..a411d1f4d5 100644
--- a/docs/en/framework/infrastructure/current-user.md
+++ b/docs/en/framework/infrastructure/current-user.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to access information about the logged-in user in your ABP Framework app using the ICurrentUser service."
+}
+```
+
# Current User
It is very common to retrieve the information about the logged in user in a web application. The current user is the active user related to the current request in a web application.
diff --git a/docs/en/framework/infrastructure/data-filtering.md b/docs/en/framework/infrastructure/data-filtering.md
index 38844f2079..341c790277 100644
--- a/docs/en/framework/infrastructure/data-filtering.md
+++ b/docs/en/framework/infrastructure/data-filtering.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement data filtering in ABP Framework, including built-in soft delete functionality for managing your entities efficiently."
+}
+```
+
# Data Filtering
[Volo.Abp.Data](https://www.nuget.org/packages/Volo.Abp.Data) package defines services to automatically filter data on querying from a database.
diff --git a/docs/en/framework/infrastructure/data-seeding.md b/docs/en/framework/infrastructure/data-seeding.md
index a2886f4975..0b50e2b726 100644
--- a/docs/en/framework/infrastructure/data-seeding.md
+++ b/docs/en/framework/infrastructure/data-seeding.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively seed initial data in your ABP applications for smooth startup and reliable testing across various databases."
+}
+```
+
# Data Seeding
## Introduction
diff --git a/docs/en/framework/infrastructure/distributed-locking.md b/docs/en/framework/infrastructure/distributed-locking.md
index 9a6488c2fd..76911a8860 100644
--- a/docs/en/framework/infrastructure/distributed-locking.md
+++ b/docs/en/framework/infrastructure/distributed-locking.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement distributed locking in your applications using ABP Framework, ensuring safe access to shared resources without conflicts."
+}
+```
+
# Distributed Locking
Distributed locking is a technique to manage many applications that try to access the same resource. The main purpose is to allow only one of many applications to access the same resource at the same time. Otherwise, accessing the same object from various applications may corrupt the value of the resources.
diff --git a/docs/en/framework/infrastructure/emailing.md b/docs/en/framework/infrastructure/emailing.md
index 21d9fa2e1f..7c240a9d75 100644
--- a/docs/en/framework/infrastructure/emailing.md
+++ b/docs/en/framework/infrastructure/emailing.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently send emails using ABP's IEmailSender service, configure settings, and integrate with background jobs and MailKit."
+}
+```
+
# Email Sending
ABP provides various services, settings and integrations for sending emails;
diff --git a/docs/en/framework/infrastructure/entity-cache.md b/docs/en/framework/infrastructure/entity-cache.md
index cba0cf8eaa..50f1bc1b3c 100644
--- a/docs/en/framework/infrastructure/entity-cache.md
+++ b/docs/en/framework/infrastructure/entity-cache.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently implement entity caching in ABP, enhancing performance by reducing database calls and ensuring data consistency."
+}
+```
+
# Entity Cache
ABP provides an entity caching system that works on top of the [distributed caching](../fundamentals/caching.md) system. It does the following operations on behalf of you:
diff --git a/docs/en/framework/infrastructure/event-bus/distributed/azure.md b/docs/en/framework/infrastructure/event-bus/distributed/azure.md
index c18eaefcb1..8e1bff3e63 100644
--- a/docs/en/framework/infrastructure/event-bus/distributed/azure.md
+++ b/docs/en/framework/infrastructure/event-bus/distributed/azure.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Azure Service Bus as a distributed event bus provider in your ABP Framework project with this comprehensive guide."
+}
+```
+
# Distributed Event Bus Azure Integration
> This document explains **how to configure the [Azure Service Bus](https://azure.microsoft.com/en-us/services/service-bus/)** as the distributed event bus provider. See the [distributed event bus document](../distributed) to learn how to use the distributed event bus system
diff --git a/docs/en/framework/infrastructure/event-bus/distributed/index.md b/docs/en/framework/infrastructure/event-bus/distributed/index.md
index f379a44f40..e5f96bba10 100644
--- a/docs/en/framework/infrastructure/event-bus/distributed/index.md
+++ b/docs/en/framework/infrastructure/event-bus/distributed/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the Distributed Event Bus in ABP Framework for seamless communication between microservices with various provider options."
+}
+```
+
# Distributed Event Bus
Distributed Event bus system allows to **publish** and **subscribe** to events that can be **transferred across application/service boundaries**. You can use the distributed event bus to asynchronously send and receive messages between **microservices** or **applications**.
diff --git a/docs/en/framework/infrastructure/event-bus/distributed/kafka.md b/docs/en/framework/infrastructure/event-bus/distributed/kafka.md
index 0a48612405..1a8ddb4668 100644
--- a/docs/en/framework/infrastructure/event-bus/distributed/kafka.md
+++ b/docs/en/framework/infrastructure/event-bus/distributed/kafka.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Kafka as a distributed event bus provider in your ABP Framework project with step-by-step configuration instructions."
+}
+```
+
# Distributed Event Bus Kafka Integration
> This document explains **how to configure the [Kafka](https://kafka.apache.org/)** as the distributed event bus provider. See the [distributed event bus document](../distributed) to learn how to use the distributed event bus system
diff --git a/docs/en/framework/infrastructure/event-bus/distributed/rabbitmq.md b/docs/en/framework/infrastructure/event-bus/distributed/rabbitmq.md
index 98395c6dff..7b7d64c4c6 100644
--- a/docs/en/framework/infrastructure/event-bus/distributed/rabbitmq.md
+++ b/docs/en/framework/infrastructure/event-bus/distributed/rabbitmq.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure RabbitMQ as a distributed event bus provider in your ABP Framework project with easy installation steps."
+}
+```
+
# Distributed Event Bus RabbitMQ Integration
> This document explains **how to configure the [RabbitMQ](https://www.rabbitmq.com/)** as the distributed event bus provider. See the [distributed event bus document](../distributed) to learn how to use the distributed event bus system
diff --git a/docs/en/framework/infrastructure/event-bus/distributed/rebus.md b/docs/en/framework/infrastructure/event-bus/distributed/rebus.md
index beb23fcad6..ddc07f1ac0 100644
--- a/docs/en/framework/infrastructure/event-bus/distributed/rebus.md
+++ b/docs/en/framework/infrastructure/event-bus/distributed/rebus.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to set up Rebus as your distributed event bus provider with ABP Framework for seamless event handling in your applications."
+}
+```
+
# Distributed Event Bus Rebus Integration
> This document explains **how to configure the [Rebus](http://mookid.dk/category/rebus/)** as the distributed event bus provider. See the [distributed event bus document](../distributed) to learn how to use the distributed event bus system
diff --git a/docs/en/framework/infrastructure/event-bus/index.md b/docs/en/framework/infrastructure/event-bus/index.md
index 1c3f59bc4e..9a309e648b 100644
--- a/docs/en/framework/infrastructure/event-bus/index.md
+++ b/docs/en/framework/infrastructure/event-bus/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn about ABP Framework's Event Bus, its types, and guidance for choosing between local and distributed messaging in your applications."
+}
+```
+
# Event Bus
An event bus is a mediator that transfers a message from a sender to a receiver. In this way, it provides a loosely coupled communication way between objects, services and applications.
diff --git a/docs/en/framework/infrastructure/event-bus/local/index.md b/docs/en/framework/infrastructure/event-bus/local/index.md
index a1f0e9a53e..b20718c51f 100644
--- a/docs/en/framework/infrastructure/event-bus/local/index.md
+++ b/docs/en/framework/infrastructure/event-bus/local/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the Local Event Bus in ABP Framework for efficient in-process event publishing and subscribing between services."
+}
+```
+
# Local Event Bus
The Local Event Bus allows services to publish and subscribe to **in-process events**. That means it is suitable if two services (publisher and subscriber) are running in the same process.
diff --git a/docs/en/framework/infrastructure/features.md b/docs/en/framework/infrastructure/features.md
index a6bc52e48b..2d135b822b 100644
--- a/docs/en/framework/infrastructure/features.md
+++ b/docs/en/framework/infrastructure/features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to enable, disable, and customize application features at runtime with ABP's flexible feature system for multi-tenant applications."
+}
+```
+
# Features
ABP Feature system is used to **enable**, **disable** or **change the behavior** of the application features **on runtime**.
diff --git a/docs/en/framework/infrastructure/global-features.md b/docs/en/framework/infrastructure/global-features.md
index a37070dc7e..c2adb9b302 100644
--- a/docs/en/framework/infrastructure/global-features.md
+++ b/docs/en/framework/infrastructure/global-features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the Global Features system in ABP Framework to enable or disable application features during development for reusable modules."
+}
+```
+
# Global Features
Global Feature system is used to enable/disable an application feature on development time. It is done on the development time, because some **services** (e.g. controllers) are removed from the application model and **database tables** are not created for the disabled features, which is not possible on runtime.
diff --git a/docs/en/framework/infrastructure/guid-generation.md b/docs/en/framework/infrastructure/guid-generation.md
index 6b3177ae22..79314e0570 100644
--- a/docs/en/framework/infrastructure/guid-generation.md
+++ b/docs/en/framework/infrastructure/guid-generation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn about GUID generation in ABP Framework, its advantages, and why it's preferred for primary keys in database management systems."
+}
+```
+
# GUID Generation
GUID is a common **primary key type** that is used in database management systems. ABP prefers GUID as the primary for pre-built [application modules](../../modules). Also, `ICurrentUser.Id` property ([see](./current-user.md)) is type of GUID, that means the ABP assumes that the User Id is always GUID.
diff --git a/docs/en/framework/infrastructure/image-manipulation.md b/docs/en/framework/infrastructure/image-manipulation.md
index a1ee6e1584..49a2e74c46 100644
--- a/docs/en/framework/infrastructure/image-manipulation.md
+++ b/docs/en/framework/infrastructure/image-manipulation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently compress and resize images in your applications using ABP Framework's extensible services powered by ImageSharp and Magick.NET."
+}
+```
+
# Image Manipulation
ABP provides services to compress and resize images and implements these services with popular [ImageSharp](https://sixlabors.com/products/imagesharp/) and [Magick.NET](https://github.com/dlemstra/Magick.NET) libraries. You can use these services in your reusable modules, libraries and applications, so you don't depend on a specific imaging library.
diff --git a/docs/en/framework/infrastructure/index.md b/docs/en/framework/infrastructure/index.md
index e5691612dc..a242c8b4fa 100644
--- a/docs/en/framework/infrastructure/index.md
+++ b/docs/en/framework/infrastructure/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover ABP's comprehensive infrastructure features for building robust .NET applications, including audit logging, background jobs, and more."
+}
+```
+
# ABP Infrastructure
ABP provides a complete infrastructure for creating real world software solutions with modern architectures based on the .NET platform. Each of the following documents explains an infrastructure feature:
diff --git a/docs/en/framework/infrastructure/json.md b/docs/en/framework/infrastructure/json.md
index 6146436818..a8d17528cb 100644
--- a/docs/en/framework/infrastructure/json.md
+++ b/docs/en/framework/infrastructure/json.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use ABP's JSON abstraction for flexible, library-independent serialization with predefined converters for seamless integration."
+}
+```
+
# JSON
The ABP provides an abstraction to work with JSON. Having such an abstraction has some benefits;
diff --git a/docs/en/framework/infrastructure/mail-kit.md b/docs/en/framework/infrastructure/mail-kit.md
index b99bb637c3..f483aaa512 100644
--- a/docs/en/framework/infrastructure/mail-kit.md
+++ b/docs/en/framework/infrastructure/mail-kit.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate MailKit with ABP Framework for efficient email sending and management in your .NET applications."
+}
+```
+
# MailKit Integration
[MailKit](http://www.mimekit.net/) is a cross-platform, popular open source mail client library for .net. ABP provides an integration package to use the MailKit as the [email sender](./emailing.md).
diff --git a/docs/en/framework/infrastructure/object-to-object-mapping.md b/docs/en/framework/infrastructure/object-to-object-mapping.md
index 8c9a0453df..4a54500814 100644
--- a/docs/en/framework/infrastructure/object-to-object-mapping.md
+++ b/docs/en/framework/infrastructure/object-to-object-mapping.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to simplify object-to-object mapping in ABP Framework, reducing repetitive code and enhancing efficiency in your applications."
+}
+```
+
# Object To Object Mapping
It's common to map an object to another similar object. It's also tedious and repetitive since generally both classes have the same or similar properties mapped to each other. Imagine a typical [application service](../architecture/domain-driven-design/application-services.md) method below:
diff --git a/docs/en/framework/infrastructure/settings.md b/docs/en/framework/infrastructure/settings.md
index f3784b1616..b48b1c84dc 100644
--- a/docs/en/framework/infrastructure/settings.md
+++ b/docs/en/framework/infrastructure/settings.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to define and manage application settings in ABP Framework, enhancing configuration and modularity for your projects."
+}
+```
+
# Settings
[Configuration system](../fundamentals/configuration.md) is a good way to configure the application on startup. In addition to the configurations, ABP provides another way to set and get some application settings.
diff --git a/docs/en/framework/infrastructure/simple-state-checker.md b/docs/en/framework/infrastructure/simple-state-checker.md
index 981e4f6a61..6bba8c10ff 100644
--- a/docs/en/framework/infrastructure/simple-state-checker.md
+++ b/docs/en/framework/infrastructure/simple-state-checker.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement a simple state checking system in your applications to dynamically enable or disable objects based on conditions."
+}
+```
+
# Simple State Checker
The simple state checking system can be used to enable/disable an object based on some dynamic conditions. For example, you can disable a menu item on the user interface, if the current user has not granted for a given permission. The simple state checking system provides a generic way to define and check such conditions.
diff --git a/docs/en/framework/infrastructure/sms-sending.md b/docs/en/framework/infrastructure/sms-sending.md
index ef2a86445f..64439be111 100644
--- a/docs/en/framework/infrastructure/sms-sending.md
+++ b/docs/en/framework/infrastructure/sms-sending.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily integrate SMS sending in your ABP applications with flexible options for changing SMS providers and creating reusable modules."
+}
+```
+
# SMS Sending
The ABP provides an abstraction to sending SMS. Having such an abstraction has some benefits;
diff --git a/docs/en/framework/infrastructure/string-encryption.md b/docs/en/framework/infrastructure/string-encryption.md
index bb398425f6..de8f6c75bf 100644
--- a/docs/en/framework/infrastructure/string-encryption.md
+++ b/docs/en/framework/infrastructure/string-encryption.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to securely encrypt and decrypt strings in your ABP applications with easy installation and usage guides."
+}
+```
+
# String Encryption
ABP provides string encryption feature that allows to **Encrypt** and **Decrypt** strings.
diff --git a/docs/en/framework/infrastructure/text-templating/index.md b/docs/en/framework/infrastructure/text-templating/index.md
index 586efa31d0..853014c1cd 100644
--- a/docs/en/framework/infrastructure/text-templating/index.md
+++ b/docs/en/framework/infrastructure/text-templating/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover ABP's powerful text templating system for dynamic content rendering, supporting conditionals, loops, and localization for enhanced applications."
+}
+```
+
# Text Templating
## Introduction
diff --git a/docs/en/framework/infrastructure/text-templating/razor.md b/docs/en/framework/infrastructure/text-templating/razor.md
index 77db5467aa..d2f690c72c 100644
--- a/docs/en/framework/infrastructure/text-templating/razor.md
+++ b/docs/en/framework/infrastructure/text-templating/razor.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Razor templates in your ABP Framework project, including installation via ABP CLI or manual methods."
+}
+```
+
# Razor Integration
diff --git a/docs/en/framework/infrastructure/text-templating/scriban.md b/docs/en/framework/infrastructure/text-templating/scriban.md
index 99d160ce85..bb72624294 100644
--- a/docs/en/framework/infrastructure/text-templating/scriban.md
+++ b/docs/en/framework/infrastructure/text-templating/scriban.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Scriban into your ABP Framework project, including installation steps and defining templates for efficient text templating."
+}
+```
+
# Scriban Integration
## Installation
diff --git a/docs/en/framework/infrastructure/timing.md b/docs/en/framework/infrastructure/timing.md
index 9f104b6336..e95c55ed47 100644
--- a/docs/en/framework/infrastructure/timing.md
+++ b/docs/en/framework/infrastructure/timing.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how ABP simplifies handling time and time zones for global applications with built-in services like IClock for accurate date and time management."
+}
+```
+
# Timing
Working with times & [time zones](https://en.wikipedia.org/wiki/Time_zone) is always tricky, especially if you need to build a **global system** that is used by users in **different time zones**.
diff --git a/docs/en/framework/infrastructure/virtual-file-system.md b/docs/en/framework/infrastructure/virtual-file-system.md
index 03dab585be..682fcd2f10 100644
--- a/docs/en/framework/infrastructure/virtual-file-system.md
+++ b/docs/en/framework/infrastructure/virtual-file-system.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage non-physical files with the ABP Virtual File System, allowing you to embed assets directly into your assemblies."
+}
+```
+
# Virtual File System
The Virtual File System makes it possible to manage files that do not physically exist on the file system (disk). It's mainly used to embed (js, css, image..) files into assemblies and use them like physical files at runtime.
diff --git a/docs/en/framework/real-time/signalr.md b/docs/en/framework/real-time/signalr.md
index d0ff3ea318..be4160a819 100644
--- a/docs/en/framework/real-time/signalr.md
+++ b/docs/en/framework/real-time/signalr.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily integrate SignalR into your ABP Framework application using the ABP CLI for seamless real-time communication."
+}
+```
+
# SignalR Integration
> It is already possible to follow [the standard Microsoft tutorial](https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr) to add [SignalR](https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction) to your application. However, ABP provides SignalR integration packages those simplify the integration and usage.
diff --git a/docs/en/framework/ui/angular/abp-window-service.md b/docs/en/framework/ui/angular/abp-window-service.md
index bd55c4d2d1..1743bee2f3 100644
--- a/docs/en/framework/ui/angular/abp-window-service.md
+++ b/docs/en/framework/ui/angular/abp-window-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use AbpWindowService in Angular to efficiently download blobs as files with easy-to-follow steps and code examples."
+}
+```
+
# Abp Window Service
diff --git a/docs/en/framework/ui/angular/account-module.md b/docs/en/framework/ui/angular/account-module.md
index 05b670d4d2..2f4df8cd42 100644
--- a/docs/en/framework/ui/angular/account-module.md
+++ b/docs/en/framework/ui/angular/account-module.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate the Angular UI Account Module into your project for seamless user authentication with login, registration, and account management features."
+}
+```
+
# Angular UI Account Module
Angular UI account module is available as of v4.3. It contains some pages (login, register, My account, etc.).
diff --git a/docs/en/framework/ui/angular/authorization.md b/docs/en/framework/ui/angular/authorization.md
index cef5dca7c4..365333224a 100644
--- a/docs/en/framework/ui/angular/authorization.md
+++ b/docs/en/framework/ui/angular/authorization.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement OAuth in your Angular apps with ABP Framework, ensuring secure authorization right from project setup."
+}
+```
+
# Authorization in Angular UI
OAuth is preconfigured in Angular application templates. So, when you start a project using the CLI (or Suite, for that matter), authorization already works. ABP Angular UI packages are using [angular-oauth2-oidc library](https://github.com/manfredsteyer/angular-oauth2-oidc#logging-in) for managing OAuth in the Angular client.
diff --git a/docs/en/framework/ui/angular/basic-theme.md b/docs/en/framework/ui/angular/basic-theme.md
index 2332091cf0..bb23330241 100644
--- a/docs/en/framework/ui/angular/basic-theme.md
+++ b/docs/en/framework/ui/angular/basic-theme.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the Basic Theme for Angular UI—minimalist styling on Bootstrap, perfect for creating custom themes for your projects."
+}
+```
+
# Angular UI: Basic Theme
The Basic Theme is a theme implementation for the Angular UI. It is a minimalist theme that doesn't add any styling on top of the plain [Bootstrap](https://getbootstrap.com/). You can take the Basic Theme as the **base theme** and build your own theme or styling on top of it. See the *Customization* section.
diff --git a/docs/en/framework/ui/angular/breadcrumb.md b/docs/en/framework/ui/angular/breadcrumb.md
index 1a26975c96..a245c1f415 100644
--- a/docs/en/framework/ui/angular/breadcrumb.md
+++ b/docs/en/framework/ui/angular/breadcrumb.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and customize breadcrumb navigation in your ABP applications with the Breadcrumb Component for enhanced user experience."
+}
+```
+
# Breadcrumb Component
ABP provides a component that listens to the angular router's `NavigationEnd`
diff --git a/docs/en/framework/ui/angular/caps-lock-directive.md b/docs/en/framework/ui/angular/caps-lock-directive.md
index 179027022d..5b6c641fa7 100644
--- a/docs/en/framework/ui/angular/caps-lock-directive.md
+++ b/docs/en/framework/ui/angular/caps-lock-directive.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement the `TrackCapsLockDirective` for password inputs in Angular, enhancing user experience with Caps Lock warnings."
+}
+```
+
# Caps Lock Directive
In password inputs, You may want to show if Caps Lock is on. To make this even easier, you can use the `TrackCapsLockDirective` which has been exposed by the `@abp/ng.core` package.
diff --git a/docs/en/framework/ui/angular/card-component.md b/docs/en/framework/ui/angular/card-component.md
index e8f1ba4d8e..a2872659e9 100644
--- a/docs/en/framework/ui/angular/card-component.md
+++ b/docs/en/framework/ui/angular/card-component.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the ABP Card Component with Bootstrap, featuring customizable CardHeader, CardBody, and CardFooter components."
+}
+```
+
# Card Component
The ABP Card Component is a wrapper component for the Bootstrap card class.
diff --git a/docs/en/framework/ui/angular/chart-component.md b/docs/en/framework/ui/angular/chart-component.md
index 44007eef5b..63eb723e98 100644
--- a/docs/en/framework/ui/angular/chart-component.md
+++ b/docs/en/framework/ui/angular/chart-component.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to effortlessly integrate the ABP Chart component into your Angular app using lazy loading for optimal performance."
+}
+```
+
# Chart Component
ABP Chart component exposed by `@abp/ng.components/chart.js` is based on [`charts.js`](https://www.chartjs.org/) v3+. You don't need to install the `chart.js` package. Since the `@abp/ng.components` is dependent on the `chart.js`, the package is already installed in your project.
diff --git a/docs/en/framework/ui/angular/checkbox-component.md b/docs/en/framework/ui/angular/checkbox-component.md
index 898f86732c..2e5cc44ad3 100644
--- a/docs/en/framework/ui/angular/checkbox-component.md
+++ b/docs/en/framework/ui/angular/checkbox-component.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement the ABP Checkbox Component for reusable form input, enhancing your applications with ease and efficiency."
+}
+```
+
# Checkbox Component
The ABP Checkbox Component is a reusable form input component for the checkbox type.
diff --git a/docs/en/framework/ui/angular/component-replacement.md b/docs/en/framework/ui/angular/component-replacement.md
index e1a3af734f..6feebfc409 100644
--- a/docs/en/framework/ui/angular/component-replacement.md
+++ b/docs/en/framework/ui/angular/component-replacement.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to replace ABP components with your custom ones for enhanced flexibility while maintaining system integrity."
+}
+```
+
# Component Replacement
You can replace some ABP components with your custom components.
diff --git a/docs/en/framework/ui/angular/config-state-service.md b/docs/en/framework/ui/angular/config-state-service.md
index 72200ed696..58fe0cf159 100644
--- a/docs/en/framework/ui/angular/config-state-service.md
+++ b/docs/en/framework/ui/angular/config-state-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently use the ConfigStateService in your ABP application to manage and access configuration settings seamlessly."
+}
+```
+
# Config State Service
`ConfigStateService` is a singleton service, i.e. provided in root level of your application, and keeps the application configuration response in the internal store.
diff --git a/docs/en/framework/ui/angular/confirmation-service.md b/docs/en/framework/ui/angular/confirmation-service.md
index 96d05387bd..758a103388 100644
--- a/docs/en/framework/ui/angular/confirmation-service.md
+++ b/docs/en/framework/ui/angular/confirmation-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily implement confirmation popups in your Angular project using the `ConfirmationService` from ABP Framework."
+}
+```
+
# Confirmation Popup
You can use the `ConfirmationService` in @abp/ng.theme.shared package to display a confirmation popup by placing at the root level in your project.
diff --git a/docs/en/framework/ui/angular/container-strategy.md b/docs/en/framework/ui/angular/container-strategy.md
index 715644826a..a5cf5c12b6 100644
--- a/docs/en/framework/ui/angular/container-strategy.md
+++ b/docs/en/framework/ui/angular/container-strategy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn about the `ContainerStrategy` class in ABP Framework, including `ClearContainerStrategy` and `InsertIntoContainerStrategy` for effective content projection."
+}
+```
+
# ContainerStrategy
`ContainerStrategy` is an abstract class exposed by @abp/ng.core package. There are two container strategies extending it: `ClearContainerStrategy` and `InsertIntoContainerStrategy`. Implementing the same methods and properties, both of these strategies help you define how your containers will be prepared and where your content will be projected.
diff --git a/docs/en/framework/ui/angular/content-projection-service.md b/docs/en/framework/ui/angular/content-projection-service.md
index ca6c9d2144..42ca02c913 100644
--- a/docs/en/framework/ui/angular/content-projection-service.md
+++ b/docs/en/framework/ui/angular/content-projection-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to use the ContentProjectionService in @abp/ng.core for easy and dynamic content projection in Angular components."
+}
+```
+
# Projecting Angular Content
You can use the `ContentProjectionService` in @abp/ng.core package in order to project content in an easy and explicit way.
diff --git a/docs/en/framework/ui/angular/content-security-strategy.md b/docs/en/framework/ui/angular/content-security-strategy.md
index 11b164365a..048a66cd30 100644
--- a/docs/en/framework/ui/angular/content-security-strategy.md
+++ b/docs/en/framework/ui/angular/content-security-strategy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to safely implement Content Security Policy with the `ContentSecurityStrategy` class in ABP Framework for enhanced web security."
+}
+```
+
# ContentSecurityStrategy
`ContentSecurityStrategy` is an abstract class exposed by @abp/ng.core package. It helps you mark inline scripts or styles as safe in terms of [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy).
diff --git a/docs/en/framework/ui/angular/content-strategy.md b/docs/en/framework/ui/angular/content-strategy.md
index 93f6a2ea44..cacf7860d1 100644
--- a/docs/en/framework/ui/angular/content-strategy.md
+++ b/docs/en/framework/ui/angular/content-strategy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the `ContentStrategy` abstract class to create inline scripts and styles in your ABP applications efficiently."
+}
+```
+
# ContentStrategy
`ContentStrategy` is an abstract class exposed by @abp/ng.core package. It helps you create inline scripts or styles.
diff --git a/docs/en/framework/ui/angular/context-strategy.md b/docs/en/framework/ui/angular/context-strategy.md
index 4bcd08b257..6a01ab3775 100644
--- a/docs/en/framework/ui/angular/context-strategy.md
+++ b/docs/en/framework/ui/angular/context-strategy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the `ContextStrategy` class in ABP, detailing context management for projected components with various strategies for developers."
+}
+```
+
# ContextStrategy
`ContextStrategy` is an abstract class exposed by @abp/ng.core package. There are three context strategies extending it: `ComponentContextStrategy`, `TemplateContextStrategy`, and `NoContextStrategy`. Implementing the same methods and properties, all of these strategies help you define how projected content will get their context.
diff --git a/docs/en/framework/ui/angular/cross-origin-strategy.md b/docs/en/framework/ui/angular/cross-origin-strategy.md
index 5edcbed9e6..7ecde7c09e 100644
--- a/docs/en/framework/ui/angular/cross-origin-strategy.md
+++ b/docs/en/framework/ui/angular/cross-origin-strategy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `CrossOriginStrategy` class in the @abp/ng.core package to manage resource retrieval in your applications effectively."
+}
+```
+
# CrossOriginStrategy
`CrossOriginStrategy` is a class exposed by @abp/ng.core package. Its instances define how a source referenced by an element will be retrieved by the browser and are consumed by other classes such as `LoadingStrategy`.
diff --git a/docs/en/framework/ui/angular/current-user.md b/docs/en/framework/ui/angular/current-user.md
index 8d90b0cfda..dc35a2bd9e 100644
--- a/docs/en/framework/ui/angular/current-user.md
+++ b/docs/en/framework/ui/angular/current-user.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to retrieve current user information in Angular using ConfigStateService methods for efficient state management."
+}
+```
+
# Angular UI: Current User
The current user information stored in Config State.
diff --git a/docs/en/framework/ui/angular/data-table-column-extensions.md b/docs/en/framework/ui/angular/data-table-column-extensions.md
index 781ad51ae4..30b9facf0d 100644
--- a/docs/en/framework/ui/angular/data-table-column-extensions.md
+++ b/docs/en/framework/ui/angular/data-table-column-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your Angular UI data tables by adding or modifying columns with the Entity Prop Extension system in ABP Framework."
+}
+```
+
# Data Table Column (or Entity Prop) Extensions for Angular UI
## Introduction
diff --git a/docs/en/framework/ui/angular/datetime-format-pipe.md b/docs/en/framework/ui/angular/datetime-format-pipe.md
index 88eb9fb604..e0e5493851 100644
--- a/docs/en/framework/ui/angular/datetime-format-pipe.md
+++ b/docs/en/framework/ui/angular/datetime-format-pipe.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily format dates in Angular using DateTime format pipes for shortDate, shortTime, and shortDateTime with culture settings."
+}
+```
+
{%{
# DateTime Format Pipes
diff --git a/docs/en/framework/ui/angular/dom-insertion-service.md b/docs/en/framework/ui/angular/dom-insertion-service.md
index 0e084d7a4a..150d9169cc 100644
--- a/docs/en/framework/ui/angular/dom-insertion-service.md
+++ b/docs/en/framework/ui/angular/dom-insertion-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily insert scripts and styles into the DOM using the `DomInsertionService` from @abp/ng.core, enhancing your Angular applications seamlessly."
+}
+```
+
# Inserting Scripts & Styles to DOM
You can use the `DomInsertionService` in @abp/ng.core package in order to insert scripts and styles in an easy and explicit way.
diff --git a/docs/en/framework/ui/angular/dom-strategy.md b/docs/en/framework/ui/angular/dom-strategy.md
index 6f1ea9ed90..a53fb80a86 100644
--- a/docs/en/framework/ui/angular/dom-strategy.md
+++ b/docs/en/framework/ui/angular/dom-strategy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the `DomStrategy` class in the @abp/ng.core package, which defines how elements attach to the DOM, enhancing your development workflow."
+}
+```
+
# DomStrategy
`DomStrategy` is a class exposed by @abp/ng.core package. Its instances define how an element will be attached to the DOM and are consumed by other classes such as `LoadingStrategy`.
diff --git a/docs/en/framework/ui/angular/dynamic-form-extensions.md b/docs/en/framework/ui/angular/dynamic-form-extensions.md
index 72c762fd4a..ee7af81397 100644
--- a/docs/en/framework/ui/angular/dynamic-form-extensions.md
+++ b/docs/en/framework/ui/angular/dynamic-form-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance Angular UI forms with dynamic field extensions, enabling customization and validation for improved user management."
+}
+```
+
# Dynamic Form (or Form Prop) Extensions for Angular UI
diff --git a/docs/en/framework/ui/angular/ellipsis-directive.md b/docs/en/framework/ui/angular/ellipsis-directive.md
index df6db94ec5..fdf3fe7092 100644
--- a/docs/en/framework/ui/angular/ellipsis-directive.md
+++ b/docs/en/framework/ui/angular/ellipsis-directive.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily truncate text with ellipsis using the `EllipsisDirective` in ABP Framework, enhancing your Angular templates effortlessly."
+}
+```
+
# Ellipsis
Text inside an HTML element can be truncated easily with an ellipsis by using CSS. To make this even easier, you can use the `EllipsisDirective` which has been exposed by the `@abp/ng.theme.shared` package.
diff --git a/docs/en/framework/ui/angular/entity-action-extensions.md b/docs/en/framework/ui/angular/entity-action-extensions.md
index 26913229bf..152ff6636d 100644
--- a/docs/en/framework/ui/angular/entity-action-extensions.md
+++ b/docs/en/framework/ui/angular/entity-action-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your Angular UI with custom entity actions, enabling dynamic functionality like modals and API calls in ABP Framework."
+}
+```
+
# Entity Action Extensions for Angular UI
## Introduction
diff --git a/docs/en/framework/ui/angular/entity-filters.md b/docs/en/framework/ui/angular/entity-filters.md
index 45929c1ef9..04abf3ca39 100644
--- a/docs/en/framework/ui/angular/entity-filters.md
+++ b/docs/en/framework/ui/angular/entity-filters.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement advanced entity filters in your ABP Framework CRUD pages using the `abp-advanced-entity-filters` component."
+}
+```
+
# Entity Filters
Every CRUD page includes some sort of inputs to filter the listed data. Some of the inputs are common among all of the entities like the `Search` box. In addition, every entity has its own advanced filters depending on its fields. To reduce the amount of code written on every CRUD page, the Angular UI of ABP Commercial introduces a new type of component called `abp-advanced-entity-filters`
diff --git a/docs/en/framework/ui/angular/environment.md b/docs/en/framework/ui/angular/environment.md
index e32fc98aae..4395141c13 100644
--- a/docs/en/framework/ui/angular/environment.md
+++ b/docs/en/framework/ui/angular/environment.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure environment variables in ABP Framework applications, including API settings and production configurations."
+}
+```
+
# Environment
Every application needs some **environment** variables. In Angular world, this is usually managed by `environment.ts`, `environment.prod.ts` and so on. It is the same for ABP as well.
diff --git a/docs/en/framework/ui/angular/extensions-overall.md b/docs/en/framework/ui/angular/extensions-overall.md
index 7fbf81126d..287d62b38e 100644
--- a/docs/en/framework/ui/angular/extensions-overall.md
+++ b/docs/en/framework/ui/angular/extensions-overall.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to enhance your Angular UI with extensions for actions, data tables, toolbars, and forms in the ABP Framework."
+}
+```
+
# Angular UI Extensions
Angular UI extensions system allows you to add a new action to the actions menu, a new column to the data table, a new action to the toolbar of a page, and add a new field to the create and/or edit forms.
diff --git a/docs/en/framework/ui/angular/feature-libraries.md b/docs/en/framework/ui/angular/feature-libraries.md
index 07a72e0297..48ef6de504 100644
--- a/docs/en/framework/ui/angular/feature-libraries.md
+++ b/docs/en/framework/ui/angular/feature-libraries.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and configure feature libraries in ABP Framework to enhance your Angular applications with modular functionality."
+}
+```
+
# About Feature Libraries
ABP has an ever-growing number of feature modules and [introducing a new one](../../architecture/modularity/basics.md) is always possible. When the UI is Angular, these features have modular Angular libraries accompanying them.
diff --git a/docs/en/framework/ui/angular/features.md b/docs/en/framework/ui/angular/features.md
index 7e71632b1e..eece10bfb2 100644
--- a/docs/en/framework/ui/angular/features.md
+++ b/docs/en/framework/ui/angular/features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to access feature values in Angular using ConfigStateService for seamless integration with ABP Framework."
+}
+```
+
# Features
You can get the value of a feature on the client-side using the [config state service](./config-state.md) if it is allowed by the feature definition on the server-side.
diff --git a/docs/en/framework/ui/angular/form-input-component.md b/docs/en/framework/ui/angular/form-input-component.md
index f1dedd824a..aaf3b6f5be 100644
--- a/docs/en/framework/ui/angular/form-input-component.md
+++ b/docs/en/framework/ui/angular/form-input-component.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Form Input Component documentation to learn how to easily implement reusable text input fields in your applications."
+}
+```
+
# Form Input Component
The ABP FormInput Component is a reusable form input component for the text type.
diff --git a/docs/en/framework/ui/angular/form-validation.md b/docs/en/framework/ui/angular/form-validation.md
index 09012252f0..35a54549af 100644
--- a/docs/en/framework/ui/angular/form-validation.md
+++ b/docs/en/framework/ui/angular/form-validation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily implement form validation in ABP Angular UI using ngx-validate, with automatic error message handling for a seamless user experience."
+}
+```
+
# Form Validation
Reactive forms in ABP Angular UI are validated by [ngx-validate](https://www.npmjs.com/package/@ngx-validate/core) and helper texts are shown automatically based on validation rules and error blueprints. You do not have to add any elements or components to your templates. The library handles that for you. Here is how the experience is:
diff --git a/docs/en/framework/ui/angular/global-features.md b/docs/en/framework/ui/angular/global-features.md
index 5214ea2906..cc4bfc8d91 100644
--- a/docs/en/framework/ui/angular/global-features.md
+++ b/docs/en/framework/ui/angular/global-features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the ConfigStateService.getGlobalFeatures API in Angular to access enabled global features for your ABP Framework applications."
+}
+```
+
# Angular: Global Features API
The `ConfigStateService.getGlobalFeatures` API allows you to get the enabled features of the [Global Features](../../infrastructure/global-features.md) on the client side.
diff --git a/docs/en/framework/ui/angular/how-replaceable-components-work-with-extensions.md b/docs/en/framework/ui/angular/how-replaceable-components-work-with-extensions.md
index 3e6d9ab328..5d70510e51 100644
--- a/docs/en/framework/ui/angular/how-replaceable-components-work-with-extensions.md
+++ b/docs/en/framework/ui/angular/how-replaceable-components-work-with-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize replaceable components with extensions in ABP Framework to customize entity actions, table columns, and page toolbars effectively."
+}
+```
+
# How Replaceable Components Work with Extensions
Additional UI extensibility points ([Entity action extensions](../angular/entity-action-extensions.md), [data table column extensions](../angular/data-table-column-extensions.md), [page toolbar extensions](../angular/page-toolbar-extensions.md) and others) are used in ABP pages to allow to control entity actions, table columns and page toolbar of a page. If you replace a page, you need to apply some configurations to be able to work extension components in your component. Let's see how to do this by replacing the roles page.
diff --git a/docs/en/framework/ui/angular/http-error-handling.md b/docs/en/framework/ui/angular/http-error-handling.md
index 73aade0960..33c4b0cec2 100644
--- a/docs/en/framework/ui/angular/http-error-handling.md
+++ b/docs/en/framework/ui/angular/http-error-handling.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure HTTP error handling in ABP Framework, including custom error screens and handling specific error codes."
+}
+```
+
# HTTP Error Handling
## Error Configurations
diff --git a/docs/en/framework/ui/angular/http-error-reporter-service.md b/docs/en/framework/ui/angular/http-error-reporter-service.md
index e7f9a6f5a8..24844dd46c 100644
--- a/docs/en/framework/ui/angular/http-error-reporter-service.md
+++ b/docs/en/framework/ui/angular/http-error-reporter-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently report HTTP errors in your Angular app using the `HttpErrorReporterService` from the ABP Framework."
+}
+```
+
# HTTP Error Reporter Service
`HttpErrorReporterService` is a service which is exposed by `@abp/ng.core` package. HTTP errors can be reported by using this service. The service emits an event when an error is reported and keeps the errors as an array. The [`RestService`](./http-requests#restservice) uses the `HttpErrorReporterService` for reporting errors.
diff --git a/docs/en/framework/ui/angular/http-requests.md b/docs/en/framework/ui/angular/http-requests.md
index 928a4f600b..5cb217540d 100644
--- a/docs/en/framework/ui/angular/http-requests.md
+++ b/docs/en/framework/ui/angular/http-requests.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to make efficient HTTP requests in Angular using HttpClient and simplify error handling with HttpInterceptor in your ABP project."
+}
+```
+
# How to Make HTTP Requests
## About HttpClient
diff --git a/docs/en/framework/ui/angular/internet-connection-service.md b/docs/en/framework/ui/angular/internet-connection-service.md
index 6fe5ed7402..945234f8bd 100644
--- a/docs/en/framework/ui/angular/internet-connection-service.md
+++ b/docs/en/framework/ui/angular/internet-connection-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `InternetConnectionService` to easily check and respond to internet connectivity status in your ABP applications."
+}
+```
+
# Internet Connection Service
`InternetConnectionService` is a service which is exposed by the `@abp/ng.core` package. **You can use this service in order to check your internet connection**
diff --git a/docs/en/framework/ui/angular/lazy-load-service.md b/docs/en/framework/ui/angular/lazy-load-service.md
index 339f0f656b..e0942a15f0 100644
--- a/docs/en/framework/ui/angular/lazy-load-service.md
+++ b/docs/en/framework/ui/angular/lazy-load-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Easily lazy load scripts and styles in your Angular app with ABP's `LazyLoadService`, streamlining resource management and improving performance."
+}
+```
+
# Lazy Loading Scripts & Styles
You can use the `LazyLoadService` in @abp/ng.core package in order to lazy load scripts and styles in an easy and explicit way.
diff --git a/docs/en/framework/ui/angular/list-service.md b/docs/en/framework/ui/angular/list-service.md
index c6b0a2a35c..f8b0a42249 100644
--- a/docs/en/framework/ui/angular/list-service.md
+++ b/docs/en/framework/ui/angular/list-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement pagination, sorting, and search with the ListService in ABP Framework for enhanced data management."
+}
+```
+
# Working with Lists
`ListService` is a utility service to provide easy pagination, sorting, and search implementation.
diff --git a/docs/en/framework/ui/angular/loading-directive.md b/docs/en/framework/ui/angular/loading-directive.md
index 1f6f7cd4e9..be871a4bb8 100644
--- a/docs/en/framework/ui/angular/loading-directive.md
+++ b/docs/en/framework/ui/angular/loading-directive.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement the `LoadingDirective` in your ABP Framework app to enhance user experience with loading spinners in your UI."
+}
+```
+
# Loading Directive
diff --git a/docs/en/framework/ui/angular/loading-strategy.md b/docs/en/framework/ui/angular/loading-strategy.md
index 5abff9a512..8b45aa53fe 100644
--- a/docs/en/framework/ui/angular/loading-strategy.md
+++ b/docs/en/framework/ui/angular/loading-strategy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement loading strategies for lazy loading in your ABP applications with the `LoadingStrategy` class and its extensions."
+}
+```
+
# LoadingStrategy
`LoadingStrategy` is an abstract class exposed by @abp/ng.core package. There are two loading strategies extending it: `ScriptLoadingStrategy` and `StyleLoadingStrategy`. Implementing the same methods and properties, both of these strategies help you define how your lazy loading will work.
diff --git a/docs/en/framework/ui/angular/localization.md b/docs/en/framework/ui/angular/localization.md
index 5d14eb0333..034e77abf0 100644
--- a/docs/en/framework/ui/angular/localization.md
+++ b/docs/en/framework/ui/angular/localization.md
@@ -1,13 +1,20 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively implement localization in your ABP Framework project using the Localization Pipe and Service for seamless multilingual support."
+}
+```
+
# Localization
-Before you read about _the Localization Pipe_ and _the Localization Service_, you should know about localization keys.
+Before exploring _the localization pipe_ and _the localization service_, you should go over the localization keys.
-The Localization key format consists of 2 sections which are **Resource Name** and **Key**.
+The localization key format consists of two sections which are **Resource Name** and **Key**.
`ResourceName::Key`
-> If you do not specify the resource name, it will be `defaultResourceName` which is declared in `environment.ts`
+> If you do not specify the resource name, the `defaultResourceName` which is declared in `environment.ts` will be considered as default.
-```js
+```ts
const environment = {
// ...
localization: {
@@ -16,7 +23,7 @@ const environment = {
};
```
-So these two are the same:
+So, these two will give the same results:
```html
{%{{{ '::Key' | abpLocalization }}}%}
@@ -32,7 +39,7 @@ You can use the `abpLocalization` pipe to get localized text as in this example:
{%{{{ 'Resource::Key' | abpLocalization }}}%}
```
-The pipe will replace the key with the localized text.
+This pipe will replace the key with the localized text.
You can also specify a default value as shown below:
@@ -43,11 +50,11 @@ You can also specify a default value as shown below:
```
-To use interpolation, you must give the values for interpolation as pipe parameters, for example:
+In order to use the interpolation, you must give the parameters for the pipe, as an example:
Localization data is stored in key-value pairs:
-```js
+```ts
{
// ...
AbpAccount: { // AbpAccount is the resource name
@@ -57,7 +64,7 @@ Localization data is stored in key-value pairs:
}
```
-So we can use this key like this:
+Then, we can use this key like this:
```html
@@ -67,7 +74,7 @@ So we can use this key like this:
### Using the Localization Service
-First of all you should import the `LocalizationService` from **@abp/ng.core**
+First of all, you should import the `LocalizationService` from **@abp/ng.core**
```js
import { LocalizationService } from '@abp/ng.core';
@@ -78,11 +85,11 @@ class MyClass {
}
```
-After that, you are able to use localization service.
+After that, you will be able to use the localization service.
> You can add interpolation parameters as arguments to `instant()` and `get()` methods.
-```js
+```ts
this.localizationService.instant(
"AbpIdentity::UserDeletionConfirmation",
"John"
@@ -103,7 +110,7 @@ this.localizationService.instant(
To get a localized text as [_Observable_](https://rxjs.dev/guide/observable) use `get` method instead of `instant`:
-```js
+```ts
this.localizationService.get("Resource::Key");
// with fallback value
@@ -115,12 +122,12 @@ this.localizationService.get({
## UI Localizations
-Localizations can be determined on backend side. Angular UI gets the localization resources from the `application-localization` API's response and merges these resources with `configuration state` in [`ConfigStateService`](config-state-service.md). You can also determine localizations on the UI side.
+Localizations can be determined on the backend side. Therefore, Angular UI gets the localization resources from the `application-localization` API's response then merges these resources with `configuration state` in [`ConfigStateService`](config-state-service.md). You can also determine localizations on the UI side.
See an example:
```ts
-import { provideAbpCore, withOptions } from '@abp/ng.core';
+import { provideAbpCore, withOptions } from "@abp/ng.core";
export const appConfig: ApplicationConfig = {
providers: [
@@ -130,70 +137,70 @@ export const appConfig: ApplicationConfig = {
// ...,
localizations: [
{
- culture: 'en',
+ culture: "en",
resources: [
{
- resourceName: 'MyProjectName',
+ resourceName: "MyProjectName",
texts: {
- Administration: 'Administration',
- HomePage: 'Home',
+ Administration: "Administration",
+ HomePage: "Home",
},
},
],
},
{
- culture: 'de',
+ culture: "de",
resources: [
{
- resourceName: 'MyProjectName',
+ resourceName: "MyProjectName",
texts: {
- Administration: 'Verwaltung',
- HomePage: 'Startseite',
+ Administration: "Verwaltung",
+ HomePage: "Startseite",
},
},
],
},
],
- }),
+ })
),
],
};
```
-...or, you can determine the localizations in a feature provider configuration:
+You can also declare the localizations in a feature provider configuration:
```ts
// your feature configuration
-export function provideFeatureConfiguration(): EnvironmentProviders{
+export function provideFeatureConfiguration(): EnvironmentProviders {
return provideAbpCoreChild({
localizations: [
- {
- culture: 'en',
- resources: [
- {
- resourceName: 'MyProjectName',
- texts: {
- Administration: 'Administration',
- HomePage: 'Home',
- },
+ {
+ culture: "en",
+ resources: [
+ {
+ resourceName: "MyProjectName",
+ texts: {
+ Administration: "Administration",
+ HomePage: "Home",
},
- ],
- },
- {
- culture: 'de-DE',
- resources: [
- {
- resourceName: 'MyProjectName',
- texts: {
- Administration: 'Verwaltung',
- HomePage: 'Startseite',
- },
+ },
+ ],
+ },
+ {
+ culture: "de-DE",
+ resources: [
+ {
+ resourceName: "MyProjectName",
+ texts: {
+ Administration: "Verwaltung",
+ HomePage: "Startseite",
},
- ],
- },
- ],
- })
+ },
+ ],
+ },
+ ],
+ });
}
```
@@ -209,7 +216,7 @@ The localizations above can be used like this:
## RTL Support
-As of v2.9 ABP has RTL support. If you are generating a new project with v2.9 and above, everything is set, you do not need to do any changes. If you are migrating your project from an earlier version, please follow the 2 steps below:
+As of v2.9 ABP supports RTL. If you are generating a new project with v2.9 and above, everything is set, there is no need to make any changes. If you are migrating your project from an earlier version, please follow the 2 steps below:
### Step 1. Create Chunks for Bootstrap LTR and RTL
@@ -257,7 +264,7 @@ Find [styles configuration in angular.json](https://angular.io/guide/workspace-c
If you have created and injected chunks for Fontawesome as seen above, you no longer need the lazy loading in the `AppComponent` which was implemented before v2.9. Simply remove them. The `AppComponent` in the template of the new version looks like this:
-```js
+```ts
import { Component } from "@angular/core";
@Component({
@@ -272,15 +279,24 @@ export class AppComponent {}
## Registering a New Locale
-Since ABP has more than one language, Angular locale files loads lazily using [Webpack's import function](https://webpack.js.org/api/module-methods/#import-1) to avoid increasing the bundle size and register to Angular core using the [`registerLocaleData`](https://angular.io/api/common/registerLocaleData) function. The chunks to be included in the bundle are specified by the [Webpack's magic comments](https://webpack.js.org/api/module-methods/#magic-comments) as hard-coded. Therefore a `registerLocale` function that returns Webpack `import` function must be passed to `provideAbpCore(withOptions({...}))`.
+Since ABP has more than one language, Angular locale files load lazily using [Webpack's import function](https://webpack.js.org/api/module-methods/#import-1) to avoid increasing the bundle size and to register the Angular core using the [`registerLocaleData`](https://angular.io/api/common/registerLocaleData) function. The chunks to be included in the bundle are specified by the [Webpack's magic comments](https://webpack.js.org/api/module-methods/#magic-comments) as hard-coded. Therefore a `registerLocale` function that returns Webpack `import` function must be passed to `provideAbpCore(withOptions({...}))`.
### registerLocaleFn
-`registerLocale` function that exported from `@abp/ng.core/locale` package is a higher order function that accepts `cultureNameLocaleFileMap` object and `errorHandlerFn` function as params and returns Webpack `import` function. A `registerLocale` function must be passed to the `withOptions` of the `provideAbpCore` as shown below:
+The `registerLocale` function, exported from the `@abp/ng.core/locale` package, is a **higher-order function**.
+
+It accepts the following parameters:
+
+- **`cultureNameLocaleFileMap`** – an object that maps culture names to their corresponding locale files.
+- **`errorHandlerFn`** – a function that handles any errors that occur during locale loading.
+
+It returns a **Webpack `import` function**.
+
+You should use `registerLocale` within the `withOptions` function of `provideAbpCore`, as shown in the example below:
```ts
-import { provideAbpCore, withOptions } from '@abp/ng.core';
-import { registerLocale } from '@abp/ng.core/locale';
+import { provideAbpCore, withOptions } from "@abp/ng.core";
+import { registerLocale } from "@abp/ng.core/locale";
export const appConfig: ApplicationConfig = {
providers: [
@@ -291,13 +307,13 @@ export const appConfig: ApplicationConfig = {
registerLocaleFn: registerLocale(
// you can pass the cultureNameLocaleFileMap and errorHandlerFn as optionally
{
- cultureNameLocaleFileMap: { 'pt-BR': 'pt' },
+ cultureNameLocaleFileMap: { "pt-BR": "pt" },
errorHandlerFn: ({ resolve, reject, locale, error }) => {
// the error can be handled here
},
- },
+ }
),
- }),
+ })
),
// ...
],
@@ -312,10 +328,10 @@ Some of the culture names defined in .NET do not match Angular locales. In such
If you see an error like this, you should pass the `cultureNameLocaleFileMap` property like below to the `registerLocale` function.
-```js
+```ts
// app.config.ts
-import { registerLocale } from '@abp/ng.core/locale';
+import { registerLocale } from "@abp/ng.core/locale";
// if you have commercial license and the language management module, add the below import
// import { registerLocale } from '@volo/abp.ng.language-management/locale';
@@ -325,15 +341,13 @@ export const appConfig: ApplicationConfig = {
provideAbpCore(
withOptions({
// ...,
- registerLocaleFn: registerLocale(
- {
- cultureNameLocaleFileMap: {
- "DotnetCultureName": "AngularLocaleFileName",
- "pt-BR": "pt" // example
- },
+ registerLocaleFn: registerLocale({
+ cultureNameLocaleFileMap: {
+ DotnetCultureName: "AngularLocaleFileName",
+ "pt-BR": "pt", // example
},
- )
- }),
+ }),
+ })
),
],
};
@@ -343,9 +357,9 @@ See [all locale files in Angular](https://github.com/angular/angular/tree/master
### Adding a New Culture
-Add the below code to the `app.config.ts` by replacing `your-locale` placeholder with a correct locale name.
+If you want to register a new language, you can add the code below to the `app.config.ts` by replacing `your-locale` placeholder with a correct locale name.
-```js
+```ts
//app.config.ts
import { storeLocaleData } from "@abp/ng.core/locale";
@@ -356,46 +370,47 @@ import(
).then((m) => storeLocaleData(m.default, "your-locale"));
```
-...or a custom `registerLocale` function can be passed to the abp core provider configuration options:
+You can also configure a custom `registerLocale` function that can be passed to the abp core provider configuration options:
-```js
+```ts
// register-locale.ts
-import { differentLocales } from '@abp/ng.core';
+import { differentLocales } from "@abp/ng.core";
export function registerLocale(locale: string) {
return import(
/* webpackChunkName: "_locale-[request]"*/
/* webpackInclude: /[/\\](en|fr).js/ */
/* webpackExclude: /[/\\]global|extra/ */
`@angular/common/locales/${differentLocales[locale] || locale}.js`
- )
+ );
}
// app.config.ts
-import { registerLocale } from './register-locale';
+import { registerLocale } from "./register-locale";
export const appConfig: ApplicationConfig = {
providers: [
- // ...
+ // ...
provideAbpCore(
withOptions({
// ...,
registerLocaleFn: registerLocale,
- }),
+ })
),
//...
],
};
```
-After this custom `registerLocale` function, since the en and fr added to the `webpackInclude`, only en and fr locale files will be created as chunks:
+After adding a custom `registerLocale` function, only the **`en`** and **`fr`** locale files will be created as separate chunks.
+This happens because only these locales are included in the **`webpackInclude`** configuration.

-Which locale files you add to `webpackInclude` magic comment, they will be included in the bundle
+The locale files that you added to the `webpackInclude` magic comment will be included in the bundle.
## See Also
-* [Localization in ASP.NET Core](../../fundamentals/localization.md)
-* [Video tutorial](https://abp.io/video-courses/essentials/localization)
+- [Localization in ASP.NET Core](../../fundamentals/localization.md)
+- [Video tutorial](https://abp.io/video-courses/essentials/localization)
diff --git a/docs/en/framework/ui/angular/lookup-components.md b/docs/en/framework/ui/angular/lookup-components.md
index e63d2b3700..ea3865c4b7 100644
--- a/docs/en/framework/ui/angular/lookup-components.md
+++ b/docs/en/framework/ui/angular/lookup-components.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement ABP Commercial's lookup components in your Angular project for efficient relational data retrieval."
+}
+```
+
# Lookup Components
The Angular UI of ABP Commercial introduces some components with `abp-lookup-...` selector prefix. These components are used for retrieving relational entity data.
diff --git a/docs/en/framework/ui/angular/manage-profile-page-tabs.md b/docs/en/framework/ui/angular/manage-profile-page-tabs.md
index fbb12c852e..1a515b7b28 100644
--- a/docs/en/framework/ui/angular/manage-profile-page-tabs.md
+++ b/docs/en/framework/ui/angular/manage-profile-page-tabs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to manage profile page tabs in ABP Framework using `ManageProfileTabsService` for adding, removing, or editing tabs effortlessly."
+}
+```
+
# Manage Profile Page Tabs

@@ -9,13 +16,12 @@ See the example below, covers all features:
```ts
// manage-profile-tabs.provider.ts
-import { provideAppInitializer, Component } from "@angular/core";
+import { Component, inject, provideAppInitializer } from "@angular/core";
import { TwoFactorTabComponent } from "@volo/abp.ng.account/public";
import {
eAccountManageProfileTabNames,
ManageProfileTabsService,
} from "@volo/abp.ng.account/public/config";
-import { MyAwesomeTabComponent } from "./my-awesome-tab/my-awesome-tab.component";
@Component({
selector: "abp-my-awesome-tab",
@@ -23,14 +29,14 @@ import { MyAwesomeTabComponent } from "./my-awesome-tab/my-awesome-tab.component
})
class MyAwesomeTabComponent {}
-export const MANAGE_PROFILE_TAB_PROVIDER = {
- provideAppInitializer(()=>{
+export const MANAGE_PROFILE_TAB_PROVIDER = [
+ provideAppInitializer(() => {
configureManageProfileTabs();
}),
-};
+];
export function configureManageProfileTabs() {
- tabs = inject(ManageProfileTabsService);
+ const tabs = inject(ManageProfileTabsService);
tabs.add([
{
name: "::MyAwesomeTab", // supports localization keys
@@ -56,7 +62,7 @@ import { MANAGE_PROFILE_TAB_PROVIDER } from "./manage-profile-tabs.provider";
export const appConfig: ApplicationConfig = {
providers: [
// ...
- MANAGE_PROFILE_TAB_PROVIDER
+ MANAGE_PROFILE_TAB_PROVIDER,
],
};
```
diff --git a/docs/en/framework/ui/angular/migration-guide-v3.md b/docs/en/framework/ui/angular/migration-guide-v3.md
index 1d968125be..d5c70d1494 100644
--- a/docs/en/framework/ui/angular/migration-guide-v3.md
+++ b/docs/en/framework/ui/angular/migration-guide-v3.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to smoothly migrate your ABP Angular UI from v2.9 to v3.0, ensuring compatibility with Angular 10 and optimizing your project."
+}
+```
+
# v2.9 to v3.0 Angular UI Migration Guide
## What Changed in v3.0?
diff --git a/docs/en/framework/ui/angular/modal.md b/docs/en/framework/ui/angular/modal.md
index 7ff20d885a..e207d080a3 100644
--- a/docs/en/framework/ui/angular/modal.md
+++ b/docs/en/framework/ui/angular/modal.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the flexible `ModalComponent` from ABP Framework for customizable modals with seamless integration and user-friendly features."
+}
+```
+
# Modal
`ModalComponent` is a pre-built component exposed by `@abp/ng.theme.shared` package to show modals. The component uses the [`ng-bootstrap`](https://ng-bootstrap.github.io/)'s modal service inside to render a modal.
diff --git a/docs/en/framework/ui/angular/modifying-the-menu.md b/docs/en/framework/ui/angular/modifying-the-menu.md
index 087f022dc3..75da5169cb 100644
--- a/docs/en/framework/ui/angular/modifying-the-menu.md
+++ b/docs/en/framework/ui/angular/modifying-the-menu.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize the menu in ABP Framework, including adding logos and navigation elements for enhanced application layout."
+}
+```
+
# Modifying the Menu
The menu is inside the `ApplicationLayoutComponent` in the @abp/ng.theme.basic package. There are several methods for modifying the menu elements. This document covers these methods. If you would like to replace the menu completely, please refer to [Component Replacement documentation](./component-replacement.md) and learn how to replace a layout.
diff --git a/docs/en/framework/ui/angular/multi-tenancy.md b/docs/en/framework/ui/angular/multi-tenancy.md
index c85ac976a3..92bc1da72d 100644
--- a/docs/en/framework/ui/angular/multi-tenancy.md
+++ b/docs/en/framework/ui/angular/multi-tenancy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement multi-tenancy in ABP Angular UI, including tenant management and switching features for a seamless user experience."
+}
+```
+
# Multi-Tenancy in Angular UI
ABP Angular UI supports the multi-tenancy. The following features related to multi-tenancy are available in the startup templates.
diff --git a/docs/en/framework/ui/angular/oauth-module.md b/docs/en/framework/ui/angular/oauth-module.md
index 8ec30ae4b4..d8ecab52fc 100644
--- a/docs/en/framework/ui/angular/oauth-module.md
+++ b/docs/en/framework/ui/angular/oauth-module.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP OAuth Package to learn about authentication integration in your app, including essential classes and functions for seamless user management."
+}
+```
+
# ABP OAuth Package
The authentication functionality has been moved from @abp/ng.core to @abp/ng.ouath since v7.0.
diff --git a/docs/en/framework/ui/angular/overview.md b/docs/en/framework/ui/angular/overview.md
index 3b54b395e1..b4dc004f87 100644
--- a/docs/en/framework/ui/angular/overview.md
+++ b/docs/en/framework/ui/angular/overview.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP Angular’s tools and utilities for seamless frontend development, enhancing your interactive web UIs with TypeScript and NodeJS."
+}
+```
+
# Angular UI
[Angular](https://angular.dev/) is a framework for building interactive, client-side web UIs using [TypeScript](https://www.typescriptlang.org) and [NodeJS](https://nodejs.org).
diff --git a/docs/en/framework/ui/angular/page-alerts.md b/docs/en/framework/ui/angular/page-alerts.md
index 8af18dbc4d..3f1e1ec4e3 100644
--- a/docs/en/framework/ui/angular/page-alerts.md
+++ b/docs/en/framework/ui/angular/page-alerts.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively display important messages to users using the ABP Framework's Page Alert feature with easy-to-follow examples."
+}
+```
+
# Page Alerts
A page alert is useful for displaying an important message to the user. The ABP provides an easy way to show the following alert to the user.
diff --git a/docs/en/framework/ui/angular/page-component.md b/docs/en/framework/ui/angular/page-component.md
index 86fd1b8aea..63acb4c33a 100644
--- a/docs/en/framework/ui/angular/page-component.md
+++ b/docs/en/framework/ui/angular/page-component.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to simplify your Angular templates with the ABP `abp-page` component, enhancing code efficiency and structure."
+}
+```
+
# Page Component
ABP provides a component that wraps your content with some built-in components to reduce the amount of code you need to write.
diff --git a/docs/en/framework/ui/angular/page-toolbar-extensions.md b/docs/en/framework/ui/angular/page-toolbar-extensions.md
index 5a741b3d2f..8214c19889 100644
--- a/docs/en/framework/ui/angular/page-toolbar-extensions.md
+++ b/docs/en/framework/ui/angular/page-toolbar-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your Angular UI with custom page toolbar actions, allowing seamless integration of functionalities like modals and API calls."
+}
+```
+
# Page Toolbar Extensions for Angular UI
## Introduction
diff --git a/docs/en/framework/ui/angular/password-complexity-indicator-component.md b/docs/en/framework/ui/angular/password-complexity-indicator-component.md
index 1733f9543e..e34100b91f 100644
--- a/docs/en/framework/ui/angular/password-complexity-indicator-component.md
+++ b/docs/en/framework/ui/angular/password-complexity-indicator-component.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement the Password Complexity Indicator in your app with default settings for colors, texts, and requirements to enhance user security."
+}
+```
+
# Password Complexity Indicator
The `PasswordComplexityIndicatorService` is for calculating the password complexity.
diff --git a/docs/en/framework/ui/angular/permission-management-component-replacement.md b/docs/en/framework/ui/angular/permission-management-component-replacement.md
index c6041cc784..f91fbb42d9 100644
--- a/docs/en/framework/ui/angular/permission-management-component-replacement.md
+++ b/docs/en/framework/ui/angular/permission-management-component-replacement.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to replace the PermissionManagementComponent in your ABP Framework application with this step-by-step guide."
+}
+```
+
# How to Replace PermissionManagementComponent

diff --git a/docs/en/framework/ui/angular/permission-management.md b/docs/en/framework/ui/angular/permission-management.md
index cb22b5863a..abba8843de 100644
--- a/docs/en/framework/ui/angular/permission-management.md
+++ b/docs/en/framework/ui/angular/permission-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage user permissions in ABP Framework with practical examples and methods for effective authorization control."
+}
+```
+
# Permission Management
A permission is a simple policy that is granted or prohibited for a particular user, role or client. You can read more about [authorization in ABP](../../fundamentals/authorization.md) document.
diff --git a/docs/en/framework/ui/angular/projection-strategy.md b/docs/en/framework/ui/angular/projection-strategy.md
index 2fa93d1ca4..4cb3c53422 100644
--- a/docs/en/framework/ui/angular/projection-strategy.md
+++ b/docs/en/framework/ui/angular/projection-strategy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use `ProjectionStrategy` in ABP Framework to effectively project components with various strategies for enhanced content management."
+}
+```
+
# ProjectionStrategy
`ProjectionStrategy` is an abstract class exposed by @abp/ng.core package. There are three projection strategies extending it: `ComponentProjectionStrategy`, `RootComponentProjectionStrategy`, and `TemplateProjectionStrategy`. Implementing the same methods and properties, all of these strategies help you define how your content projection will work.
diff --git a/docs/en/framework/ui/angular/pwa-configuration.md b/docs/en/framework/ui/angular/pwa-configuration.md
index 9825eb0a52..2c042e9d77 100644
--- a/docs/en/framework/ui/angular/pwa-configuration.md
+++ b/docs/en/framework/ui/angular/pwa-configuration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily convert your Angular application into a Progressive Web App (PWA) and leverage native features for enhanced user experience."
+}
+```
+
# PWA Configuration
[Progressive Web Apps](https://web.dev/progressive-web-apps/) are web applications which, although not as integrated to the OS as a native app, can take advantage of native features. They can be discovered via search engines, installed on devices with a single tap or click, and shared via a regular link. They also can work offline and get updates when new content is available.
diff --git a/docs/en/framework/ui/angular/quick-start.md b/docs/en/framework/ui/angular/quick-start.md
index 77080141ed..f5bc88329f 100644
--- a/docs/en/framework/ui/angular/quick-start.md
+++ b/docs/en/framework/ui/angular/quick-start.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to set up your development environment for ABP Angular 17.3.x with this quick start guide, ensuring a smooth development experience."
+}
+```
+
# ABP Angular Quick Start
**In this version ABP uses Angular [20.0.x](https://github.com/angular/angular/tree/20.0.x) version. You don't have to install Angular CLI globally**
diff --git a/docs/en/framework/ui/angular/router-events.md b/docs/en/framework/ui/angular/router-events.md
index a41874ec10..b7b760ae3f 100644
--- a/docs/en/framework/ui/angular/router-events.md
+++ b/docs/en/framework/ui/angular/router-events.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to simplify router event handling in Angular with `RouterEvents`, making your code cleaner and more efficient."
+}
+```
+
# Router Events Simplified
`RouterEvents` is a utility service for filtering specific router events and reacting to them. Please see [this page in Angular docs](https://angular.io/api/router/Event) for available router events.
diff --git a/docs/en/framework/ui/angular/service-proxies.md b/docs/en/framework/ui/angular/service-proxies.md
index 23e17b9759..51a6c4f5b4 100644
--- a/docs/en/framework/ui/angular/service-proxies.md
+++ b/docs/en/framework/ui/angular/service-proxies.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently create service proxies for Angular applications using ABP Framework, avoiding manual transformations and improving code clarity."
+}
+```
+
# Service Proxies
Calling a REST endpoint from Angular applications is common. We usually create **services** matching server-side controllers and **interfaces** matching [DTOs](../../architecture/domain-driven-design/data-transfer-objects.md) to interact with the server. This often results in manually transforming C# code into TypeScript equivalents and that is unfortunate, if not intolerable.
diff --git a/docs/en/framework/ui/angular/settings.md b/docs/en/framework/ui/angular/settings.md
index f6325c9a8d..dc352e96a1 100644
--- a/docs/en/framework/ui/angular/settings.md
+++ b/docs/en/framework/ui/angular/settings.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the ConfigStateService in Angular projects to access server-defined settings effectively with ABP Framework."
+}
+```
+
# Settings
You can get settings on the client-side using the [config state service](./config-state.md) if they are allowed by their setting definition on the server-side.
diff --git a/docs/en/framework/ui/angular/show-password-directive.md b/docs/en/framework/ui/angular/show-password-directive.md
index 588aa3a60b..64c15c9541 100644
--- a/docs/en/framework/ui/angular/show-password-directive.md
+++ b/docs/en/framework/ui/angular/show-password-directive.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Easily enhance password inputs with the Show Password Directive from ABP Framework, allowing users to toggle visibility for better usability."
+}
+```
+
# Show Password Directive
In password input, text can be shown easily via changing input type attribute to `text`. To make this even easier, you can use the `ShowPasswordDirective` which has been exposed by the `@abp/ng.core` package.
diff --git a/docs/en/framework/ui/angular/sorting-navigation-elements.md b/docs/en/framework/ui/angular/sorting-navigation-elements.md
index a5a9b3db89..f1ab1eae9d 100644
--- a/docs/en/framework/ui/angular/sorting-navigation-elements.md
+++ b/docs/en/framework/ui/angular/sorting-navigation-elements.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to sort navigation elements in ABP Framework, customize sorting behavior, and understand the default algorithm effectively."
+}
+```
+
# Sorting Navigation Elements
This documentation describes how the navigation elements are sorted and how to change this default behaviour.
diff --git a/docs/en/framework/ui/angular/subscription-service.md b/docs/en/framework/ui/angular/subscription-service.md
index f098d556d4..b04a3dbf58 100644
--- a/docs/en/framework/ui/angular/subscription-service.md
+++ b/docs/en/framework/ui/angular/subscription-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage RxJS subscriptions in Angular components using the `SubscriptionService` for efficient resource cleanup."
+}
+```
+
# Managing RxJS Subscriptions
`SubscriptionService` is a utility service to provide an easy unsubscription from RxJS observables in Angular components and directives. Please see [why you should unsubscribe from observables on instance destruction](https://angular.io/guide/lifecycle-hooks#cleaning-up-on-instance-destruction).
diff --git a/docs/en/framework/ui/angular/testing.md b/docs/en/framework/ui/angular/testing.md
index 28da243b47..c0d5ff312c 100644
--- a/docs/en/framework/ui/angular/testing.md
+++ b/docs/en/framework/ui/angular/testing.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to unit test your ABP Angular UI applications with preconfigured Karma and Jasmine, plus ABP-specific testing topics."
+}
+```
+
# Unit Testing Angular UI
ABP Angular UI is tested like any other Angular application. So, [the guide here](https://angular.io/guide/testing) applies to ABP too. That said, we would like to point out some **unit testing topics specific to ABP Angular applications**.
diff --git a/docs/en/framework/ui/angular/theme-configurations.md b/docs/en/framework/ui/angular/theme-configurations.md
index bdb5189c8b..f052d97e3d 100644
--- a/docs/en/framework/ui/angular/theme-configurations.md
+++ b/docs/en/framework/ui/angular/theme-configurations.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure theme settings in Angular for ABP Framework, ensuring your UI styles load correctly with the latest updates."
+}
+```
+
# Angular UI: Theme Configurations
Theme packages no longer import styles as CSS modules as of ABP version 6.0. The following style settings need to be included to the angular.json file in order for theme packages to load styles.
diff --git a/docs/en/framework/ui/angular/theming.md b/docs/en/framework/ui/angular/theming.md
index b19f713c71..cb6f8fe8b0 100644
--- a/docs/en/framework/ui/angular/theming.md
+++ b/docs/en/framework/ui/angular/theming.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's Angular UI Theming system, enabling customizable, theme-independent modules for seamless application design and upgrades."
+}
+```
+
# Angular UI: Theming
## Introduction
diff --git a/docs/en/framework/ui/angular/toaster-service.md b/docs/en/framework/ui/angular/toaster-service.md
index 2737e1067e..49094159f2 100644
--- a/docs/en/framework/ui/angular/toaster-service.md
+++ b/docs/en/framework/ui/angular/toaster-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the ToasterService in ABP to display customizable toast messages in your Angular applications effortlessly."
+}
+```
+
# Toast Overlay
You can use the `ToasterService` in @abp/ng.theme.shared package to display messages in an overlay by placing at the root level in your project.
diff --git a/docs/en/framework/ui/angular/track-by-service.md b/docs/en/framework/ui/angular/track-by-service.md
index 84159f12de..046935e5b6 100644
--- a/docs/en/framework/ui/angular/track-by-service.md
+++ b/docs/en/framework/ui/angular/track-by-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to simplify Angular's `TrackByFunction` with the `TrackByService`, enhancing performance in your components effortlessly."
+}
+```
+
# Easy *ngFor trackBy
`TrackByService` is a utility service to provide an easy implementation for one of the most frequent needs in Angular templates: `TrackByFunction`. Please see [this page in Angular docs](https://angular.io/guide/template-syntax#ngfor-with-trackby) for its purpose.
diff --git a/docs/en/framework/ui/blazor/authentication.md b/docs/en/framework/ui/blazor/authentication.md
index a907beb862..a793a784bd 100644
--- a/docs/en/framework/ui/blazor/authentication.md
+++ b/docs/en/framework/ui/blazor/authentication.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement authentication in Blazor applications using OpenId Connect, with features like registration and password recovery."
+}
+```
+
# Blazor UI: Authentication
````json
diff --git a/docs/en/framework/ui/blazor/authorization.md b/docs/en/framework/ui/blazor/authorization.md
index 3d66c7949c..fc006136b4 100644
--- a/docs/en/framework/ui/blazor/authorization.md
+++ b/docs/en/framework/ui/blazor/authorization.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement authorization in Blazor UI with ABP Framework, utilizing role-based and policy-based access control for enhanced security."
+}
+```
+
# Blazor UI: Authorization
Blazor applications can use the same authorization system and permissions defined in the server side.
diff --git a/docs/en/framework/ui/blazor/basic-theme.md b/docs/en/framework/ui/blazor/basic-theme.md
index bf4684b668..33c0cb7175 100644
--- a/docs/en/framework/ui/blazor/basic-theme.md
+++ b/docs/en/framework/ui/blazor/basic-theme.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Basic Theme for Blazor UI— a minimalist base to customize and build your own themes with ease!"
+}
+```
+
# Blazor UI: Basic Theme
````json
diff --git a/docs/en/framework/ui/blazor/block-busy.md b/docs/en/framework/ui/blazor/block-busy.md
index 1c88a48436..38863c8064 100644
--- a/docs/en/framework/ui/blazor/block-busy.md
+++ b/docs/en/framework/ui/blazor/block-busy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the Block/Busy Service in Blazor UI to disable page elements and enhance user experience with progress indicators."
+}
+```
+
# Blazor UI: Block/Busy Service
UI Block disables (blocks) the page or a part of the page.
diff --git a/docs/en/framework/ui/blazor/branding.md b/docs/en/framework/ui/blazor/branding.md
index 81b4244c25..d6e7e4d358 100644
--- a/docs/en/framework/ui/blazor/branding.md
+++ b/docs/en/framework/ui/blazor/branding.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize your Blazor app's branding with the `IBrandingProvider` interface for a personalized user experience."
+}
+```
+
# Blazor UI: Branding
## IBrandingProvider
diff --git a/docs/en/framework/ui/blazor/components/submit-button.md b/docs/en/framework/ui/blazor/components/submit-button.md
index 86a86f110e..832554c9b1 100644
--- a/docs/en/framework/ui/blazor/components/submit-button.md
+++ b/docs/en/framework/ui/blazor/components/submit-button.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the `SubmitButton` component in Blazor UI, designed for easy form submissions with localization support and loading indicators."
+}
+```
+
# Blazor UI: SubmitButton Component
`SubmitButton` is a simple wrapper around `Button` component. It is used to be placed inside of page Form or Modal dialogs where it can response to user actions and to be activated as a default button by pressing an ENTER key. Once clicked it will go into the `disabled` state and also it will show a small loading indicator until clicked event is finished.
diff --git a/docs/en/framework/ui/blazor/current-tenant.md b/docs/en/framework/ui/blazor/current-tenant.md
index a7a9d35fcb..6456acc7cb 100644
--- a/docs/en/framework/ui/blazor/current-tenant.md
+++ b/docs/en/framework/ui/blazor/current-tenant.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `ICurrentTenant` service in ABP Framework to access tenant information in multi-tenant applications effectively."
+}
+```
+
# Blazor UI: Current Tenant
`ICurrentTenant` service can be used to get information about the current tenant in a [multi-tenant](../../architecture/multi-tenancy) application. `ICurrentTenant` defines the following properties;
diff --git a/docs/en/framework/ui/blazor/current-user.md b/docs/en/framework/ui/blazor/current-user.md
index 5016ba79aa..43a798f2f1 100644
--- a/docs/en/framework/ui/blazor/current-user.md
+++ b/docs/en/framework/ui/blazor/current-user.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `ICurrentUser` service in Blazor to access and display authenticated user information seamlessly."
+}
+```
+
# Blazor UI: Current User
`ICurrentUser` service is used to obtain information about the currently authenticated user. Inject the `ICurrentUser` into any component/page and use its properties and methods.
diff --git a/docs/en/framework/ui/blazor/customization-overriding-components.md b/docs/en/framework/ui/blazor/customization-overriding-components.md
index fb8e4422e5..8855ff89bd 100644
--- a/docs/en/framework/ui/blazor/customization-overriding-components.md
+++ b/docs/en/framework/ui/blazor/customization-overriding-components.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize and override Razor components in Blazor applications using ABP Framework for a tailored UI experience."
+}
+```
+
# Blazor UI: Customization / Overriding Components
````json
diff --git a/docs/en/framework/ui/blazor/data-table-column-extensions.md b/docs/en/framework/ui/blazor/data-table-column-extensions.md
index 4fc12d6cda..b89b825201 100644
--- a/docs/en/framework/ui/blazor/data-table-column-extensions.md
+++ b/docs/en/framework/ui/blazor/data-table-column-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to add custom columns to your Blazor UI data tables with the Data Table Column Extensions, enhancing your application's functionality."
+}
+```
+
# Data Table Column Extensions for Blazor UI
Data table column extension system allows you to add a **new table column** on the user interface. The example below adds a new column with the "Email Confirmed" title:
diff --git a/docs/en/framework/ui/blazor/entity-action-extensions.md b/docs/en/framework/ui/blazor/entity-action-extensions.md
index 0383546ddf..ab3d4b3cba 100644
--- a/docs/en/framework/ui/blazor/entity-action-extensions.md
+++ b/docs/en/framework/ui/blazor/entity-action-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your Blazor UI by adding custom actions to entity menus with Entity Action Extensions in ABP Framework."
+}
+```
+
# Entity Action Extensions for Blazor UI
Entity action extension system allows you to add a **new action** to the action menu for an entity. A **Click Me** action was added to the *User Management* page below:
diff --git a/docs/en/framework/ui/blazor/error-handling.md b/docs/en/framework/ui/blazor/error-handling.md
index b2e607d3ea..2fae4ff38d 100644
--- a/docs/en/framework/ui/blazor/error-handling.md
+++ b/docs/en/framework/ui/blazor/error-handling.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement effective error handling in Blazor UI with ABP Framework, ensuring user-friendly messages and seamless integration with server-side exceptions."
+}
+```
+
# Blazor UI: Error Handling
````json
diff --git a/docs/en/framework/ui/blazor/forms-validation.md b/docs/en/framework/ui/blazor/forms-validation.md
index dc5de1f6ce..7fb1423e77 100644
--- a/docs/en/framework/ui/blazor/forms-validation.md
+++ b/docs/en/framework/ui/blazor/forms-validation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement form validation in ABP Blazor UI using Blazorise's validation infrastructure with practical examples."
+}
+```
+
# Blazor UI: Forms & Validation
ABP Blazor UI is based on the [Blazorise](https://blazorise.com/docs) and does not have a built-in form validation infrastructure. However, you can use the [Blazorise validation infrastructure](https://blazorise.com/docs/components/validation) to validate your forms.
diff --git a/docs/en/framework/ui/blazor/global-features.md b/docs/en/framework/ui/blazor/global-features.md
index cbc1bf28af..605a72f0b1 100644
--- a/docs/en/framework/ui/blazor/global-features.md
+++ b/docs/en/framework/ui/blazor/global-features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use `GlobalFeatureManager` in Blazor to check and manage global features effectively for your applications."
+}
+```
+
# Blazor UI: Global Features
`GlobalFeatureManager` allows you to check the global features in your Blazor applications.
diff --git a/docs/en/framework/ui/blazor/global-scripts-styles.md b/docs/en/framework/ui/blazor/global-scripts-styles.md
index a8819df35a..998a16a50a 100644
--- a/docs/en/framework/ui/blazor/global-scripts-styles.md
+++ b/docs/en/framework/ui/blazor/global-scripts-styles.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage global scripts and styles in Blazor apps using ABP, simplifying references and dependency management effortlessly."
+}
+```
+
# Blazor UI: Managing Global Scripts & Styles
You can add your JavaScript and CSS files from your modules or applications to the Blazor global assets system. All the JavaScript and CSS files will be added to the `global.js` and `global.css` files. You can access these files via the following URL in a Blazor WASM project:
diff --git a/docs/en/framework/ui/blazor/layout-hooks.md b/docs/en/framework/ui/blazor/layout-hooks.md
index d54b225c6d..53d0b5edf5 100644
--- a/docs/en/framework/ui/blazor/layout-hooks.md
+++ b/docs/en/framework/ui/blazor/layout-hooks.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize Blazor layouts using Layout Hooks in the ABP Framework, enabling dynamic content integration while maintaining theme updates."
+}
+```
+
# Blazor UI: Layout Hooks
ABP theming system places the page layout into the [theme](theming.md) NuGet packages. That means the final application doesn't include a layout, so you can't directly change the layout code to customize it.
diff --git a/docs/en/framework/ui/blazor/localization.md b/docs/en/framework/ui/blazor/localization.md
index 77a4c516c3..c8de94c89c 100644
--- a/docs/en/framework/ui/blazor/localization.md
+++ b/docs/en/framework/ui/blazor/localization.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement localization in Blazor apps using `IStringLocalizer` for seamless multi-language support with ABP Framework."
+}
+```
+
# Blazor UI: Localization
Blazor applications can reuse the same `IStringLocalizer` service that is explained in the [localization document](../../fundamentals/localization.md).
diff --git a/docs/en/framework/ui/blazor/message.md b/docs/en/framework/ui/blazor/message.md
index ee47aa6b52..850b199c29 100644
--- a/docs/en/framework/ui/blazor/message.md
+++ b/docs/en/framework/ui/blazor/message.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the Blazor UI Message Service to display user-friendly success messages in your app with ease."
+}
+```
+
# Blazor UI: Message Service
UI message service is used to show nice-looking messages to the user as a blocking dialog.
diff --git a/docs/en/framework/ui/blazor/navigation-menu.md b/docs/en/framework/ui/blazor/navigation-menu.md
index 4019538d42..be708963d0 100644
--- a/docs/en/framework/ui/blazor/navigation-menu.md
+++ b/docs/en/framework/ui/blazor/navigation-menu.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively add and manage navigation menus in your ABP Framework application using the modular menu infrastructure."
+}
+```
+
# Blazor UI: Navigation / Menu
Every application has a main menu to allow users to navigate to pages/screens of the application. Some applications may contain more than one menu in different sections of the UI.
diff --git a/docs/en/framework/ui/blazor/notification.md b/docs/en/framework/ui/blazor/notification.md
index 57578cafc4..1f483f67a8 100644
--- a/docs/en/framework/ui/blazor/notification.md
+++ b/docs/en/framework/ui/blazor/notification.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to implement toast notifications in Blazor UI with the `IUiNotificationService` for a better user experience."
+}
+```
+
# Blazor UI: Notification Service
`IUiNotificationService` is used to show toast style notifications on the user interface.
diff --git a/docs/en/framework/ui/blazor/overall.md b/docs/en/framework/ui/blazor/overall.md
index 54a545759e..23077e307e 100644
--- a/docs/en/framework/ui/blazor/overall.md
+++ b/docs/en/framework/ui/blazor/overall.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's Blazor UI integration, simplifying your development with various hosting models for building interactive web applications."
+}
+```
+
# Blazor UI: Overall
[Blazor](https://docs.microsoft.com/en-us/aspnet/core/blazor/) is a framework for building interactive client-side web UI with .NET. It enables .NET developers to create Single-Page Web Applications using C# and the Razor syntax.
diff --git a/docs/en/framework/ui/blazor/page-alerts.md b/docs/en/framework/ui/blazor/page-alerts.md
index 14554ecdea..bde73820d6 100644
--- a/docs/en/framework/ui/blazor/page-alerts.md
+++ b/docs/en/framework/ui/blazor/page-alerts.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement page alerts in Blazor UI using IAlertManager for effective user notifications in your applications."
+}
+```
+
# Blazor UI: Page Alerts
It is common to show error, warning or information alerts to inform the user. An example *Service Interruption* alert is shown below:
diff --git a/docs/en/framework/ui/blazor/page-header.md b/docs/en/framework/ui/blazor/page-header.md
index d21db1ab59..ed2e16903d 100644
--- a/docs/en/framework/ui/blazor/page-header.md
+++ b/docs/en/framework/ui/blazor/page-header.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the Blazor `PageHeader` component to customize page titles, breadcrumbs, and toolbars for your ABP Framework applications."
+}
+```
+
# Blazor UI: Page Header
You can use the`PageHeader` component to set the page title, the breadcrumb items and the toolbar items for a page. Before using the `PageHeader` component, you need to add a using statement for the `Volo.Abp.AspNetCore.Components.Web.Theming.Layout` namespace.
diff --git a/docs/en/framework/ui/blazor/page-layout.md b/docs/en/framework/ui/blazor/page-layout.md
index 5680166608..75666fd17a 100644
--- a/docs/en/framework/ui/blazor/page-layout.md
+++ b/docs/en/framework/ui/blazor/page-layout.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to define page-specific elements with PageLayout in ABP Framework, enhancing your application's navigation and title management."
+}
+```
+
# Page Layout
PageLayout is used to define page-specific elements across application.
diff --git a/docs/en/framework/ui/blazor/page-progress.md b/docs/en/framework/ui/blazor/page-progress.md
index 4c6fb72d97..0616a63e80 100644
--- a/docs/en/framework/ui/blazor/page-progress.md
+++ b/docs/en/framework/ui/blazor/page-progress.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the Page Progress feature in Blazor UI to enhance user experience with automated and customizable loading indicators."
+}
+```
+
# Blazor UI: Page Progress
Page Progress is used to show a progress bar indicator on top of the page and to show to the user that currently a long running process is in the work.
diff --git a/docs/en/framework/ui/blazor/page-toolbar-extensions.md b/docs/en/framework/ui/blazor/page-toolbar-extensions.md
index 555bf1d145..7e341c50fe 100644
--- a/docs/en/framework/ui/blazor/page-toolbar-extensions.md
+++ b/docs/en/framework/ui/blazor/page-toolbar-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your Blazor UI by adding custom components to the page toolbar, like an \"Import users from Excel\" button."
+}
+```
+
# Page Toolbar Extensions for Blazor UI
Page toolbar system allows you to add components to the toolbar of any page. The page toolbar is the area right to the header of a page. A button ("Import users from excel") was added to the user management page below:
diff --git a/docs/en/framework/ui/blazor/pwa-configuration.md b/docs/en/framework/ui/blazor/pwa-configuration.md
index 6c2396b214..28ba4cacd9 100644
--- a/docs/en/framework/ui/blazor/pwa-configuration.md
+++ b/docs/en/framework/ui/blazor/pwa-configuration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure Progressive Web Apps (PWAs) with Blazor WebAssembly in ABP Framework for enhanced offline and installable experiences."
+}
+```
+
# PWA Configuration
[PWAs (Progressive Web Apps)](https://web.dev/progressive-web-apps/) are developed using specific technologies to allow applications to take advantage of both web and native app features.
diff --git a/docs/en/framework/ui/blazor/routing.md b/docs/en/framework/ui/blazor/routing.md
index 59f698d37e..9c77bddc87 100644
--- a/docs/en/framework/ui/blazor/routing.md
+++ b/docs/en/framework/ui/blazor/routing.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance Blazor's routing in ABP Framework by adding assemblies for modular development with the AbpRouterOptions configuration."
+}
+```
+
# Blazor UI: Routing
Blazor has its own [routing system](https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing) and you can use it in your applications. ABP doesn't add any new feature to it, except one small improvement for the [modular development](../../architecture/modularity/basics.md).
diff --git a/docs/en/framework/ui/blazor/settings.md b/docs/en/framework/ui/blazor/settings.md
index 8bcea2323c..6e735c9468 100644
--- a/docs/en/framework/ui/blazor/settings.md
+++ b/docs/en/framework/ui/blazor/settings.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the ISettingProvider in Blazor applications to efficiently manage and retrieve settings values."
+}
+```
+
# Blazor UI: Settings
Blazor applications can reuse the same `ISettingProvider` service that is explained in the [settings document](../../infrastructure/settings.md).
diff --git a/docs/en/framework/ui/blazor/theming.md b/docs/en/framework/ui/blazor/theming.md
index dd942fd92f..7ded33608f 100644
--- a/docs/en/framework/ui/blazor/theming.md
+++ b/docs/en/framework/ui/blazor/theming.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover ABP's UI Theming system for Blazor, enabling customizable, theme-independent applications with reusable modules and easy upgrades."
+}
+```
+
# Blazor UI: Theming
````json
diff --git a/docs/en/framework/ui/blazor/toolbars.md b/docs/en/framework/ui/blazor/toolbars.md
index 8ed30f1364..fa1a5d32e6 100644
--- a/docs/en/framework/ui/blazor/toolbars.md
+++ b/docs/en/framework/ui/blazor/toolbars.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create and customize toolbars in Blazor UI, enhancing your app's interface with user-friendly features."
+}
+```
+
# Blazor UI: Toolbars
The Toolbar system is used to define **toolbars** on the user interface. Modules (or your application) can add **items** to a toolbar, then the [theme](theming.md) renders the toolbar on the **layout**.
diff --git a/docs/en/framework/ui/common/utils/linked-list.md b/docs/en/framework/ui/common/utils/linked-list.md
index 8c6c425e5c..cb9328113f 100644
--- a/docs/en/framework/ui/common/utils/linked-list.md
+++ b/docs/en/framework/ui/common/utils/linked-list.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and use a doubly linked list with the @abp/utils package in Angular and MVC, enhancing your data structure skills!"
+}
+```
+
# Linked List (Doubly)
diff --git a/docs/en/framework/ui/index.md b/docs/en/framework/ui/index.md
index 1e70914225..d892c63c69 100644
--- a/docs/en/framework/ui/index.md
+++ b/docs/en/framework/ui/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's UI options, including MVC, Blazor, Angular, React Native, and MAUI, to build dynamic applications effortlessly."
+}
+```
+
# ABP UI Options
ABP provides several options for building the user interface (UI) in your applications. Here are some of the officially supported UI options you can use with ABP:
diff --git a/docs/en/framework/ui/maui/index.md b/docs/en/framework/ui/maui/index.md
index 94d9357fed..547617bcae 100644
--- a/docs/en/framework/ui/maui/index.md
+++ b/docs/en/framework/ui/maui/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to develop mobile applications with the ABP Commercial platform using MAUI, integrating seamlessly with your ABP backend."
+}
+```
+
````json
//[doc-params]
{
diff --git a/docs/en/framework/ui/mvc-razor-pages/auto-complete-select.md b/docs/en/framework/ui/mvc-razor-pages/auto-complete-select.md
index 760587084d..69f92be3f2 100644
--- a/docs/en/framework/ui/mvc-razor-pages/auto-complete-select.md
+++ b/docs/en/framework/ui/mvc-razor-pages/auto-complete-select.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to implement an auto-complete select component in ASP.NET Core MVC/Razor Pages with pagination and server-side search using ABP."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: Auto-Complete Select
A simple select component sometimes isn't useful with a huge amount of data. ABP Provides a select implementation that works with pagination and server-side search via using [Select2](https://select2.org/). It works with single or multiple choices well.
diff --git a/docs/en/framework/ui/mvc-razor-pages/basic-theme.md b/docs/en/framework/ui/mvc-razor-pages/basic-theme.md
index 4e618edfeb..cbdfe7a79f 100644
--- a/docs/en/framework/ui/mvc-razor-pages/basic-theme.md
+++ b/docs/en/framework/ui/mvc-razor-pages/basic-theme.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Basic Theme for ASP.NET Core MVC/Razor Pages—minimalist, customizable, and RTL-supported, perfect for building your own designs."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: The Basic Theme
The Basic Theme is a theme implementation for the ASP.NET Core MVC / Razor Pages UI. It is a minimalist theme that doesn't add any styling on top of the plain [Bootstrap](https://getbootstrap.com/). You can take the Basic Theme as the **base theme** and build your own theme or styling on top of it. See the *Customization* section.
diff --git a/docs/en/framework/ui/mvc-razor-pages/branding.md b/docs/en/framework/ui/mvc-razor-pages/branding.md
index 46c05d7d7e..e8e9309ff8 100644
--- a/docs/en/framework/ui/mvc-razor-pages/branding.md
+++ b/docs/en/framework/ui/mvc-razor-pages/branding.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize your ASP.NET Core application's branding with `IBrandingProvider` to display your app name and logo effortlessly."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: Branding
## IBrandingProvider
diff --git a/docs/en/framework/ui/mvc-razor-pages/bundling-minification.md b/docs/en/framework/ui/mvc-razor-pages/bundling-minification.md
index b50a144bfe..0114361188 100644
--- a/docs/en/framework/ui/mvc-razor-pages/bundling-minification.md
+++ b/docs/en/framework/ui/mvc-razor-pages/bundling-minification.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently bundle and minify JavaScript and CSS in ASP.NET Core MVC using ABP's built-in solutions for better performance."
+}
+```
+
# ASP.NET Core MVC Bundling & Minification
diff --git a/docs/en/framework/ui/mvc-razor-pages/client-side-package-management.md b/docs/en/framework/ui/mvc-razor-pages/client-side-package-management.md
index 76f9acd5db..de56b40d98 100644
--- a/docs/en/framework/ui/mvc-razor-pages/client-side-package-management.md
+++ b/docs/en/framework/ui/mvc-razor-pages/client-side-package-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage client-side packages with ABP Framework, including using NPM/Yarn for optimal compatibility and stability."
+}
+```
+
# ASP.NET Core MVC Client Side Package Management
diff --git a/docs/en/framework/ui/mvc-razor-pages/customization-user-interface.md b/docs/en/framework/ui/mvc-razor-pages/customization-user-interface.md
index c279f685c0..feadf5b5b3 100644
--- a/docs/en/framework/ui/mvc-razor-pages/customization-user-interface.md
+++ b/docs/en/framework/ui/mvc-razor-pages/customization-user-interface.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize the user interface in ASP.NET Core MVC/Razor Pages by overriding page models and Razor pages for enhanced functionality and design."
+}
+```
+
# ASP.NET Core (MVC / Razor Pages) User Interface Customization Guide
This document explains how to override the user interface of a depended [application module](../../../modules) or [theme](theming.md) for ASP.NET Core MVC / Razor Page applications.
diff --git a/docs/en/framework/ui/mvc-razor-pages/data-table-column-extensions.md b/docs/en/framework/ui/mvc-razor-pages/data-table-column-extensions.md
index 9ad7f7b184..6af6338824 100644
--- a/docs/en/framework/ui/mvc-razor-pages/data-table-column-extensions.md
+++ b/docs/en/framework/ui/mvc-razor-pages/data-table-column-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your ASP.NET Core UI by adding custom data table columns with our easy-to-follow guide on data table column extensions."
+}
+```
+
# Data Table Column Extensions for ASP.NET Core UI
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/data-tables.md b/docs/en/framework/ui/mvc-razor-pages/data-tables.md
index 5418b15710..fb60d40aef 100644
--- a/docs/en/framework/ui/mvc-razor-pages/data-tables.md
+++ b/docs/en/framework/ui/mvc-razor-pages/data-tables.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate DataTables.Net with ABP Framework for seamless tabular data display in your ASP.NET Core MVC/Razor Pages applications."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: Data Tables
A Data Table (aka Data Grid) is a UI component to show tabular data to the users. There are a lot of Data table components/libraries and **you can use any one you like** with the ABP. However, the startup templates come with the [DataTables.Net](https://datatables.net/) library as **pre-installed and configured**. ABP provides adapters for this library and make it easy to use with the API endpoints.
diff --git a/docs/en/framework/ui/mvc-razor-pages/dynamic-javascript-proxies.md b/docs/en/framework/ui/mvc-razor-pages/dynamic-javascript-proxies.md
index 02053f4c9f..ab2f309131 100644
--- a/docs/en/framework/ui/mvc-razor-pages/dynamic-javascript-proxies.md
+++ b/docs/en/framework/ui/mvc-razor-pages/dynamic-javascript-proxies.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use dynamic JavaScript API client proxies in ABP Framework for efficient runtime API calls, enhancing your development experience."
+}
+```
+
# Dynamic JavaScript API Client Proxies
It is typical to consume your HTTP APIs from your JavaScript code. To do that, you normally deal with low level AJAX calls, like $.ajax, or better [abp.ajax](javascript-api/ajax.md). ABP provides **a better way** to call your HTTP APIs from your JavaScript code: JavaScript API Client Proxies!
diff --git a/docs/en/framework/ui/mvc-razor-pages/entity-action-extensions.md b/docs/en/framework/ui/mvc-razor-pages/entity-action-extensions.md
index 1c0b2e73b8..d54a6208d0 100644
--- a/docs/en/framework/ui/mvc-razor-pages/entity-action-extensions.md
+++ b/docs/en/framework/ui/mvc-razor-pages/entity-action-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your ASP.NET Core UI with custom entity action extensions, enabling tailored user interactions for improved functionality."
+}
+```
+
# Entity Action Extensions for ASP.NET Core UI
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/forms-validation.md b/docs/en/framework/ui/mvc-razor-pages/forms-validation.md
index 53684711cd..a3258992e0 100644
--- a/docs/en/framework/ui/mvc-razor-pages/forms-validation.md
+++ b/docs/en/framework/ui/mvc-razor-pages/forms-validation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how ABP simplifies forms and validation in ASP.NET Core MVC/Razor Pages, with automated localization and client-side validation."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: Forms & Validation
ABP provides infrastructure and conventions to make easier to create forms, localize display names for the form elements and handle server & client side validation;
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/ajax.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/ajax.md
index 6575c98b8e..3ee58ca458 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/ajax.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/ajax.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to simplify AJAX calls in ASP.NET Core with the `abp.ajax` API, offering error handling, CSRF protection, and customization options."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI JavaScript AJAX API
`abp.ajax` API provides a convenient way of performing AJAX calls to the server. It internally uses JQuery's `$.ajax`, but automates some common tasks for you;
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/auth.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/auth.md
index 80ba9bed1b..5f31c184ec 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/auth.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/auth.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the JavaScript Auth API in ABP Framework to manage user permissions and conditionally adjust your UI."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Auth API
Auth API allows you to check permissions (policies) for the current user in the client side. In this way, you can conditionally show/hide UI parts or perform your client side logic based on the current permissions.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/block-busy.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/block-busy.md
index 4262b8ff7a..cb053de571 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/block-busy.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/block-busy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the JavaScript UI Block API in ASP.NET Core MVC to efficiently disable parts of your page during operations."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript UI Block/Busy API
UI Block API disables (blocks) the page or a part of the page.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/current-user.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/current-user.md
index ca0797e105..e99fea8264 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/current-user.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/current-user.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp.currentUser` JavaScript API to access current user information in your ASP.NET Core MVC/Razor Pages applications."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript CurrentUser API
`abp.currentUser` is an object that contains information about the current user of the application.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/dom.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/dom.md
index 07713d156d..ecc8648443 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/dom.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/dom.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the ABP Framework's JavaScript DOM API to manage dynamic elements in your ASP.NET Core MVC/Razor Pages applications efficiently."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript DOM API
`abp.dom` (Document Object Model) provides events that you can subscribe to get notified when elements dynamically added to and removed from the page (DOM).
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/events.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/events.md
index 3425355f44..1cb90e6819 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/events.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/events.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp.event` API to publish, subscribe, and manage JavaScript events in your ASP.NET Core MVC/Razor Pages UI for better component communication."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Events API
`abp.event` object is a simple service that is used to publish and subscribe to global events **in the browser**.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/features.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/features.md
index 34dee96fce..6e9f13e70e 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/features.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp.features` JavaScript API to access and manage feature values in your ASP.NET Core applications."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Features API
`abp.features` API allows you to check features or get the values of the features on the client side. You can read the current value of a feature in the client side only if it is allowed by the feature definition (on the server side).
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/global-features.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/global-features.md
index 55d36bb7a1..f25241b36b 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/global-features.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/global-features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp.globalFeatures` JavaScript API to access enabled global features in your ABP Framework applications."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Global Features API
`abp.globalFeatures` API allows you to get the enabled features of the [Global Features](../../../infrastructure/global-features.md) in the client side.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/index.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/index.md
index a8f95bb7fb..193575def6 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/index.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's JavaScript APIs for seamless integration in ASP.NET Core MVC/Razor Pages, enhancing client-side functionality and server-side interaction."
+}
+```
+
# JavaScript API
ABP provides a set of JavaScript APIs for ASP.NET Core MVC / Razor Pages applications. They can be used to perform common application requirements easily in the client side and integrate to the server side.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/localization.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/localization.md
index d4266d0a0b..d0279f557e 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/localization.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/localization.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the JavaScript Localization API in ABP Framework to access server-side localization resources on the client side."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Localization API
Localization API allows you to reuse the server side localization resources in the client side.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/logging.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/logging.md
index 9b3902760b..63bfdfa7d0 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/logging.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/logging.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement client-side logging with the `abp.log` API in ASP.NET Core MVC/Razor Pages for effective debugging and error tracking."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Logging API
`abp.log` API is used to write simple logs in the client side.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/message.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/message.md
index ab9bf084df..d391a7644f 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/message.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/message.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the ABP Framework's Message API for displaying user-friendly alerts in ASP.NET Core MVC/Razor Pages with SweetAlert integration."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Message API
Message API is used to show nice looking messages to the user as a blocking dialog. Message API is an abstraction provided by the ABP and implemented using the [SweetAlert](https://sweetalert.js.org/) library by default.
@@ -88,6 +95,58 @@ abp.message.confirm(
});
````
+## Prompt Message
+
+`abp.message.prompt(...)` can be used to get a text (or other input) from the user.
+
+Simple usage:
+```js
+abp.message.prompt('Please enter a name:', (value)=> console.log('Entered name:', value));
+```
+
+**Example (then):**
+
+````js
+let options = { title: "Name Change" ,icon: "info", inputValue: "John Doe"};
+abp.message.prompt('Enter a new name to change your name', options)
+ .then(function(value){
+ if (value) {
+ console.log('Entered name:', value);
+ }
+ });
+````
+
+**Example (await):**
+
+````js
+(async function(){
+ let options = { title: "Email Registration" ,icon: "info", input: "email"};
+ const email = await abp.message.prompt('Enter your email:', options);
+ if (email) {
+ console.log('Entered email:', email);
+ }
+})();
+````
+
+
+
+### The Return Value
+
+The return value of the `abp.message.prompt(...)` function is a promise that resolves to the entered value (`string`) or `null` if the dialog is canceled/dismissed.
+
+### Parameters
+
+`abp.message.prompt(...)` function has the following parameters:
+
+* `message`: A message (`string`) to show to the user.
+* `titleOrOptionsOrCallback` (optional):
+ * a `string` title, or
+ * an `object` containing SweetAlert options (e.g., `input`, `inputAttributes`, `inputPlaceholder`), or
+ * a `function` callback that receives the resulting value (or `null`).
+* `callback` (optional): If you've passed a title as the second parameter, you can pass your callback function as the 3rd parameter.
+
+Passing a callback function is an alternative to using the returned promise.
+
## SweetAlert Configuration
The Message API is implemented using the [SweetAlert](https://sweetalert.js.org/) library by default. If you want to change its configuration, you can set the options in the `abp.libs.sweetAlert.config` object. The default configuration object is shown below:
@@ -125,4 +184,3 @@ abp.libs.sweetAlert.config.warn.icon = 'error';
````
See the [SweetAlert document](https://sweetalert.js.org/) for all the configuration options.
-
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md
index 043f811d49..187c3621db 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/notify.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the Notify API in ABP Framework to create toast notifications with ease, enhancing user experience in your ASP.NET Core apps."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Notify API
Notify API is used to show toast style, auto disappearing UI notifications to the end user.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/resource-loader.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/resource-loader.md
index 10b8c36f59..3294bf5bc8 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/resource-loader.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/resource-loader.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp.ResourceLoader` API in ASP.NET Core to efficiently load and execute JavaScript and CSS files on demand."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Resource Loader API
`abp.ResourceLoader` is a service that can load a JavaScript or CSS file on demand. It guarantees to load the file only once even if you request multiple times.
diff --git a/docs/en/framework/ui/mvc-razor-pages/javascript-api/settings.md b/docs/en/framework/ui/mvc-razor-pages/javascript-api/settings.md
index cab2bcf98f..13805f08fe 100644
--- a/docs/en/framework/ui/mvc-razor-pages/javascript-api/settings.md
+++ b/docs/en/framework/ui/mvc-razor-pages/javascript-api/settings.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to utilize the JavaScript Setting API in ABP Framework to access client-side settings efficiently and enhance your ASP.NET Core applications."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: JavaScript Setting API
Localization API allows you to get the values of the settings on the client side. You can read the current value of a setting in the client side only if it is allowed by the setting definition (on the server side).
diff --git a/docs/en/framework/ui/mvc-razor-pages/layout-hooks.md b/docs/en/framework/ui/mvc-razor-pages/layout-hooks.md
index 71e82e8e05..f194f6bba3 100644
--- a/docs/en/framework/ui/mvc-razor-pages/layout-hooks.md
+++ b/docs/en/framework/ui/mvc-razor-pages/layout-hooks.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize your ABP Framework layout using Layout Hooks to enhance your ASP.NET Core MVC/Razor Pages applications."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: Layout Hooks
ABP theming system places the page layout into the [theme](theming.md) NuGet packages. That means the final application doesn't include a `Layout.cshtml`, so you can't directly change the layout code to customize it.
diff --git a/docs/en/framework/ui/mvc-razor-pages/modals.md b/docs/en/framework/ui/mvc-razor-pages/modals.md
index 5cfee1a3ab..d37575cc26 100644
--- a/docs/en/framework/ui/mvc-razor-pages/modals.md
+++ b/docs/en/framework/ui/mvc-razor-pages/modals.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how ABP Framework simplifies modal management in ASP.NET Core MVC/Razor Pages, automating tasks for enhanced user experience."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: Modals
While you can continue to use the standard [Bootstrap way](https://getbootstrap.com/docs/4.5/components/modal/) to create, open and manage modals in your applications, ABP provides a **flexible** way to manage modals by **automating common tasks** for you.
diff --git a/docs/en/framework/ui/mvc-razor-pages/navigation-menu.md b/docs/en/framework/ui/mvc-razor-pages/navigation-menu.md
index e9d025b696..41cc31f77f 100644
--- a/docs/en/framework/ui/mvc-razor-pages/navigation-menu.md
+++ b/docs/en/framework/ui/mvc-razor-pages/navigation-menu.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively manage navigation menus in your ABP Framework applications, enabling modular menu item integration with ease."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: Navigation Menu
Every application has a main menu to allow users to navigate to pages/screens of the application. Some applications may contain more than one menu in different sections of the UI.
diff --git a/docs/en/framework/ui/mvc-razor-pages/overall.md b/docs/en/framework/ui/mvc-razor-pages/overall.md
index 657fb42df7..fc5b0b0ac0 100644
--- a/docs/en/framework/ui/mvc-razor-pages/overall.md
+++ b/docs/en/framework/ui/mvc-razor-pages/overall.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to build web applications with ABP using ASP.NET Core MVC and Razor Pages for a streamlined, maintainable development experience."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/page-alerts.md b/docs/en/framework/ui/mvc-razor-pages/page-alerts.md
index d1fa5e6514..80e4285492 100644
--- a/docs/en/framework/ui/mvc-razor-pages/page-alerts.md
+++ b/docs/en/framework/ui/mvc-razor-pages/page-alerts.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement user alerts in ASP.NET Core MVC/Razor Pages with ABP Framework for effective communication in your applications."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: Page Alerts
It is common to show error, warning or information alerts to inform the user. An example *Service Interruption* alert is shown below:
diff --git a/docs/en/framework/ui/mvc-razor-pages/page-header.md b/docs/en/framework/ui/mvc-razor-pages/page-header.md
index 7d760f6ec7..329c447054 100644
--- a/docs/en/framework/ui/mvc-razor-pages/page-header.md
+++ b/docs/en/framework/ui/mvc-razor-pages/page-header.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `IPageLayout` service in ASP.NET Core MVC/Razor Pages to effectively set page titles and manage breadcrumbs for enhanced navigation."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: Page Header
`IPageLayout` service can be used to set the page title, selected menu item and the breadcrumb items for a page. It's the [theme](theming.md)'s responsibility to render these on the page.
diff --git a/docs/en/framework/ui/mvc-razor-pages/page-toolbar-extensions.md b/docs/en/framework/ui/mvc-razor-pages/page-toolbar-extensions.md
index fa5a3a8941..54ad4e182c 100644
--- a/docs/en/framework/ui/mvc-razor-pages/page-toolbar-extensions.md
+++ b/docs/en/framework/ui/mvc-razor-pages/page-toolbar-extensions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your ASP.NET Core UI with custom page toolbar extensions, adding buttons and functionality to improve user experience."
+}
+```
+
# Page Toolbar Extensions for ASP.NET Core UI
Page toolbar system allows you to add components to the toolbar of any page. The page toolbar is the area right to the header of a page. A button ("Import users from excel") was added to the user management page below:
diff --git a/docs/en/framework/ui/mvc-razor-pages/security-headers.md b/docs/en/framework/ui/mvc-razor-pages/security-headers.md
index a54697aca4..a804145e10 100644
--- a/docs/en/framework/ui/mvc-razor-pages/security-headers.md
+++ b/docs/en/framework/ui/mvc-razor-pages/security-headers.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enhance your application's security with essential HTTP headers using ABP Framework's `UseAbpSecurityHeaders` middleware."
+}
+```
+
# Security Headers
ABP allows you to add frequently used security headers into your application. The following security headers will be added as response headers to your application if you use the `UseAbpSecurityHeaders` middleware:
diff --git a/docs/en/framework/ui/mvc-razor-pages/static-javascript-proxies.md b/docs/en/framework/ui/mvc-razor-pages/static-javascript-proxies.md
index ac63334e51..7f7cb042a2 100644
--- a/docs/en/framework/ui/mvc-razor-pages/static-javascript-proxies.md
+++ b/docs/en/framework/ui/mvc-razor-pages/static-javascript-proxies.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use static JavaScript API client proxies with ABP for efficient HTTP API calls, enhancing performance and development ease."
+}
+```
+
# Static JavaScript API Client Proxies
It is typical to consume your HTTP APIs from your JavaScript code. To do that, you normally deal with low level AJAX calls, like $.ajax, or better [abp.ajax](javascript-api/ajax.md). ABP provides **a better way** to call your HTTP APIs from your JavaScript code: JavaScript API Client Proxies!
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/alerts.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/alerts.md
index cf19e31e29..f88ce17401 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/alerts.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/alerts.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create and customize alerts using the `abp-alert` component in ABP Framework, with examples and attribute details for effective notifications."
+}
+```
+
# Alerts
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/badges.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/badges.md
index c627273062..358823b69d 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/badges.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/badges.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use ABP Tag Helpers to create stylish badges in your web applications with customizable attributes and easy examples."
+}
+```
+
# Badges
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/blockquote.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/blockquote.md
index a63187aeb3..be6a207578 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/blockquote.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/blockquote.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp-blockquote` component to create styled blockquotes with proper HTML structure and classes in your ABP applications."
+}
+```
+
# Blockquote
`abp-blockquote` is the main container for blockquote items.
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/borders.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/borders.md
index e1d98ac7d8..76aa6639ae 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/borders.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/borders.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp-border` Tag Helper for versatile border styling in your ABP applications with clear examples and a demo."
+}
+```
+
# Borders
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/breadcrumbs.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/breadcrumbs.md
index b7082696c5..2d995eef8d 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/breadcrumbs.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/breadcrumbs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and customize breadcrumbs in your ABP Framework applications with the `abp-breadcrumb` component for improved navigation."
+}
+```
+
# Breadcrumbs
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/button-groups.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/button-groups.md
index bfd558f89e..f9e9753d5a 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/button-groups.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/button-groups.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use `abp-button-group` for creating grouped buttons in your ABP Framework projects, with customizable directions and sizes."
+}
+```
+
# Button groups
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/buttons.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/buttons.md
index 65e3ee2cf8..75b493a9e2 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/buttons.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/buttons.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the `abp-button` element for creating versatile buttons in your projects. Learn about styles, sizes, and attributes to enhance your UI efficiently."
+}
+```
+
# Buttons
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/cards.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/cards.md
index d7f3896cdd..45f0ba2069 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/cards.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/cards.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp-card` component in ABP Framework to create stylish and functional content containers effortlessly."
+}
+```
+
# Cards
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/carousel.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/carousel.md
index 3b91087838..907eeff717 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/carousel.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/carousel.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and customize the `abp-carousel` component in ABP Framework with easy-to-follow examples and attributes."
+}
+```
+
# Carousel
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/collapse.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/collapse.md
index dfbe8ea248..46813d2011 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/collapse.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/collapse.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use `abp-collapse-body` and `abp-collapse-id` to create dynamic content visibility in your ABP Framework projects."
+}
+```
+
# Collapse
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/dropdowns.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/dropdowns.md
index 75d57479b5..923dcc08ee 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/dropdowns.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/dropdowns.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and customize dropdowns in the ABP Framework with easy-to-follow examples and attributes for enhanced user interaction."
+}
+```
+
# Dropdowns
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/dynamic-forms.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/dynamic-forms.md
index 6b9a07f63a..c83f4a947b 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/dynamic-forms.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/dynamic-forms.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create dynamic forms using `abp-dynamic-form` with a C# model, enhancing your ABP Framework applications effortlessly."
+}
+```
+
# Dynamic Forms
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/figure.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/figure.md
index 20f0450565..b6d7cf8c8e 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/figure.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/figure.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp-figure` component to create responsive images with captions in your Bootstrap projects effortlessly."
+}
+```
+
# Figures
`abp-figure` is the main container for bootstrap figure items.
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/form-elements.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/form-elements.md
index b59ecf8dd3..3ec836872f 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/form-elements.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/form-elements.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to efficiently build forms using ABP Framework's input tag helpers, enhancing your ASP.NET Core applications with ease."
+}
+```
+
# Form Elements
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/grids.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/grids.md
index b33fa03c46..fdad8ceed5 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/grids.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/grids.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's tag helpers for Bootstrap's grid system, including equal width columns and column breakers, to enhance your web development experience."
+}
+```
+
# Grids
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/index.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/index.md
index 02937c7215..d986d65b43 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/index.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP Tag Helpers for ASP.NET Core to simplify UI development with type-safe Bootstrap components and enhance your coding efficiency."
+}
+```
+
# ABP Tag Helpers
ABP defines a set of **tag helper components** to simply the user interface development for ASP.NET Core (MVC / Razor Pages) applications.
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/list-groups.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/list-groups.md
index 08b942bd09..f30ef72a1e 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/list-groups.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/list-groups.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use `abp-list-group` to create structured lists in your ABP Framework applications, complete with examples and attributes."
+}
+```
+
# List Groups
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/modals.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/modals.md
index 47ae472719..1d4084956e 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/modals.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/modals.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily create and customize modals using the `abp-modal` Tag Helper in ABP Framework, enhancing your web application's user experience."
+}
+```
+
# Modals
> This document explains the details of the `abp-modal` Tag Helper, which simplifies to build the HTML markup for a modal dialog. Read [that documentation](../modals.md) to learn how to work with modals.
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/navs.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/navs.md
index 9c8347b831..720eee42aa 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/navs.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/navs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the `abp-nav` tag helper for creating stylish navigation components in your ABP Framework applications."
+}
+```
+
# Navs
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/paginator.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/paginator.md
index c30e68eed9..b7054bf2ef 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/paginator.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/paginator.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement the `abp-paginator` tag in your ABP Framework project for seamless pagination with customizable options."
+}
+```
+
# Paginator
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/popovers.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/popovers.md
index 55bb9fb0f6..04ff130361 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/popovers.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/popovers.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and customize popovers in your ABP Framework applications with the `abp-popover` tag, enhancing user interaction effortlessly."
+}
+```
+
# Popovers
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/progress-bars.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/progress-bars.md
index 1f723f80ae..5f31d25ee3 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/progress-bars.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/progress-bars.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and customize progress bars using the `abp-progress-bar` tag in your ABP Framework applications with practical examples and demos."
+}
+```
+
# Progress Bars
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tables.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tables.md
index db30db6a09..08d98649f1 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tables.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tables.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and customize tables using the `abp-table` component in ABP Framework for responsive and user-friendly designs."
+}
+```
+
# Tables
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tabs.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tabs.md
index 4b8763dc4e..bea9035865 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tabs.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tabs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively use the `abp-tab` component for seamless tab navigation in your ABP Framework applications with practical examples."
+}
+```
+
# Tabs
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tooltips.md b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tooltips.md
index 55b6e574e8..5e3a885699 100644
--- a/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tooltips.md
+++ b/docs/en/framework/ui/mvc-razor-pages/tag-helpers/tooltips.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement tooltips in your ABP Framework applications with easy examples and demos for enhanced user interaction."
+}
+```
+
# Tooltips
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/testing.md b/docs/en/framework/ui/mvc-razor-pages/testing.md
index b637b52be4..f05084f791 100644
--- a/docs/en/framework/ui/mvc-razor-pages/testing.md
+++ b/docs/en/framework/ui/mvc-razor-pages/testing.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to leverage ABP's testing infrastructure for ASP.NET Core MVC/Razor Pages, enhancing your integration testing capabilities."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: Testing
> You can follow the [ASP.NET Core Integration Tests documentation](https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests) to learn details of ASP.NET Core integration tests. This document explains the additional test infrastructure provided by the ABP.
diff --git a/docs/en/framework/ui/mvc-razor-pages/theming.md b/docs/en/framework/ui/mvc-razor-pages/theming.md
index 895032f1d7..ff73b3ad1b 100644
--- a/docs/en/framework/ui/mvc-razor-pages/theming.md
+++ b/docs/en/framework/ui/mvc-razor-pages/theming.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement flexible UI theming in ABP Framework, enabling theme-independent modules and easy customization for your applications."
+}
+```
+
# ASP.NET Core MVC / Razor Pages: UI Theming
## Introduction
diff --git a/docs/en/framework/ui/mvc-razor-pages/toolbars.md b/docs/en/framework/ui/mvc-razor-pages/toolbars.md
index 04860b9adb..fd7160417d 100644
--- a/docs/en/framework/ui/mvc-razor-pages/toolbars.md
+++ b/docs/en/framework/ui/mvc-razor-pages/toolbars.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to define and customize toolbars in your ASP.NET Core MVC/Razor Pages UI, enhancing user experience with flexible UI components."
+}
+```
+
# ASP.NET Core MVC / Razor Pages UI: Toolbars
The Toolbar system is used to define **toolbars** on the user interface. Modules (or your application) can add **items** to a toolbar, then the [theme](theming.md) renders the toolbar on the **layout**.
diff --git a/docs/en/framework/ui/mvc-razor-pages/widgets.md b/docs/en/framework/ui/mvc-razor-pages/widgets.md
index 78c7012fd5..ac9901733b 100644
--- a/docs/en/framework/ui/mvc-razor-pages/widgets.md
+++ b/docs/en/framework/ui/mvc-razor-pages/widgets.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create reusable widgets in ABP Framework, enhancing your ASP.NET Core applications with modular, scriptable components for dynamic dashboards."
+}
+```
+
# Widgets
ABP provides a model and infrastructure to create **reusable widgets**. Widget system is an extension to [ASP.NET Core's ViewComponents](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components). Widgets are especially useful when you want to;
diff --git a/docs/en/framework/ui/react-native/index.md b/docs/en/framework/ui/react-native/index.md
index f83b66b7b6..6496b0a640 100644
--- a/docs/en/framework/ui/react-native/index.md
+++ b/docs/en/framework/ui/react-native/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to set up your development environment for React Native with ABP Framework, enabling seamless mobile app integration!"
+}
+```
+
````json
//[doc-params]
{
diff --git a/docs/en/framework/ui/react-native/setting-up-android-emulator.md b/docs/en/framework/ui/react-native/setting-up-android-emulator.md
index 8ead542a76..e5d14de32a 100644
--- a/docs/en/framework/ui/react-native/setting-up-android-emulator.md
+++ b/docs/en/framework/ui/react-native/setting-up-android-emulator.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to set up an Android emulator without Android Studio using command line tools on Windows, macOS, and Linux."
+}
+```
+
# Setting Up Android Emulator Without Android Studio (Windows, macOS, Linux)
This guide explains how to install and run an Android emulator **without Android Studio**, using only **Command Line Tools**.
@@ -111,6 +118,34 @@ adb install myApp.apk
---
+## How to Enable Fast Refresh in React Native
+
+React Native uses a hot reload system called **Fast Refresh**.
+It is enabled by default in development mode, but you can manually enable or disable it via the Developer Menu.
+
+### To open the Developer Menu on Android emulator:
+
+```bash
+adb shell input keyevent 82
+```
+
+This command simulates the hardware menu button and opens the Developer Menu inside the emulator.
+
+### From the Developer Menu:
+
+- Look for the option: **Enable Fast Refresh**
+- If it's unchecked, tap to enable it
+- If it's already checked, Fast Refresh is already active
+
+### Alternative (if adb doesn't work):
+
+Focus the emulator window and press:
+
+- **Ctrl + M** (Windows/Linux)
+- **Cmd + M** (Mac)
+
+---
+
## Troubleshooting
| Problem | Explanation |
diff --git a/docs/en/get-started/console.md b/docs/en/get-started/console.md
index 6a17784380..cc1223a24d 100644
--- a/docs/en/get-started/console.md
+++ b/docs/en/get-started/console.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to quickly set up a minimalist console application using the ABP CLI with this straightforward guide. Perfect for developers!"
+}
+```
+
# Console Application Startup Template
This template is used to create a minimalist console application project.
diff --git a/docs/en/get-started/empty-aspnet-core-application.md b/docs/en/get-started/empty-aspnet-core-application.md
index 95861719ce..78eb744eda 100644
--- a/docs/en/get-started/empty-aspnet-core-application.md
+++ b/docs/en/get-started/empty-aspnet-core-application.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create an empty ASP.NET Core MVC/Razor Pages application with ABP, minimizing dependencies for a fresh start."
+}
+```
+
# Getting Started with an Empty ASP.NET Core MVC / Razor Pages Application
This tutorial explains how to start ABP from scratch with minimal dependencies. You generally want to start with the **[startup template](../get-started/layered-web-application.md)**.
diff --git a/docs/en/get-started/index.md b/docs/en/get-started/index.md
index 59f9812563..dcc7aa80c3 100644
--- a/docs/en/get-started/index.md
+++ b/docs/en/get-started/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's startup templates for .NET applications, offering tailored solutions for single-layer, layered, and microservice architectures."
+}
+```
+
# Get Started
Great that you've decided to create a new application with ABP. ABP provides multiple startup templates for different needs. Each startup template is a fine-tuned and production-ready .NET solution that you can immediately start to develop your application based on it.
diff --git a/docs/en/get-started/layered-web-application.md b/docs/en/get-started/layered-web-application.md
index c1e08fdb93..dc65e45829 100644
--- a/docs/en/get-started/layered-web-application.md
+++ b/docs/en/get-started/layered-web-application.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create a layered web application with ABP Framework using ABP Studio. Set up your environment and start building efficiently!"
+}
+```
+
# Get Started with ABP: Creating a Layered Web Application
````json
diff --git a/docs/en/get-started/maui.md b/docs/en/get-started/maui.md
index 21497fb2f7..6c189c8cba 100644
--- a/docs/en/get-started/maui.md
+++ b/docs/en/get-started/maui.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Create a minimalist MAUI app with the ABP Framework; easily set up your project and explore the solution structure for development."
+}
+```
+
# MAUI Application Startup Template
This template is used to create a minimalist MAUI application project.
diff --git a/docs/en/get-started/microservice.md b/docs/en/get-started/microservice.md
index c3d551a2a0..fb8626baef 100644
--- a/docs/en/get-started/microservice.md
+++ b/docs/en/get-started/microservice.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create a microservice solution with ABP Framework using ABP Studio. Set up your development environment and get started quickly!"
+}
+```
+
# Get Started with ABP: Creating a Microservice Solution
> You must have an ABP Business or a higher license to use this startup template.
diff --git a/docs/en/get-started/pre-requirements.md b/docs/en/get-started/pre-requirements.md
index 35dcf05ec9..8d3555fb99 100644
--- a/docs/en/get-started/pre-requirements.md
+++ b/docs/en/get-started/pre-requirements.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Prepare your development environment for ABP applications with essential prerequisites and IDE recommendations for .NET development."
+}
+```
+
# Prerequisites for Developing ABP Applications
This document will guide you through preparing your development environment for ABP based application development.
diff --git a/docs/en/get-started/single-layer-web-application.md b/docs/en/get-started/single-layer-web-application.md
index 630c2a9046..06c5ed90f9 100644
--- a/docs/en/get-started/single-layer-web-application.md
+++ b/docs/en/get-started/single-layer-web-application.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create a single layer web application with ABP Framework in this quick start guide. Set up your environment and get coding!"
+}
+```
+
# Get Started with ABP: Creating a Single Layer Web Application
````json
diff --git a/docs/en/get-started/wpf.md b/docs/en/get-started/wpf.md
index 287119986e..08251bae39 100644
--- a/docs/en/get-started/wpf.md
+++ b/docs/en/get-started/wpf.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to quickly set up a minimalist WPF application using the ABP Framework with this easy-to-follow template guide."
+}
+```
+
# WPF Application Startup Template
This template is used to create a minimalist WPF application project.
diff --git a/docs/en/guides/add-microservice.md b/docs/en/guides/add-microservice.md
index 512bdd8bd4..1efee159aa 100644
--- a/docs/en/guides/add-microservice.md
+++ b/docs/en/guides/add-microservice.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create new microservices in your ABP solution with step-by-step guidance, enhancing your understanding of microservice architecture."
+}
+```
+
# Add new Microservices to the Solution
````json
diff --git a/docs/en/guides/add-module-to-microservice.md b/docs/en/guides/add-module-to-microservice.md
index 903440fca3..bc9cfd12e4 100644
--- a/docs/en/guides/add-module-to-microservice.md
+++ b/docs/en/guides/add-module-to-microservice.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to seamlessly add a module to your existing microservice with ABP Framework, enhancing your project's capabilities effortlessly."
+}
+```
+
# Add Module to Existing Microservices
> This documentation introduces guidance for adding a module to a microservice for your microservice template project. Eventually, every module has its own documentation and implementation steps. However, some steps can be different for the microservice template. This guide will demonstrate the steps to add a module to an existing microservice.
diff --git a/docs/en/guides/asynchronous-interservice-communication.md b/docs/en/guides/asynchronous-interservice-communication.md
index 511ba7777c..634f56b391 100644
--- a/docs/en/guides/asynchronous-interservice-communication.md
+++ b/docs/en/guides/asynchronous-interservice-communication.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement asynchronous communication between microservices using event-based methods to improve decoupling and data consistency."
+}
+```
+
# Asynchronous Communication between Microservices
> This documentation introduces guidance for event based communication between microservices.
diff --git a/docs/en/guides/customizing-modules.md b/docs/en/guides/customizing-modules.md
index 86ef290ea2..d4dc7aec52 100644
--- a/docs/en/guides/customizing-modules.md
+++ b/docs/en/guides/customizing-modules.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to extend and customize ABP modules effectively with our comprehensive guide on module customization."
+}
+```
+
# Customizing the Modules
ABP [modules](../modules/index.md) are designed to be extensible and customizable. They fully implement the extensibility system that is defined by the ABP. See the **[Customizing the Application Modules](https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Guide)** guide to learn different ways of extending/customizing a module.
\ No newline at end of file
diff --git a/docs/en/guides/extracting-module-as-microservice.md b/docs/en/guides/extracting-module-as-microservice.md
index 943b585cc6..b80795a431 100644
--- a/docs/en/guides/extracting-module-as-microservice.md
+++ b/docs/en/guides/extracting-module-as-microservice.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to extract the Audit-Logging Management module into a standalone microservice with this comprehensive guide."
+}
+```
+
# Extracting a Module as a Microservice
````json
diff --git a/docs/en/guides/interservice-communication.md b/docs/en/guides/interservice-communication.md
index e1bbc89b31..5170d2a492 100644
--- a/docs/en/guides/interservice-communication.md
+++ b/docs/en/guides/interservice-communication.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn effective strategies for interservice communication in microservices, covering both synchronous and asynchronous messaging patterns."
+}
+```
+
# Communications Between Microservices
There are two basic messaging patterns for communication between two microservices:
diff --git a/docs/en/guides/microservice-mongodb.md b/docs/en/guides/microservice-mongodb.md
index 4c5042802b..2a918f4d3f 100644
--- a/docs/en/guides/microservice-mongodb.md
+++ b/docs/en/guides/microservice-mongodb.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to switch your ABP Microservice project to MongoDB, replacing EF Core references and updating dependencies for seamless integration."
+}
+```
+
# Change Microservice project to use MongoDB Provider
This guide explains how to change the Microservice project to use MongoDB as the database provider.
diff --git a/docs/en/guides/migrating-from-open-source.md b/docs/en/guides/migrating-from-open-source.md
index 35ba91df7a..1ea7b33bcd 100644
--- a/docs/en/guides/migrating-from-open-source.md
+++ b/docs/en/guides/migrating-from-open-source.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to seamlessly upgrade your ABP Framework projects from open-source templates to Pro modules using ABP Studio for enhanced features."
+}
+```
+
# Migrating from Open Source Templates
[ABP Studio](https://abp.io/studio) provides a way for the users who already started the development before purchasing a license to auto-upgrade their solutions with Pro modules. You can use this functionality through ABP Studio UI or ABP Studio CLI:
diff --git a/docs/en/guides/ms-multi-tenant-domain-resolving.md b/docs/en/guides/ms-multi-tenant-domain-resolving.md
index cb48a63905..7603491f56 100644
--- a/docs/en/guides/ms-multi-tenant-domain-resolving.md
+++ b/docs/en/guides/ms-multi-tenant-domain-resolving.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement multi-tenant domain resolving in your microservice solution with ABP Framework, using helm charts for Kubernetes deployment."
+}
+```
+
# Multi-tenant Domain Resolving in Microservice Solution
> This documentation introduces guidance for adding multi-tenant domain resolver to your microservice solution. This guide will use **mystore** as the main project name and you can simply replace it with your own project name to adept your solution. This guide will be using existing helm charts for deploying this solution on local kubernetes cluster with mystore domain name.
diff --git a/docs/en/guides/synchronous-interservice-communication.md b/docs/en/guides/synchronous-interservice-communication.md
index 6371d1c068..9d80c15223 100644
--- a/docs/en/guides/synchronous-interservice-communication.md
+++ b/docs/en/guides/synchronous-interservice-communication.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement synchronous HTTP communication between microservices, enhancing service interaction and efficiency in your applications."
+}
+```
+
# Synchronous Communication between Microservices
````json
diff --git a/docs/en/images/ai-management-workspaces.png b/docs/en/images/ai-management-workspaces.png
new file mode 100644
index 0000000000..8c47b76785
Binary files /dev/null and b/docs/en/images/ai-management-workspaces.png differ
diff --git a/docs/en/images/identity-pro-module-change-password.png b/docs/en/images/identity-pro-module-change-password.png
new file mode 100644
index 0000000000..3acff1c68a
Binary files /dev/null and b/docs/en/images/identity-pro-module-change-password.png differ
diff --git a/docs/en/images/identity-pro-module-password-history-settings.png b/docs/en/images/identity-pro-module-password-history-settings.png
new file mode 100644
index 0000000000..76b1e08799
Binary files /dev/null and b/docs/en/images/identity-pro-module-password-history-settings.png differ
diff --git a/docs/en/images/js-message-prompt.png b/docs/en/images/js-message-prompt.png
new file mode 100644
index 0000000000..631e9791af
Binary files /dev/null and b/docs/en/images/js-message-prompt.png differ
diff --git a/docs/en/images/penetration-test-report.md b/docs/en/images/penetration-test-report.md
index 54e006c243..3992c698ac 100644
--- a/docs/en/images/penetration-test-report.md
+++ b/docs/en/images/penetration-test-report.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Penetration Test Report detailing security findings, false positives, and actionable fixes for MVC v8.2.0 applications."
+}
+```
+
# ABP Penetration Test Report
The ABP Commercial MVC `v8.2.0` application template has been tested against security vulnerabilities by the [OWASP ZAP v2.14.0](https://www.zaproxy.org/) tool. The demo web application was started on the `https://localhost:44349` address. The below alerts have been reported by the pentest tool. These alerts are sorted by the risk level as high, medium, and low. The informational alerts are not mentioned in this document.
diff --git a/docs/en/index.md b/docs/en/index.md
index c65f9ab548..46b9923b57 100644
--- a/docs/en/index.md
+++ b/docs/en/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP documentation to build robust enterprise solutions with best practices, templates, and tools for .NET and ASP.NET Core."
+}
+```
+
# ABP Documentation
ABP offers an **opinionated architecture** to build enterprise software solutions with **best practices** on top of the **.NET** and the **ASP.NET Core** platforms. It provides the fundamental infrastructure, production-ready startup templates, pre-built application modules, UI themes, tooling, guides and documentation to implement that architecture properly and **automate the details** and repetitive works as much as possible.
diff --git a/docs/en/kb/can-not-login-with-admin-user.md b/docs/en/kb/can-not-login-with-admin-user.md
index 300a1a5c8f..0d2c2ca617 100644
--- a/docs/en/kb/can-not-login-with-admin-user.md
+++ b/docs/en/kb/can-not-login-with-admin-user.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Trouble logging in as admin? Follow these steps to reset access and ensure your database is properly configured."
+}
+```
+
# KB#0003: Cannot login with the admin user
## Use the Correct Username and Password
diff --git a/docs/en/kb/index.md b/docs/en/kb/index.md
index 5bbb201765..7c3f85f73f 100644
--- a/docs/en/kb/index.md
+++ b/docs/en/kb/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Knowledge Base for essential insights on common issues and best practices to enhance your development experience."
+}
+```
+
# ABP Knowledge Base
The following documents provide useful information about several topics you might need to know.
diff --git a/docs/en/kb/when-to-use-a-distributed-cache-server.md b/docs/en/kb/when-to-use-a-distributed-cache-server.md
index 27fced60a9..d88e3790c9 100644
--- a/docs/en/kb/when-to-use-a-distributed-cache-server.md
+++ b/docs/en/kb/when-to-use-a-distributed-cache-server.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn when to use a distributed cache server with ABP Framework to enhance performance in multi-instance and microservice applications."
+}
+```
+
# KB#0002: When to Use a Distributed Cache Server
ABP provides a [distributed cache service](../framework/fundamentals/caching.md) that is based on [ASP.NET Core's distributed cache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed). This document explains when you need to have a separate cache server for your applications.
diff --git a/docs/en/kb/windows-path-too-long-fix.md b/docs/en/kb/windows-path-too-long-fix.md
index 1486abd40f..7b7bbffc7e 100644
--- a/docs/en/kb/windows-path-too-long-fix.md
+++ b/docs/en/kb/windows-path-too-long-fix.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to fix the \"filename too long\" error on Windows by enabling long path options and resolving related .NET MAUI issues."
+}
+```
+
# KB#0001: How to Fix "Filename too long" Error on Windows
If you encounter the "filename too long" or "unzip" error on Windows, it's probably related to the Windows maximum file path limitation. Windows has a maximum file path limitation of 255 characters.
diff --git a/docs/en/modules/account-pro.md b/docs/en/modules/account-pro.md
index 594d51da62..62d7a00785 100644
--- a/docs/en/modules/account-pro.md
+++ b/docs/en/modules/account-pro.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Account Module (Pro) for ABP Framework, featuring user authentication, two-factor setup, and tenant switching functionalities."
+}
+```
+
# Account Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/account.md b/docs/en/modules/account.md
index a9532a9c36..3fc2c8e3aa 100644
--- a/docs/en/modules/account.md
+++ b/docs/en/modules/account.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Account Module for ABP Framework, featuring essential authentication functions like login, registration, and account management with advanced integration options."
+}
+```
+
# Account Module
Account module implements the basic authentication features like **login**, **register**, **forgot password** and **account management**.
diff --git a/docs/en/modules/account/authority-delegation.md b/docs/en/modules/account/authority-delegation.md
index fafe297677..7ac7cec18f 100644
--- a/docs/en/modules/account/authority-delegation.md
+++ b/docs/en/modules/account/authority-delegation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enable Authority Delegation in ABP Framework, allowing users to perform actions on behalf of others securely and efficiently."
+}
+```
+
# Authority Delegation
Authority Delegation is a way of delegating the responsibility of the current user to a different user(s) for a limited time. Thus, the user can switch to the delegated user's account and perform actions on their behalf.
diff --git a/docs/en/modules/account/impersonation.md b/docs/en/modules/account/impersonation.md
index e814a414b2..c6fdae0ebf 100644
--- a/docs/en/modules/account/impersonation.md
+++ b/docs/en/modules/account/impersonation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enable user impersonation in ABP Framework to perform actions on behalf of users securely, enhancing tenant management."
+}
+```
+
# Tenant impersonation & User impersonation
User impersonation allows you to temporarily sign in as a different user in your tenant's users. This article introduces how to enable impersonation in ABP. Impersonation is enabled by defautl in ABP v5.0 and above.
diff --git a/docs/en/modules/account/linkedaccounts.md b/docs/en/modules/account/linkedaccounts.md
index 9868215d77..1862a3d217 100644
--- a/docs/en/modules/account/linkedaccounts.md
+++ b/docs/en/modules/account/linkedaccounts.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to link multiple accounts for seamless navigation, enhancing user experience with ABP Framework's Linked Accounts feature."
+}
+```
+
# Linked Accounts
Linked accounts are used to link multiple accounts to each other. In this way, a user can easily navigate through his/her accounts using this feature.
diff --git a/docs/en/modules/account/session-management.md b/docs/en/modules/account/session-management.md
index 65a68bcb45..0d48842161 100644
--- a/docs/en/modules/account/session-management.md
+++ b/docs/en/modules/account/session-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage user sessions and prevent concurrent logins with the ABP Framework's Session Management feature."
+}
+```
+
# Session Management
Session Management feature allows you to prevent concurrent login and manage user sessions.
diff --git a/docs/en/modules/ai-management/index.md b/docs/en/modules/ai-management/index.md
new file mode 100644
index 0000000000..0d3abe18a0
--- /dev/null
+++ b/docs/en/modules/ai-management/index.md
@@ -0,0 +1,624 @@
+# AI Management (Pro)
+
+> You must have an ABP Team or a higher license to use this module.
+
+This module implements AI (Artificial Intelligence) management capabilities on top of the [Artificial Intelligence Workspaces](../../framework/infrastructure/artificial-intelligence.md) feature of the ABP Framework and allows to manage workspaces dynamically from the application including UI components and API endpoints.
+
+
+## How to Install
+
+AI Management module is not pre-installed in [the startup templates](../solution-templates/layered-web-application). You can install it using the ABP CLI or ABP Studio.
+
+**Using ABP CLI:**
+
+```bash
+abp add-module Volo.AIManagement
+```
+
+**Using ABP Studio:**
+
+Open ABP Studio, navigate to your solution explorer, **Right Click** on the project and select **Import Module**. Choose `Volo.AIManagement` from `NuGet` tab and check the "Install this Module" checkbox. Click the "OK" button to install the module.
+
+
+## Packages
+
+This module follows the [module development best practices guide](../../framework/architecture/best-practices) and consists of several NuGet and NPM packages. See the guide if you want to understand the packages and relations between them.
+
+You can visit [AI Management module package list page](https://abp.io/packages?moduleName=Volo.AIManagement) to see list of packages related with this module.
+
+AI Management module packages are designed for various usage scenarios. Packages are grouped by the usage scenario as `Volo.AIManagement.*` and `Volo.AIManagement.Client.*`. This structure helps to separate the use-cases clearly.
+
+## User Interface
+
+### Menu Items
+
+AI Management module adds the following items to the "Main" menu:
+
+* **AI Management**: Root menu item for AI Management module. (`AIManagement`)
+ * **Workspaces**: Workspace management page. (`AIManagement.Workspaces`)
+
+`AIManagementMenus` class has the constants for the menu item names.
+
+### Pages
+
+#### Workspace Management
+
+Workspaces page is used to manage AI workspaces in the system. You can create, edit, duplicate, and delete workspaces.
+
+
+
+You can create a new workspace or edit an existing workspace in this page. The workspace configuration includes:
+
+* **Name**: Unique identifier for the workspace (cannot contain spaces)
+* **Provider**: AI provider (OpenAI, Ollama, or custom providers)
+* **Model**: AI model name (e.g., gpt-4, mistral)
+* **API Key**: Authentication key (if required by provider)
+* **API Base URL**: Custom endpoint URL (optional)
+* **System Prompt**: Default system instructions
+* **Temperature**: Response randomness (0.0-1.0)
+* **Application Name**: Associate with specific application
+* **Required Permission**: Permission needed to use this workspace
+
+#### Chat Interface
+
+The AI Management module includes a built-in chat interface for testing workspaces. You can:
+
+* Select a workspace from available workspaces
+* Send messages and receive AI responses
+* Test streaming responses
+* Verify workspace configuration before using in production
+
+> Access the chat interface at: `/AIManagement/Chat`
+
+## Workspace Configuration
+
+Workspaces are the core concept of the AI Management module. A workspace represents an AI provider configuration that can be used throughout your application.
+
+### Workspace Properties
+
+When creating or managing a workspace, you can configure the following properties:
+
+| Property | Required | Description |
+|----------|----------|-------------|
+| `Name` | Yes | Unique workspace identifier (cannot contain spaces) |
+| `Provider` | Yes* | AI provider name (e.g., "OpenAI", "Ollama") |
+| `ModelName` | Yes* | Model identifier (e.g., "gpt-4", "mistral") |
+| `ApiKey` | No | API authentication key (required by some providers) |
+| `ApiBaseUrl` | No | Custom endpoint URL (defaults to provider's default) |
+| `SystemPrompt` | No | Default system prompt for all conversations |
+| `Temperature` | No | Response randomness (0.0-1.0, defaults to provider default) |
+| `Description` | No | Workspace description |
+| `IsActive` | No | Enable/disable the workspace (default: true) |
+| `ApplicationName` | No | Associate workspace with specific application |
+| `RequiredPermissionName` | No | Permission required to use this workspace |
+| `IsSystem` | No | Whether it's a system workspace (read-only) |
+| `OverrideSystemConfiguration` | No | Allow database configuration to override code-defined settings |
+
+**\*Not required for system workspaces**
+
+### System vs Dynamic Workspaces
+
+The AI Management module supports two types of workspaces:
+
+#### System Workspaces
+
+* **Defined in code** using `PreConfigure`
+* **Cannot be deleted** through the UI
+* **Read-only by default**, but can be overridden when `OverrideSystemConfiguration` is enabled
+* **Useful for** application-critical AI features that must always be available
+* **Created automatically** when the application starts
+
+Example:
+
+```csharp
+PreConfigure(options =>
+{
+ options.Workspaces.Configure(configuration =>
+ {
+ configuration.ConfigureChatClient(chatClientConfiguration =>
+ {
+ chatClientConfiguration.Builder = new ChatClientBuilder(
+ sp => new OpenAIClient(apiKey).GetChatClient("gpt-4")
+ );
+ });
+ });
+});
+```
+
+#### Dynamic Workspaces
+
+* **Created through the UI** or programmatically via `IWorkspaceRepository`
+* **Fully manageable** - can be created, updated, activated/deactivated, and deleted
+* **Stored in database** with all configuration
+* **Ideal for** user-customizable AI features
+
+Example (data seeding):
+
+```csharp
+var workspace = new Workspace(
+ name: "CustomerSupportWorkspace",
+ provider: "OpenAI",
+ modelName: "gpt-4",
+ apiKey: "your-api-key"
+);
+workspace.ApplicationName = ApplicationInfoAccessor.ApplicationName;
+workspace.SystemPrompt = "You are a helpful customer support assistant.";
+await _workspaceRepository.InsertAsync(workspace);
+```
+
+### Workspace Naming Rules
+
+* Workspace names **must be unique**
+* Workspace names **cannot contain spaces** (use underscores or camelCase)
+* Workspace names are **case-sensitive**
+
+## Permissions
+
+The AI Management module defines the following permissions:
+
+| Permission | Description | Default Granted To |
+|------------|-------------|-------------------|
+| `AIManagement.Workspaces` | View workspaces | Admin role |
+| `AIManagement.Workspaces.Create` | Create new workspaces | Admin role |
+| `AIManagement.Workspaces.Update` | Edit existing workspaces | Admin role |
+| `AIManagement.Workspaces.Delete` | Delete workspaces | Admin role |
+
+
+### Workspace-Level Permissions
+
+In addition to module-level permissions, you can restrict access to individual workspaces by setting the `RequiredPermissionName` property:
+
+```csharp
+var workspace = new Workspace(
+ name: "PremiumWorkspace",
+ provider: "OpenAI",
+ modelName: "gpt-4",
+ requiredPermissionName: "MyApp.PremiumFeatures"
+);
+```
+
+When a workspace has a required permission:
+* Only authorized users with that permission can access the workspace endpoints
+* Users without the permission will receive an authorization error
+
+## Usage Scenarios
+
+The AI Management module is designed to support various usage patterns, from simple standalone AI integration to complex microservice architectures. The module provides two main package groups to support different scenarios:
+
+- **`Volo.AIManagement.*`** packages for hosting AI Management with full database and management capabilities
+- **`Volo.AIManagement.Client.*`** packages for client applications that consume AI services
+
+### Scenario 1: No AI Management Dependency
+
+**Use this when:** You want to use AI in your application without any dependency on the AI Management module.
+
+In this scenario, you only use the ABP Framework's AI features directly. You configure AI providers (like OpenAI) in your code and don't need any database or management UI.
+
+**Required Packages:**
+- `Volo.Abp.AI`
+- Any Microsoft AI extensions (e.g., `Microsoft.Extensions.AI.OpenAI`)
+
+**Configuration:**
+
+```csharp
+public class YourModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ PreConfigure(options =>
+ {
+ options.Workspaces.ConfigureDefault(configuration =>
+ {
+ configuration.ConfigureChatClient(chatClientConfiguration =>
+ {
+ chatClientConfiguration.Builder = new ChatClientBuilder(
+ sp => new OpenAIClient(apiKey).GetChatClient("gpt-4")
+ );
+ });
+ });
+ });
+ }
+}
+```
+
+**Usage:**
+
+```csharp
+public class MyService
+{
+ private readonly IChatClient _chatClient;
+
+ public MyService(IChatClient chatClient)
+ {
+ _chatClient = chatClient;
+ }
+
+ public async Task GetResponseAsync(string prompt)
+ {
+ var response = await _chatClient.CompleteAsync(prompt);
+ return response.Message.Text;
+ }
+}
+```
+
+> See [Artificial Intelligence](../../framework/infrastructure/artificial-intelligence.md) documentation for more details about workspace configuration.
+
+### Scenario 2: AI Management with Domain Layer Dependency (Local Execution)
+
+**Use this when:** You want to host the full AI Management module inside your application with database storage and management UI.
+
+In this scenario, you install the AI Management module with its database layer, which allows you to manage AI workspaces dynamically through the UI or data seeding.
+
+**Required Packages:**
+
+**Minimum (backend only):**
+- `Volo.AIManagement.EntityFrameworkCore` (or `Volo.AIManagement.MongoDB`)
+- `Volo.AIManagement.OpenAI` (or another AI provider package)
+
+**Full installation (with UI and API):**
+- `Volo.AIManagement.EntityFrameworkCore` (or `Volo.AIManagement.MongoDB`)
+- `Volo.AIManagement.Application`
+- `Volo.AIManagement.HttpApi`
+- `Volo.AIManagement.Web` (for management UI)
+- `Volo.AIManagement.OpenAI` (or another AI provider package)
+
+> Note: `Volo.AIManagement.EntityFrameworkCore` transitively includes `Volo.AIManagement.Domain` and `Volo.Abp.AI.AIManagement` packages.
+
+**Workspace Definition Options:**
+
+**Option 1 - System Workspace (Code-based):**
+
+```csharp
+public class YourModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ PreConfigure(options =>
+ {
+ options.Workspaces.Configure(configuration =>
+ {
+ configuration.ConfigureChatClient(chatClientConfiguration =>
+ {
+ // Configuration will be populated from database
+ });
+ });
+ });
+ }
+}
+```
+
+**Option 2 - Dynamic Workspace (UI-based):**
+
+No code configuration needed. Define workspaces through:
+- The AI Management UI (navigate to AI Management > Workspaces)
+- Data seeding in your `DataSeeder` class
+
+**Using Chat Client:**
+
+```csharp
+public class MyService
+{
+ private readonly IChatClient _chatClient;
+
+ public MyService(IChatClient chatClient)
+ {
+ _chatClient = chatClient;
+ }
+}
+```
+
+### Scenario 3: AI Management Client with Remote Execution
+
+**Use this when:** You want to use AI capabilities without managing AI configuration yourself, and let a dedicated AI Management microservice handle everything.
+
+In this scenario, your application communicates with a separate AI Management microservice that manages configurations and communicates with AI providers on your behalf. The AI Management service handles all AI provider interactions.
+
+**Required Packages:**
+- `Volo.AIManagement.Client.HttpApi.Client`
+
+**Configuration:**
+
+Add the remote service endpoint in your `appsettings.json`:
+
+```json
+{
+ "RemoteServices": {
+ "AIManagementClient": {
+ "BaseUrl": "https://your-ai-management-service.com/"
+ }
+ }
+}
+```
+
+Optionally define workspace in your module:
+
+```csharp
+public class YourModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ PreConfigure(options =>
+ {
+ // Optional: Pre-define workspace type for type safety
+ options.Workspaces.Configure(configuration =>
+ {
+ // Configuration will be fetched from remote service
+ });
+ });
+ }
+}
+```
+
+**Usage:**
+
+```csharp
+public class MyService
+{
+ private readonly IChatCompletionClientAppService _chatService;
+
+ public MyService(IChatCompletionClientAppService chatService)
+ {
+ _chatService = chatService;
+ }
+
+ public async Task GetAIResponseAsync(string workspaceName, string prompt)
+ {
+ var request = new ChatClientCompletionRequestDto
+ {
+ Messages = new List
+ {
+ new ChatMessageDto { Role = "user", Content = prompt }
+ }
+ };
+
+ var response = await _chatService.ChatCompletionsAsync(workspaceName, request);
+ return response.Content;
+ }
+
+ // For streaming responses
+ public async IAsyncEnumerable StreamAIResponseAsync(string workspaceName, string prompt)
+ {
+ var request = new ChatClientCompletionRequestDto
+ {
+ Messages = new List
+ {
+ new ChatMessageDto { Role = "user", Content = prompt }
+ }
+ };
+
+ await foreach (var update in _chatService.StreamChatCompletionsAsync(workspaceName, request))
+ {
+ yield return update.Content;
+ }
+ }
+}
+```
+
+### Scenario 4: Exposing Client HTTP Endpoints (Proxy Pattern)
+
+**Use this when:** You want your application to act as a proxy/API gateway, exposing AI capabilities to other services or client applications.
+
+This scenario builds on Scenario 3, but your application exposes its own HTTP endpoints that other applications can call. Your application then forwards these requests to the AI Management service.
+
+**Required Packages:**
+- `Volo.AIManagement.Client.HttpApi.Client` (to communicate with AI Management service)
+- `Volo.AIManagement.Client.Application` (application services)
+- `Volo.AIManagement.Client.HttpApi` (to expose HTTP endpoints)
+- `Volo.AIManagement.Client.Web` (optional, for UI components)
+
+**Configuration:**
+
+Same as Scenario 3, configure the remote AI Management service in `appsettings.json`.
+
+**Usage:**
+
+Once configured, other applications can call your application's endpoints:
+- `POST /api/ai-management-client/chat-completion` for chat completions
+- `POST /api/ai-management-client/stream-chat-completion` for streaming responses
+
+Your application acts as a proxy, forwarding these requests to the AI Management microservice.
+
+## Comparison Table
+
+| Scenario | Database Required | Manages Config | Executes AI | Exposes API | Use Case |
+|----------|------------------|----------------|-------------|-------------|----------|
+| **1. No AI Management** | No | Code | Local | Optional | Simple apps, no config management needed |
+| **2. Full AI Management** | Yes | Database/UI | Local | Optional | Monoliths, services managing their own AI |
+| **3. Client Remote** | No | Remote Service | Remote Service | No | Microservices consuming AI centrally |
+| **4. Client Proxy** | No | Remote Service | Remote Service | Yes | API Gateway pattern, proxy services |
+
+## Implementing Custom AI Provider Factories
+
+While the AI Management module provides built-in support for OpenAI through the `Volo.AIManagement.OpenAI` package, you can easily add support for other AI providers by implementing a custom `IChatClientFactory`.
+
+### Understanding the Factory Pattern
+
+The AI Management module uses a factory pattern to create `IChatClient` instances based on the provider configuration stored in the database. Each provider (OpenAI, Ollama, Azure OpenAI, etc.) needs its own factory implementation.
+
+### Creating a Custom Factory
+
+Here's how to implement a factory for Ollama as an example:
+
+#### Step 1: Install the Provider's NuGet Package
+
+First, install the AI provider's package. For Ollama:
+
+```bash
+dotnet add package OllamaSharp
+```
+
+#### Step 2: Implement the `IChatClientFactory` Interface
+
+Create a factory class that implements `IChatClientFactory`:
+
+```csharp
+using Microsoft.Extensions.AI;
+using OllamaSharp;
+using Volo.AIManagement.Factory;
+using Volo.Abp.DependencyInjection;
+
+namespace YourNamespace;
+
+public class OllamaChatClientFactory : IChatClientFactory, ITransientDependency
+{
+ public string Provider => "Ollama";
+
+ public Task CreateAsync(ChatClientCreationConfiguration configuration)
+ {
+ // Create the Ollama client with configuration from database
+ var client = new OllamaApiClient(
+ configuration.ApiBaseUrl ?? "http://localhost:11434",
+ configuration.ModelName
+ );
+
+ // Return as IChatClient
+ return Task.FromResult(client);
+ }
+}
+```
+
+#### Step 3: Register the Factory
+
+Register your factory in your module's `ConfigureServices` method:
+
+```csharp
+public override void ConfigureServices(ServiceConfigurationContext context)
+{
+ Configure(options =>
+ {
+ options.AddFactory("Ollama");
+ });
+}
+```
+
+> [!TIP]
+> For production scenarios, you may want to add validation for the factory configuration.
+
+
+### Available Configuration Properties
+
+The `ChatClientCreationConfiguration` object provides the following properties from the database:
+
+| Property | Type | Description |
+|----------|------|-------------|
+| `Name` | string | Workspace name |
+| `Provider` | string | Provider name (e.g., "OpenAI", "Ollama") |
+| `ApiKey` | string? | API key for authentication |
+| `ModelName` | string | Model identifier (e.g., "gpt-4", "mistral") |
+| `SystemPrompt` | string? | Default system prompt for the workspace |
+| `Temperature` | float? | Temperature setting for response generation |
+| `ApiBaseUrl` | string? | Custom API endpoint URL |
+| `Description` | string? | Workspace description |
+| `IsActive` | bool | Whether the workspace is active |
+| `IsSystem` | bool | Whether it's a system workspace |
+| `RequiredPermissionName` | string? | Permission required to use this workspace |
+
+### Example: Azure OpenAI Factory
+
+Here's an example of implementing a factory for Azure OpenAI:
+
+```csharp
+using Azure.AI.OpenAI;
+using Azure;
+using Microsoft.Extensions.AI;
+using Volo.AIManagement.Factory;
+using Volo.Abp.DependencyInjection;
+
+namespace YourNamespace;
+
+public class AzureOpenAIChatClientFactory : IChatClientFactory, ITransientDependency
+{
+ public string Provider => "AzureOpenAI";
+
+ public Task CreateAsync(ChatClientCreationConfiguration configuration)
+ {
+ var client = new AzureOpenAIClient(
+ new Uri(configuration.ApiBaseUrl ?? throw new ArgumentNullException(nameof(configuration.ApiBaseUrl))),
+ new AzureKeyCredential(configuration.ApiKey ?? throw new ArgumentNullException(nameof(configuration.ApiKey)))
+ );
+
+ var chatClient = client.GetChatClient(configuration.ModelName);
+ return Task.FromResult(chatClient.AsIChatClient());
+ }
+}
+```
+
+### Using Your Custom Provider
+
+After implementing and registering your factory:
+
+1. **Through UI**: Navigate to the AI Management workspaces page and create a new workspace:
+ - Select your provider name (e.g., "Ollama", "AzureOpenAI")
+ - Configure the API settings
+ - Set the model name
+
+2. **Through Code** (data seeding):
+
+```csharp
+await _workspaceRepository.InsertAsync(new Workspace(
+ GuidGenerator.Create(),
+ "MyOllamaWorkspace",
+ provider: "Ollama",
+ modelName: "mistral",
+ apiBaseUrl: "http://localhost:11434",
+ description: "Local Ollama workspace"
+));
+```
+
+> **Tip**: The provider name you use in `AddFactory("ProviderName")` must match the provider name stored in the workspace configuration in the database.
+
+## Internals
+
+### Domain Layer
+
+The AI Management module follows Domain-Driven Design principles and has a well-structured domain layer.
+
+#### Aggregates
+
+- **Workspace**: The main aggregate root representing an AI workspace configuration.
+
+#### Repositories
+
+The following custom repositories are defined:
+
+- `IWorkspaceRepository`: Repository for workspace management with custom queries.
+
+#### Domain Services
+
+- `ApplicationWorkspaceManager`: Manages workspace operations and validations.
+- `WorkspaceConfigurationStore`: Retrieves workspace configuration with caching.
+- `ChatClientResolver`: Resolves the appropriate `IChatClient` implementation for a workspace.
+
+#### Integration Services
+
+The module exposes the following integration services for inter-service communication:
+
+- `IAIChatCompletionIntegrationService`: Executes AI chat completions remotely.
+- `IWorkspaceConfigurationIntegrationService`: Retrieves workspace configuration for remote setup.
+- `IWorkspaceIntegrationService`: Manages workspaces remotely.
+
+> Integration services are exposed at `/integration-api` prefix and marked with `[IntegrationService]` attribute.
+
+### Application Layer
+
+#### Application Services
+
+- `WorkspaceAppService`: CRUD operations for workspace management.
+- `ChatCompletionClientAppService`: Client-side chat completion services.
+- `AIChatCompletionIntegrationService`: Integration service for remote AI execution.
+
+### Caching
+
+Workspace configurations are cached for performance. The cache key format:
+
+```
+WorkspaceConfiguration:{ApplicationName}:{WorkspaceName}
+```
+
+The cache is automatically invalidated when workspaces are created, updated, or deleted.
+
+## See Also
+
+- [Artificial Intelligence Infrastructure](../../framework/infrastructure/artificial-intelligence.md): Learn about the underlying AI workspace infrastructure
+- [Microsoft.Extensions.AI](https://learn.microsoft.com/en-us/dotnet/ai/): Microsoft's unified AI abstractions
+- [Semantic Kernel](https://learn.microsoft.com/en-us/semantic-kernel/): Microsoft's Semantic Kernel integration
\ No newline at end of file
diff --git a/docs/en/modules/audit-logging-pro.md b/docs/en/modules/audit-logging-pro.md
index 607d67539c..20f220857c 100644
--- a/docs/en/modules/audit-logging-pro.md
+++ b/docs/en/modules/audit-logging-pro.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the ABP Framework's Audit Logging Module (Pro) to track changes, filter logs, and enhance application monitoring efficiently."
+}
+```
+
# Audit Logging Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/audit-logging.md b/docs/en/modules/audit-logging.md
index e47b0ce39e..5cba52cf34 100644
--- a/docs/en/modules/audit-logging.md
+++ b/docs/en/modules/audit-logging.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement the Audit Logging Module in ABP Framework to efficiently save and manage audit logs in your database."
+}
+```
+
# Audit Logging Module
The Audit Logging Module basically implements the `IAuditingStore` to save the audit log objects to a database.
diff --git a/docs/en/modules/background-jobs.md b/docs/en/modules/background-jobs.md
index 1ccc6a9394..971284b7c9 100644
--- a/docs/en/modules/background-jobs.md
+++ b/docs/en/modules/background-jobs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and manage background jobs in the ABP Framework with this guide on the Background Jobs module, including installation and source code access."
+}
+```
+
# Background Jobs Module
The Background Jobs module implements the `IBackgroundJobStore` interface and makes possible to use the default background job manager of the ABP. If you don't want to use this module, then you should implement the `IBackgroundJobStore` interface yourself.
diff --git a/docs/en/modules/chat.md b/docs/en/modules/chat.md
index 42379b29bc..b6932149fb 100644
--- a/docs/en/modules/chat.md
+++ b/docs/en/modules/chat.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement real-time messaging in your application with the ABP Chat Module. Installation made easy via ABP Suite or CLI."
+}
+```
+
# Chat Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/cms-kit-pro/contact-form.md b/docs/en/modules/cms-kit-pro/contact-form.md
index fcfa4a2582..6cdb08a569 100644
--- a/docs/en/modules/cms-kit-pro/contact-form.md
+++ b/docs/en/modules/cms-kit-pro/contact-form.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to enable and utilize the CMS Kit Pro contact form widget for efficient contact management on your website with ABP Framework."
+}
+```
+
# CMS Kit Pro: Contact Management
> You must have an ABP Team or a higher license to use CMS Kit Pro module's features.
diff --git a/docs/en/modules/cms-kit-pro/faq.md b/docs/en/modules/cms-kit-pro/faq.md
index a153b3fee5..78ec252d17 100644
--- a/docs/en/modules/cms-kit-pro/faq.md
+++ b/docs/en/modules/cms-kit-pro/faq.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement and manage the FAQ system in CMS Kit Pro, including enabling features and customizing the user interface."
+}
+```
+
# CMS Kit Pro: FAQ System
> You must have an ABP Team or a higher license to use CMS Kit Pro module's features.
diff --git a/docs/en/modules/cms-kit-pro/index.md b/docs/en/modules/cms-kit-pro/index.md
index 332b9dddc2..8a29db2d63 100644
--- a/docs/en/modules/cms-kit-pro/index.md
+++ b/docs/en/modules/cms-kit-pro/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Enhance your application with the CMS Kit Module (Pro) for advanced content management, including dynamic pages, blogging, and user interactions."
+}
+```
+
# CMS Kit Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/cms-kit-pro/newsletter.md b/docs/en/modules/cms-kit-pro/newsletter.md
index b55ac23d04..84cc2ee34c 100644
--- a/docs/en/modules/cms-kit-pro/newsletter.md
+++ b/docs/en/modules/cms-kit-pro/newsletter.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to enable and manage the newsletter system in CMS Kit Pro, enhancing user engagement with subscription features."
+}
+```
+
# CMS Kit Pro: Newsletter System
> You must have an ABP Team or a higher license to use CMS Kit Pro module's features.
diff --git a/docs/en/modules/cms-kit-pro/page-feedback.md b/docs/en/modules/cms-kit-pro/page-feedback.md
index dd519eb15b..ac2278d893 100644
--- a/docs/en/modules/cms-kit-pro/page-feedback.md
+++ b/docs/en/modules/cms-kit-pro/page-feedback.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement the Page Feedback system in CMS Kit Pro, enabling user feedback collection with ease for enhanced engagement."
+}
+```
+
# CMS Kit Pro: Page Feedback System
> You must have an ABP Team or a higher license to use CMS Kit Pro module's features.
diff --git a/docs/en/modules/cms-kit-pro/poll.md b/docs/en/modules/cms-kit-pro/poll.md
index ed60964edc..f10baf080e 100644
--- a/docs/en/modules/cms-kit-pro/poll.md
+++ b/docs/en/modules/cms-kit-pro/poll.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement and manage a poll system in CMS Kit Pro, enabling user engagement with easy setup and customization features."
+}
+```
+
# CMS Kit Pro: Poll System
> You must have an ABP Team or a higher license to use CMS Kit Pro module's features.
diff --git a/docs/en/modules/cms-kit-pro/url-forwarding.md b/docs/en/modules/cms-kit-pro/url-forwarding.md
index 10ca0a7f98..cd164ebba0 100644
--- a/docs/en/modules/cms-kit-pro/url-forwarding.md
+++ b/docs/en/modules/cms-kit-pro/url-forwarding.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enable and use the URL forwarding system in CMS Kit Pro for seamless redirection of pages and external links."
+}
+```
+
# CMS Kit Pro: URL Forwarding System
> You must have an ABP Team or a higher license to use CMS Kit Pro module's features.
diff --git a/docs/en/modules/cms-kit/blogging.md b/docs/en/modules/cms-kit/blogging.md
index 0ccfd7b2fa..90356a59fe 100644
--- a/docs/en/modules/cms-kit/blogging.md
+++ b/docs/en/modules/cms-kit/blogging.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to enable and manage the blogging feature in the CMS Kit, including UI elements for blogs and blog posts."
+}
+```
+
# CMS Kit: Blogging
The blogging feature provides the necessary UI to manage and render blogs and blog posts.
diff --git a/docs/en/modules/cms-kit/comments.md b/docs/en/modules/cms-kit/comments.md
index 8ff8ff5ba8..0070b5a2a9 100644
--- a/docs/en/modules/cms-kit/comments.md
+++ b/docs/en/modules/cms-kit/comments.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enable and configure the CMS Kit's comment system for various resources like blog posts and products efficiently."
+}
+```
+
# CMS Kit: Comments
CMS Kit provides a **comment** system to add the comment feature to any kind of resource, like blog posts, products, etc.
diff --git a/docs/en/modules/cms-kit/dynamic-widget.md b/docs/en/modules/cms-kit/dynamic-widget.md
index f8f5df9822..8644f7cd63 100644
--- a/docs/en/modules/cms-kit/dynamic-widget.md
+++ b/docs/en/modules/cms-kit/dynamic-widget.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the CMS Kit's dynamic widget feature to seamlessly integrate custom components into your pages and blog posts."
+}
+```
+
# CMS Kit: Dynamic Widget
CMS Kit provides a dynamic [widget](../../framework/ui/mvc-razor-pages/widgets.md) used to render the components previously developed by the software in the content of the pages and blog posts. Its means, that in static content you can use dynamic content. We will mention how you can do it. You have two choices to define the widget in the system: Writing and UI.
diff --git a/docs/en/modules/cms-kit/global-resources.md b/docs/en/modules/cms-kit/global-resources.md
index 7a6981c964..ff02351be8 100644
--- a/docs/en/modules/cms-kit/global-resources.md
+++ b/docs/en/modules/cms-kit/global-resources.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to dynamically manage global styles and scripts in CMS Kit, enabling features for seamless development with ABP Framework."
+}
+```
+
# CMS Kit: Global Resources
CMS Kit Global Resources system allows to add global styles and scripts dynamically.
diff --git a/docs/en/modules/cms-kit/index.md b/docs/en/modules/cms-kit/index.md
index 3744ce3590..630540fde9 100644
--- a/docs/en/modules/cms-kit/index.md
+++ b/docs/en/modules/cms-kit/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the CMS Kit Module, offering essential tools for building dynamic websites with page management, blogging, and tagging features."
+}
+```
+
# CMS Kit Module
This module provides CMS (Content Management System) capabilities for your application. It provides **core building blocks** and fully working **sub-systems** to create your own website with CMS features enabled, or use the building blocks in your web sites with any purpose.
diff --git a/docs/en/modules/cms-kit/marked-items.md b/docs/en/modules/cms-kit/marked-items.md
index 05b9dd9e06..bd0db306eb 100644
--- a/docs/en/modules/cms-kit/marked-items.md
+++ b/docs/en/modules/cms-kit/marked-items.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement and customize a marking system for your resources in the CMS Kit, enhancing user engagement effortlessly."
+}
+```
+
# CMS Kit: Marked Item System
CMS kit provides a marking system to mark any kind of resource, like a blog post or a product, as a favorite, starred, flagged, or bookmarked.
diff --git a/docs/en/modules/cms-kit/menus.md b/docs/en/modules/cms-kit/menus.md
index d9ece26d21..429e9226e6 100644
--- a/docs/en/modules/cms-kit/menus.md
+++ b/docs/en/modules/cms-kit/menus.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Manage public menus dynamically with the CMS Kit Menu system. Learn how to enable features and navigate the user interface for effective menu management."
+}
+```
+
# CMS Kit: Menus
CMS Kit Menu system allows to manage public menus dynamically.
diff --git a/docs/en/modules/cms-kit/pages.md b/docs/en/modules/cms-kit/pages.md
index 3e4671e6a2..b2f428d9cd 100644
--- a/docs/en/modules/cms-kit/pages.md
+++ b/docs/en/modules/cms-kit/pages.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enable and manage dynamic pages in the CMS Kit, enhancing your ABP Framework applications with customizable content features."
+}
+```
+
# CMS Kit: Pages
CMS Kit Page system allows you to create dynamic pages by specifying URLs, which is the fundamental feature of a CMS.
diff --git a/docs/en/modules/cms-kit/ratings.md b/docs/en/modules/cms-kit/ratings.md
index 8e7724d679..492af1c803 100644
--- a/docs/en/modules/cms-kit/ratings.md
+++ b/docs/en/modules/cms-kit/ratings.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement and manage a flexible rating system in CMS Kit, perfect for enhancing user engagement on your resources."
+}
+```
+
# CMS Kit: Rating System
CMS Kit provides a **rating** system to to add ratings feature to any kind of resource like blog posts, comments, etc. Here how the rating component looks like on a sample page:
diff --git a/docs/en/modules/cms-kit/reactions.md b/docs/en/modules/cms-kit/reactions.md
index 4f23c73647..1db865e287 100644
--- a/docs/en/modules/cms-kit/reactions.md
+++ b/docs/en/modules/cms-kit/reactions.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and customize a reaction system in CMS Kit for engaging user interactions on your resources."
+}
+```
+
# CMS Kit: Reaction System
CMS Kit provides a **reaction** system to add reactions feature to any kind of resource, like blog posts or comments.
diff --git a/docs/en/modules/cms-kit/tags.md b/docs/en/modules/cms-kit/tags.md
index fffcf27473..7b57a49b9b 100644
--- a/docs/en/modules/cms-kit/tags.md
+++ b/docs/en/modules/cms-kit/tags.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage tags in CMS Kit, enabling you to categorize resources like blog posts and products effectively."
+}
+```
+
# CMS Kit: Tag Management
CMS Kit provides a **tag** system to tag any kind of resources, like a blog post.
diff --git a/docs/en/modules/database-tables.md b/docs/en/modules/database-tables.md
index ad8c66d684..1f79a496f6 100644
--- a/docs/en/modules/database-tables.md
+++ b/docs/en/modules/database-tables.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the database tables in the ABP Framework, detailing their purposes and relationships for effective auditing and entity tracking."
+}
+```
+
# Database Tables
This documentation describes all database tables and their purposes. You can read this documentation to get general knowledge of the database tables that come from each module.
diff --git a/docs/en/modules/docs.md b/docs/en/modules/docs.md
index 414766645d..bfb959f128 100644
--- a/docs/en/modules/docs.md
+++ b/docs/en/modules/docs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the ABP Docs Module for easy software documentation management, supporting GitHub integration and versioning for streamlined workflows."
+}
+```
+
# Docs Module
## What is Docs Module?
diff --git a/docs/en/modules/elsa-pro.md b/docs/en/modules/elsa-pro.md
index a3181b20b8..3a6ec4533b 100644
--- a/docs/en/modules/elsa-pro.md
+++ b/docs/en/modules/elsa-pro.md
@@ -131,4 +131,4 @@ After that, Elsa Studio will redirect to your ABP application's login page, then
### Elsa Workflows - Sample Workflow Demo
-ABP provides a complete demo application that shows how to use the Elsa module in your ABP application. You can download the demo application and see the integration points, if you stuck at any point. Please see the [Elsa Workflows - Sample Workflow Demo](../samples/elsa-workflows.md) page for more information.
+ABP provides a complete demo application that shows how to use the Elsa module in your ABP application. You can download the demo application and see the integration points, if you stuck at any point. Please see the [Elsa Workflows - Sample Workflow Demo](../samples/elsa-workflows-demo.md) page for more information.
diff --git a/docs/en/modules/feature-management.md b/docs/en/modules/feature-management.md
index 0757ab52e4..300b232f93 100644
--- a/docs/en/modules/feature-management.md
+++ b/docs/en/modules/feature-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and manage feature flags in your application using the ABP Framework's Feature Management module, with installation and customization options."
+}
+```
+
# Feature Management Module
The Feature Management module implements the `IFeatureManagementStore` interface defined by the [Feature System](../framework/infrastructure/features.md).
diff --git a/docs/en/modules/file-management.md b/docs/en/modules/file-management.md
index 19658de254..5725af4297 100644
--- a/docs/en/modules/file-management.md
+++ b/docs/en/modules/file-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the File Management Module for ABP Framework, enabling efficient file uploads, downloads, and organization with multi-tenancy support."
+}
+```
+
# File Management Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/forms.md b/docs/en/modules/forms.md
index ab50bded64..f903cc471b 100644
--- a/docs/en/modules/forms.md
+++ b/docs/en/modules/forms.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "The Forms Module (Pro) enables easy creation and management of questionnaires, allowing data collection, export to CSV, and sharing via unique links."
+}
+```
+
# Forms Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/gdpr.md b/docs/en/modules/gdpr.md
index 43e38eb6b2..f797a3b713 100644
--- a/docs/en/modules/gdpr.md
+++ b/docs/en/modules/gdpr.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage user data with the GDPR module, enabling personal data downloads and deletions in your ABP applications."
+}
+```
+
# GDPR Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/identity-pro.md b/docs/en/modules/identity-pro.md
index 6649a335e3..f23b9e801a 100644
--- a/docs/en/modules/identity-pro.md
+++ b/docs/en/modules/identity-pro.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Identity Module (Pro) for ABP Framework, enabling robust user and role management, permissions, and authentication features."
+}
+```
+
# Identity Module (Pro)
> You must have an ABP Team or a higher license to use this module.
@@ -431,4 +438,5 @@ This module doesn't define any additional distributed event. See the [standard d
* [OAuth Login](./identity/oauth-login.md)
* [Periodic Password Change (Password Aging)](./identity/periodic-password-change.md)
* [Two Factor Authentication](./identity/two-factor-authentication.md)
-* [Session Management](./identity/session-management.md)
\ No newline at end of file
+* [Session Management](./identity/session-management.md)
+* [Password History](./identity/password-history.md)
diff --git a/docs/en/modules/identity-server-pro.md b/docs/en/modules/identity-server-pro.md
index ad197e8a7d..66e16fcb71 100644
--- a/docs/en/modules/identity-server-pro.md
+++ b/docs/en/modules/identity-server-pro.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Identity Server Module (Pro) for ABP Framework, enabling easy management of clients, identity resources, and API resources."
+}
+```
+
# Identity Server Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/identity-server.md b/docs/en/modules/identity-server.md
index a13dcc2f57..5df207a17b 100644
--- a/docs/en/modules/identity-server.md
+++ b/docs/en/modules/identity-server.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the IdentityServer module for ABP Framework, enabling advanced authentication features with seamless integration and database support."
+}
+```
+
# IdentityServer Module
IdentityServer module provides a full integration with the [IdentityServer4](https://github.com/IdentityServer/IdentityServer4) (IDS) framework, which provides advanced authentication features like single sign-on and API access control. This module persists clients, resources and other IDS-related objects to database. **This module is replaced by** [OpenIddict module](./openiddict.md) after ABP v6.0 in the startup templates.
diff --git a/docs/en/modules/identity.md b/docs/en/modules/identity.md
index 46c6a671c1..8d800fe131 100644
--- a/docs/en/modules/identity.md
+++ b/docs/en/modules/identity.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Identity Management Module for the ABP Framework to efficiently manage user roles, permissions, and authentication with customizable UI options."
+}
+```
+
# Identity Management Module
Identity module is used to manage roles, users and their permissions, based on the [Microsoft Identity library](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity).
diff --git a/docs/en/modules/identity/idap.md b/docs/en/modules/identity/idap.md
index e25367f1c1..cf4c8fbcaa 100644
--- a/docs/en/modules/identity/idap.md
+++ b/docs/en/modules/identity/idap.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement LDAP authentication with ABP Framework's LdapExternalLoginProvider, enhancing external login capabilities for your applications."
+}
+```
+
# LDAP External Login Provider
## Introduction
diff --git a/docs/en/modules/identity/import-external-users.md b/docs/en/modules/identity/import-external-users.md
index e547dd6860..562515ceee 100644
--- a/docs/en/modules/identity/import-external-users.md
+++ b/docs/en/modules/identity/import-external-users.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to import external users into the ABP Framework using LDAP or OAuth providers with our step-by-step guide."
+}
+```
+
# Import External Users
## Introduction
diff --git a/docs/en/modules/identity/oauth-login.md b/docs/en/modules/identity/oauth-login.md
index 474167a95b..f628ec8c7b 100644
--- a/docs/en/modules/identity/oauth-login.md
+++ b/docs/en/modules/identity/oauth-login.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enable OAuth Resource Owner Password authentication for external logins in the ABP Framework's Identity PRO module."
+}
+```
+
# OAuth Resource Owner Password (ROP) External login Provider
## Introduction
diff --git a/docs/en/modules/identity/password-history.md b/docs/en/modules/identity/password-history.md
new file mode 100644
index 0000000000..e28d78fe0e
--- /dev/null
+++ b/docs/en/modules/identity/password-history.md
@@ -0,0 +1,20 @@
+# Password History
+
+## Introduction
+
+> You must have an ABP Team or a higher license to use this module & its features.
+
+The Identity PRO module has a built-in password history function that allows you to enforce password reuse policies for users within your application. It keeps track of users’ previously used passwords and checks this history whenever a user attempts to change their password. This prevents users from setting a password that they have already used in the past, ensuring that each new password is unique and not a repetition of an older one.
+
+## Password History Settings
+
+You need to enable the password history and configure related settings:
+
+
+
+* **Enable prevent password reuse**: Whether to prevent users from reusing their previous passwords.
+* **Password change period**: The number of previous passwords that cannot be reused.
+
+When you enable the password history, users and administrators will not be able to reuse their previous passwords when changing/resetting their passwords.
+
+
diff --git a/docs/en/modules/identity/periodic-password-change.md b/docs/en/modules/identity/periodic-password-change.md
index 3134649394..4367ee88bb 100644
--- a/docs/en/modules/identity/periodic-password-change.md
+++ b/docs/en/modules/identity/periodic-password-change.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure periodic password changes with the ABP Identity PRO module, ensuring enhanced security for your users."
+}
+```
+
# Periodic Password Change (Password Aging)
## Introduction
diff --git a/docs/en/modules/identity/session-management.md b/docs/en/modules/identity/session-management.md
index e911146081..4a323553e2 100644
--- a/docs/en/modules/identity/session-management.md
+++ b/docs/en/modules/identity/session-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage user sessions and prevent concurrent logins in the ABP Framework with flexible settings for enhanced security."
+}
+```
+
# Session Management
The Session Management feature allows you to prevent concurrent login and manage user sessions.
diff --git a/docs/en/modules/identity/two-factor-authentication.md b/docs/en/modules/identity/two-factor-authentication.md
index 3aa9c5e454..2acab6ec53 100644
--- a/docs/en/modules/identity/two-factor-authentication.md
+++ b/docs/en/modules/identity/two-factor-authentication.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement two-factor authentication in ABP Framework to enhance security for users and protect against unauthorized access."
+}
+```
+
# Two Factor Authentication
> You must have an ABP Team or a higher license to use this module & its features.
diff --git a/docs/en/modules/index.md b/docs/en/modules/index.md
index 105f60274e..5ab619698a 100644
--- a/docs/en/modules/index.md
+++ b/docs/en/modules/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's modular framework for building applications with core and business functionalities, simplifying development with rich infrastructure."
+}
+```
+
# Application Modules
ABP is a **modular application framework** which consists of dozens of **NuGet & NPM packages**. It also provides a complete infrastructure to build your own application modules which may have entities, services, database integration, APIs, UI components and so on.
diff --git a/docs/en/modules/language-management.md b/docs/en/modules/language-management.md
index 536abc7ab3..8ac9e6088e 100644
--- a/docs/en/modules/language-management.md
+++ b/docs/en/modules/language-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to manage languages, translate UI texts, and set defaults effortlessly with the ABP Framework's Language Management Module (Pro)."
+}
+```
+
# Language Management Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/openiddict-pro.md b/docs/en/modules/openiddict-pro.md
index b70cd83ac2..5b681f6461 100644
--- a/docs/en/modules/openiddict-pro.md
+++ b/docs/en/modules/openiddict-pro.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the OpenIddict Module (Pro) for ABP Framework to manage applications, API scopes, and client permissions seamlessly."
+}
+```
+
# OpenIddict Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/openiddict.md b/docs/en/modules/openiddict.md
index 35c5220096..c17b8200d2 100644
--- a/docs/en/modules/openiddict.md
+++ b/docs/en/modules/openiddict.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP OpenIddict Module for seamless authentication, including SSO and API access control. Easily integrate and customize for your needs."
+}
+```
+
# ABP OpenIddict Module
OpenIddict module provides an integration with the [OpenIddict](https://github.com/openiddict/openiddict-core) which provides advanced authentication features like single sign-on, single log-out, and API access control. This module persists applications, scopes, and other OpenIddict-related objects to the database.
diff --git a/docs/en/modules/payment-custom-gateway.md b/docs/en/modules/payment-custom-gateway.md
index cdf847b528..a17a225e09 100644
--- a/docs/en/modules/payment-custom-gateway.md
+++ b/docs/en/modules/payment-custom-gateway.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create a custom payment gateway in ABP Framework, enhancing your application's payment flexibility and integration."
+}
+```
+
# Creating a Custom Payment Gateway
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/payment.md b/docs/en/modules/payment.md
index 6a55cc83ae..b0d976b758 100644
--- a/docs/en/modules/payment.md
+++ b/docs/en/modules/payment.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Integrate payment gateways seamlessly with the ABP Payment Module, supporting multiple options like Stripe and PayPal for one-time and recurring payments."
+}
+```
+
# Payment Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/permission-management.md b/docs/en/modules/permission-management.md
index 2368768fe6..85cefffe7d 100644
--- a/docs/en/modules/permission-management.md
+++ b/docs/en/modules/permission-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage permissions in your application using the ABP Framework's Permission Management Module, including installation and source code access."
+}
+```
+
# Permission Management Module
This module implements the `IPermissionStore` to store and manage permissions values in a database.
diff --git a/docs/en/modules/saas.md b/docs/en/modules/saas.md
index f1e85d6ceb..d6faa4dbcb 100644
--- a/docs/en/modules/saas.md
+++ b/docs/en/modules/saas.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Manage tenants and editions in your multi-tenant applications with the ABP SaaS Module, enhancing your app's scalability and flexibility."
+}
+```
+
# SaaS Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/setting-management.md b/docs/en/modules/setting-management.md
index 7772e7f1f5..dcb021fe14 100644
--- a/docs/en/modules/setting-management.md
+++ b/docs/en/modules/setting-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage application settings effortlessly with the ABP Framework's Setting Management Module and ISettingManager."
+}
+```
+
# Setting Management Module
Setting Management Module implements the `ISettingStore` (see [the setting system](../framework/infrastructure/settings.md)) to store the setting values in a database and provides the `ISettingManager` to manage (change) the setting values in the database.
diff --git a/docs/en/modules/tenant-management.md b/docs/en/modules/tenant-management.md
index 4116bccb33..a8b56d0c6b 100644
--- a/docs/en/modules/tenant-management.md
+++ b/docs/en/modules/tenant-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Tenant Management module in ABP Framework, enabling efficient multi-tenancy setup for your SaaS applications with easy tenant management."
+}
+```
+
# Tenant Management Module
[Multi-Tenancy](../framework/architecture/multi-tenancy) is one of the core features of ABP. It provides the fundamental infrastructure to build your own SaaS (Software-as-a-Service) solution. ABP's multi-tenancy system abstracts where your tenants are stored, by providing the `ITenantStore` interface. All you need to do is to implement that interface.
diff --git a/docs/en/modules/text-template-management.md b/docs/en/modules/text-template-management.md
index 7f045cd8e1..c0e19a0523 100644
--- a/docs/en/modules/text-template-management.md
+++ b/docs/en/modules/text-template-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Manage and edit text templates effortlessly with the ABP Framework's Text Template Management Module, enhancing your application's communication features."
+}
+```
+
# Text Template Management Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/twilio-sms.md b/docs/en/modules/twilio-sms.md
index 56e667db18..6ea6c7e93f 100644
--- a/docs/en/modules/twilio-sms.md
+++ b/docs/en/modules/twilio-sms.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Integrate Twilio SMS into your ABP application effortlessly with our Pro module. Learn installation and best practices for seamless messaging!"
+}
+```
+
# Twilio SMS Module (Pro)
> You must have an ABP Team or a higher license to use this module.
diff --git a/docs/en/modules/virtual-file-explorer.md b/docs/en/modules/virtual-file-explorer.md
index 3157198c30..a891e57140 100644
--- a/docs/en/modules/virtual-file-explorer.md
+++ b/docs/en/modules/virtual-file-explorer.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to install and use the Virtual File Explorer Module in your ABP Framework application to easily manage files in a virtual file system."
+}
+```
+
# Virtual File Explorer Module
## What is Virtual File Explorer Module?
diff --git a/docs/en/others/aspnet-boilerplate-migration-guide.md b/docs/en/others/aspnet-boilerplate-migration-guide.md
index b3f3c0f577..e88b4b1c45 100644
--- a/docs/en/others/aspnet-boilerplate-migration-guide.md
+++ b/docs/en/others/aspnet-boilerplate-migration-guide.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to seamlessly migrate your projects from ASP.NET Boilerplate to ABP Framework with our comprehensive guide for developers."
+}
+```
+
# Migrating from ASP.NET Boilerplate to the ABP
ABP is **the successor** of the open source [ASP.NET Boilerplate](https://aspnetboilerplate.com/) framework. This guide aims to help you to **migrate your existing solutions** (you developed with the ASP.NET Boilerplate framework) to the ABP.
diff --git a/docs/en/others/aspnet-zero-vs-abp.md b/docs/en/others/aspnet-zero-vs-abp.md
index 245428926f..3d18d51a02 100644
--- a/docs/en/others/aspnet-zero-vs-abp.md
+++ b/docs/en/others/aspnet-zero-vs-abp.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Compare ABP Framework and ASP.NET Zero features to make informed decisions for your next project with this insightful guide."
+}
+```
+
# ABP vs ASP.NET Zero
[ASP.NET Zero](https://aspnetzero.com/) is a startup project template which is also developed by [Volosoft](https://volosoft.com/). Here you can see the feature differences between ASP.NET Zero and ABP Platform (with commercial licenses).
diff --git a/docs/en/others/free-licenses-vs-pro-licenses.md b/docs/en/others/free-licenses-vs-pro-licenses.md
index 81c751d1a2..96f06eecb1 100644
--- a/docs/en/others/free-licenses-vs-pro-licenses.md
+++ b/docs/en/others/free-licenses-vs-pro-licenses.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Compare the key differences between ABP's free open-source license and the enhanced features of ABP Pro licenses for developers."
+}
+```
+
# Free (Open Source) License vs Commercial (Pro) Licenses
[ABP](https://abp.io) is a completely free, open-source and community-driven project. It provides a base framework, [startup templates](../solution-templates), [CLI](../cli), theme called [LeptonX Lite](../ui-themes/lepton-x-lite/asp-net-core.md) and ready to use [application modules](../modules).
diff --git a/docs/en/others/penetration-test-report.md b/docs/en/others/penetration-test-report.md
index 0ed0628033..13086fb2a0 100644
--- a/docs/en/others/penetration-test-report.md
+++ b/docs/en/others/penetration-test-report.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Penetration Test Report detailing security findings, false positives, and actionable fixes for the ABP Commercial MVC app."
+}
+```
+
# ABP Penetration Test Report
The ABP Commercial MVC `v9.1.0` application template has been tested against security vulnerabilities by the [OWASP ZAP v2.14.0](https://www.zaproxy.org/) tool. The demo web application was started on the `https://localhost:44349` address. The below alerts have been reported by the pentest tool. These alerts are sorted by the risk level as high, medium, and low. The informational alerts are not mentioned in this document.
diff --git a/docs/en/others/why-abp-platform.md b/docs/en/others/why-abp-platform.md
index 61756d2654..1c2bf2cf6f 100644
--- a/docs/en/others/why-abp-platform.md
+++ b/docs/en/others/why-abp-platform.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover why the ABP Platform is the ideal choice for building software solutions efficiently, overcoming common development challenges."
+}
+```
+
# Why ABP Platform?
This document aims to answer the big question:
diff --git a/docs/en/release-info/index.md b/docs/en/release-info/index.md
index d5de2d2893..e3d3aa56cd 100644
--- a/docs/en/release-info/index.md
+++ b/docs/en/release-info/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the latest ABP Framework release information, including notes, migration guides, and upgrading tips to enhance your development experience."
+}
+```
+
# Release Information
* [Release Notes](./release-notes.md)
diff --git a/docs/en/release-info/migration-guides/abp-10-0.md b/docs/en/release-info/migration-guides/abp-10-0.md
index 24be60d1f8..c4b46a1edd 100644
--- a/docs/en/release-info/migration-guides/abp-10-0.md
+++ b/docs/en/release-info/migration-guides/abp-10-0.md
@@ -8,6 +8,12 @@ This document is a guide for upgrading ABP v9.x solutions to ABP v10.0. There ar
We've upgraded ABP to .NET 10.0, so you need to move your solutions to .NET 10.0 if you want to use ABP 10.0. You can check Microsoft’s [Migrate from ASP.NET Core 9.0 to 10.0](https://learn.microsoft.com/en-us/aspnet/core/migration/90-to-100) documentation, to see how to update an existing ASP.NET Core 9.0 project to ASP.NET Core 10.0.
+### Add new EF Core Migrations
+
+Some entities in certain modules have been modified. If you are using Entity Framework Core, please create a new EF Core migration in your project after upgrading to ABP 10.0.
+
+> If the migration file is empty, you can remove it by `dotnet ef migrations remove` command.
+
### Razor Runtime Compilation Obsolete
We removed the Razor Runtime Compilation support since it is obsolete and replaced by [Hot Reload](https://learn.microsoft.com/en-us/aspnet/core/test/hot-reload) in .NET 10.0.
diff --git a/docs/en/release-info/migration-guides/abp-4-0-angular.md b/docs/en/release-info/migration-guides/abp-4-0-angular.md
index 9e909182ec..dc575405b2 100644
--- a/docs/en/release-info/migration-guides/abp-4-0-angular.md
+++ b/docs/en/release-info/migration-guides/abp-4-0-angular.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to seamlessly migrate from Angular UI 3.3 to 4.0 with this guide, including key updates and breaking changes for ABP Framework users."
+}
+```
+
# Angular UI 3.3 to 4.0 Migration Guide
## Angular v11
diff --git a/docs/en/release-info/migration-guides/abp-4-0-blazor.md b/docs/en/release-info/migration-guides/abp-4-0-blazor.md
index 7f00d6de75..63a93ac7ab 100644
--- a/docs/en/release-info/migration-guides/abp-4-0-blazor.md
+++ b/docs/en/release-info/migration-guides/abp-4-0-blazor.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Blazor UI 3.3 to 4.0 Migration Guide, detailing essential updates for your project files and dependencies to ensure a smooth transition."
+}
+```
+
# Blazor UI 3.3 to 4.0 Migration Guide
## Startup Template Changes
diff --git a/docs/en/release-info/migration-guides/abp-4-0-mvc-razor-pages.md b/docs/en/release-info/migration-guides/abp-4-0-mvc-razor-pages.md
index d2fa97ec5e..31e6b85102 100644
--- a/docs/en/release-info/migration-guides/abp-4-0-mvc-razor-pages.md
+++ b/docs/en/release-info/migration-guides/abp-4-0-mvc-razor-pages.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily migrate from MVC/Razor Pages UI 3.3 to 4.0 by updating the namespace for IBrandingProvider in ABP Framework."
+}
+```
+
# MVC / Razor Pages UI 3.3 to 4.0 Migration Guide
## Use IBrandingProvider in the Volo.Abp.UI Package
diff --git a/docs/en/release-info/migration-guides/abp-4-0.md b/docs/en/release-info/migration-guides/abp-4-0.md
index e809dc807f..79c897edd0 100644
--- a/docs/en/release-info/migration-guides/abp-4-0.md
+++ b/docs/en/release-info/migration-guides/abp-4-0.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to upgrade your ABP 3.x solutions to 4.0 by addressing breaking changes and enhancing your development experience with .NET 5.0."
+}
+```
+
# ABP 3.3 to 4.0 Migration Guide
This document introduces the breaking changes done in the ABP 4.0 and explains how to fix your 3.x based solutions while upgrading to the ABP 4.0.
diff --git a/docs/en/release-info/migration-guides/abp-4-2.md b/docs/en/release-info/migration-guides/abp-4-2.md
index 76bfdd7957..2c9bdd9c0a 100644
--- a/docs/en/release-info/migration-guides/abp-4-2.md
+++ b/docs/en/release-info/migration-guides/abp-4-2.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the ABP 4.2 Migration Guide to enhance performance with new repository features and leverage LINQ for efficient data queries."
+}
+```
+
# ABP version 4.2 Migration Guide
This version has no breaking changes but there is an important change on the repositories that should be applied for your application for an important performance and scalability gain.
diff --git a/docs/en/release-info/migration-guides/abp-4-3.md b/docs/en/release-info/migration-guides/abp-4-3.md
index 79fb82d448..c2cb6b97bf 100644
--- a/docs/en/release-info/migration-guides/abp-4-3.md
+++ b/docs/en/release-info/migration-guides/abp-4-3.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to smoothly migrate from ABP 4.x to 4.3 with our guide, covering breaking changes and essential updates for Blazor UI."
+}
+```
+
# ABP 4.x to 4.3 Migration Guide
This version comes with some changes in the startup template, mostly related to Blazor UI. This document explains the breaking changes. However, **it is suggested to [compare the startup templates manually](upgrading-startup-template.md) to see all the changes** and apply to your solution.
diff --git a/docs/en/release-info/migration-guides/abp-5-0-angular.md b/docs/en/release-info/migration-guides/abp-5-0-angular.md
index 4941bcc251..f6abcf10f6 100644
--- a/docs/en/release-info/migration-guides/abp-5-0-angular.md
+++ b/docs/en/release-info/migration-guides/abp-5-0-angular.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the essential migration steps and breaking changes for upgrading your Angular UI from v4.x to v5.0 in the ABP Framework."
+}
+```
+
# Angular UI v4.x to v5.0 Migration Guide
> This document is for the Angular UI. See also [the main migration guide](abp-5-0.md).
diff --git a/docs/en/release-info/migration-guides/abp-5-0-blazor.md b/docs/en/release-info/migration-guides/abp-5-0-blazor.md
index 0884df7ca3..19fbeb8ceb 100644
--- a/docs/en/release-info/migration-guides/abp-5-0-blazor.md
+++ b/docs/en/release-info/migration-guides/abp-5-0-blazor.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to migrate your ABP Blazor UI from v4.x to v5.0, including updates for Blazorise and Bootstrap 5 for seamless integration."
+}
+```
+
# ABP Blazor UI v4.x to v5.0 Migration Guide
> This document is for the Blazor UI. See also [the main migration guide](abp-5-0.md).
diff --git a/docs/en/release-info/migration-guides/abp-5-0-mvc.md b/docs/en/release-info/migration-guides/abp-5-0-mvc.md
index 035d78e7ae..f10579a311 100644
--- a/docs/en/release-info/migration-guides/abp-5-0-mvc.md
+++ b/docs/en/release-info/migration-guides/abp-5-0-mvc.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP MVC/Razor Pages UI with this guide, featuring essential changes like Gulp removal and SweetAlert2 integration."
+}
+```
+
# ABP MVC / Razor Pages UI v4.x to v5.0 Migration Guide
> This document is for the ABP MVC / Razor Pages UI. See also [the main migration guide](abp-5-0.md).
diff --git a/docs/en/release-info/migration-guides/abp-5-0.md b/docs/en/release-info/migration-guides/abp-5-0.md
index 79ac59c8bb..7acc67ee7d 100644
--- a/docs/en/release-info/migration-guides/abp-5-0.md
+++ b/docs/en/release-info/migration-guides/abp-5-0.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP 4.x solutions to 5.0 with this comprehensive migration guide, covering essential breaking changes and updates."
+}
+```
+
# ABP v4.x to v5.0 Migration Guide
This document is a guide for upgrading ABP 4.x solutions to ABP 5.0. Please read them all since 5.0 has some important breaking changes.
diff --git a/docs/en/release-info/migration-guides/abp-5-2.md b/docs/en/release-info/migration-guides/abp-5-2.md
index 036c28ecf8..5861eaab95 100644
--- a/docs/en/release-info/migration-guides/abp-5-2.md
+++ b/docs/en/release-info/migration-guides/abp-5-2.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP v5.x solutions to v5.2 with this comprehensive migration guide, covering key changes for MongoDB and Blazor UI."
+}
+```
+
# ABP Version 5.2 Migration Guide
This document is a guide for upgrading ABP v5.x solutions to ABP v5.2. Please read them all since v5.2 has some changes you should take care.
diff --git a/docs/en/release-info/migration-guides/abp-5-3.md b/docs/en/release-info/migration-guides/abp-5-3.md
index ad4aa3b724..0ffcee3d94 100644
--- a/docs/en/release-info/migration-guides/abp-5-3.md
+++ b/docs/en/release-info/migration-guides/abp-5-3.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP v5.2 solutions to v5.3 with this migration guide, highlighting crucial changes and AutoMapper updates for seamless transitions."
+}
+```
+
# ABP Version 5.3 Migration Guide
This document is a guide for upgrading ABP v5.2 solutions to ABP v5.3. There is a change in this version that may effect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-6-0.md b/docs/en/release-info/migration-guides/abp-6-0.md
index 610b94b1f5..880e167d7e 100644
--- a/docs/en/release-info/migration-guides/abp-6-0.md
+++ b/docs/en/release-info/migration-guides/abp-6-0.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP applications seamlessly with the 6.0 Migration Guide, detailing essential changes and updates for a smooth transition."
+}
+```
+
# ABP Version 6.0 Migration Guide
This document is a guide for upgrading ABP v5.3 solutions to ABP v6.0. There is a change in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-7-0.md b/docs/en/release-info/migration-guides/abp-7-0.md
index b067781150..8d26f937cf 100644
--- a/docs/en/release-info/migration-guides/abp-7-0.md
+++ b/docs/en/release-info/migration-guides/abp-7-0.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP v6.x solutions to v7.0 with this comprehensive migration guide, covering essential changes and .NET 7.0 requirements."
+}
+```
+
# ABP Version 7.0 Migration Guide
This document is a guide for upgrading ABP v6.x solutions to ABP v7.0. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-7-1.md b/docs/en/release-info/migration-guides/abp-7-1.md
index 32817c78f2..c537fb1253 100644
--- a/docs/en/release-info/migration-guides/abp-7-1.md
+++ b/docs/en/release-info/migration-guides/abp-7-1.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP Framework from v7.0 to v7.1 with this migration guide, covering essential changes and improvements for seamless integration."
+}
+```
+
# ABP Version 7.1 Migration Guide
This document is a guide for upgrading ABP v7.0 solutions to ABP v7.1. There are a few changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-7-2.md b/docs/en/release-info/migration-guides/abp-7-2.md
index 453f1cf785..5fd58b4af3 100644
--- a/docs/en/release-info/migration-guides/abp-7-2.md
+++ b/docs/en/release-info/migration-guides/abp-7-2.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP v7.1 solutions to v7.2 with this migration guide, covering essential changes and new properties for smoother transitions."
+}
+```
+
# ABP Version 7.2 Migration Guide
This document is a guide for upgrading ABP v7.1 solutions to ABP v7.2. There are a few changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-7-3.md b/docs/en/release-info/migration-guides/abp-7-3.md
index 5400f28c3a..cda00e13e4 100644
--- a/docs/en/release-info/migration-guides/abp-7-3.md
+++ b/docs/en/release-info/migration-guides/abp-7-3.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP framework from v7.2 to v7.3 with this comprehensive migration guide, detailing essential changes and fixes for smooth transitions."
+}
+```
+
# ABP Version 7.3 Migration Guide
This document is a guide for upgrading ABP v7.2 solutions to ABP v7.3. There are a few changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-7-4.md b/docs/en/release-info/migration-guides/abp-7-4.md
index 8674ea4ab6..c81112e8c0 100644
--- a/docs/en/release-info/migration-guides/abp-7-4.md
+++ b/docs/en/release-info/migration-guides/abp-7-4.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP applications from v7.3 to v7.4 with this comprehensive migration guide, ensuring a smooth transition and optimal performance."
+}
+```
+
# ABP Version 7.4 Migration Guide
This document is a guide for upgrading ABP v7.3 solutions to ABP v7.4. There are a few changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-8-0.md b/docs/en/release-info/migration-guides/abp-8-0.md
index 04f1346adb..7109ae4844 100644
--- a/docs/en/release-info/migration-guides/abp-8-0.md
+++ b/docs/en/release-info/migration-guides/abp-8-0.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP solutions to version 8.0 with this comprehensive migration guide, detailing essential changes and dependencies."
+}
+```
+
# ABP Version 8.0 Migration Guide
This document is a guide for upgrading ABP v7.x solutions to ABP v8.0. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-8-1.md b/docs/en/release-info/migration-guides/abp-8-1.md
index 4c17da95ed..f1d9636a00 100644
--- a/docs/en/release-info/migration-guides/abp-8-1.md
+++ b/docs/en/release-info/migration-guides/abp-8-1.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP Framework from v8.0 to v8.1 with this essential migration guide, covering key changes and new features."
+}
+```
+
# ABP Version 8.1 Migration Guide
This document is a guide for upgrading ABP v8.0 solutions to ABP v8.1. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-8-2-blazor-web-app.md b/docs/en/release-info/migration-guides/abp-8-2-blazor-web-app.md
index ef9533bbc2..e3b65e1221 100644
--- a/docs/en/release-info/migration-guides/abp-8-2-blazor-web-app.md
+++ b/docs/en/release-info/migration-guides/abp-8-2-blazor-web-app.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to migrate to the ABP v8.2 Blazor Web App template, exploring new features and rendering modes for enhanced web UI development."
+}
+```
+
# Migrating to Blazor Web App
ASP.NET Blazor in .NET 8 allows you to use a single powerful component model to handle all of your web UI needs, including server-side rendering, client-side rendering, streaming rendering, progressive enhancement, and much more!
diff --git a/docs/en/release-info/migration-guides/abp-8-2.md b/docs/en/release-info/migration-guides/abp-8-2.md
index 5f811da2d4..13bf4c96ed 100644
--- a/docs/en/release-info/migration-guides/abp-8-2.md
+++ b/docs/en/release-info/migration-guides/abp-8-2.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP v8.x solutions to v8.2 with this migration guide, detailing essential changes and updated target frameworks for seamless integration."
+}
+```
+
# ABP Version 8.2 Migration Guide
This document is a guide for upgrading ABP v8.x solutions to ABP v8.2. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-8-3.md b/docs/en/release-info/migration-guides/abp-8-3.md
index b68805a3ab..acf1616581 100644
--- a/docs/en/release-info/migration-guides/abp-8-3.md
+++ b/docs/en/release-info/migration-guides/abp-8-3.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP v8.x solutions smoothly with this guide, detailing essential changes and new features in version 8.3!"
+}
+```
+
# ABP Version 8.3 Migration Guide
This document is a guide for upgrading ABP v8.x solutions to ABP v8.3. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/abp-9-0.md b/docs/en/release-info/migration-guides/abp-9-0.md
index b63b6bd030..8f0b9c09f6 100644
--- a/docs/en/release-info/migration-guides/abp-9-0.md
+++ b/docs/en/release-info/migration-guides/abp-9-0.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your ABP applications from v8.x to v9.0 with this comprehensive migration guide, ensuring compatibility with .NET 9.0."
+}
+```
+
# ABP Version 9.0 Migration Guide
This document is a guide for upgrading ABP v8.x solutions to ABP v9.0. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
diff --git a/docs/en/release-info/migration-guides/blazorui-3-3.md b/docs/en/release-info/migration-guides/blazorui-3-3.md
index 9ebbda2b2f..5df065de5d 100644
--- a/docs/en/release-info/migration-guides/blazorui-3-3.md
+++ b/docs/en/release-info/migration-guides/blazorui-3-3.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the migration guide for upgrading your Blazor UI from v3.2 to v3.3, featuring essential changes and improvements for a smoother transition."
+}
+```
+
# Migration Guide for the Blazor UI from the v3.2 to the v3.3
## Startup Template Changes
diff --git a/docs/en/release-info/migration-guides/identityserver-to-openiddict.md b/docs/en/release-info/migration-guides/identityserver-to-openiddict.md
index d60493be7a..2770722a51 100644
--- a/docs/en/release-info/migration-guides/identityserver-to-openiddict.md
+++ b/docs/en/release-info/migration-guides/identityserver-to-openiddict.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to migrate from Identity Server to OpenIddict in ABP Framework with this comprehensive guide, ensuring a smooth transition."
+}
+```
+
# Migration Identity Server to OpenIddict Guide
This document explains how to migrate to [OpenIddict](https://github.com/openiddict/openiddict-core) from Identity Server. From now on the ABP startup templates uses `OpenIddict` as the auth server by default since version v6.0.0.
diff --git a/docs/en/release-info/migration-guides/identityserver4-step-by-step.md b/docs/en/release-info/migration-guides/identityserver4-step-by-step.md
index 12973b6073..844d5ae071 100644
--- a/docs/en/release-info/migration-guides/identityserver4-step-by-step.md
+++ b/docs/en/release-info/migration-guides/identityserver4-step-by-step.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Step-by-step guide for migrating from OpenIddict to IdentityServer4 in ABP Framework applications, ensuring a smooth transition for developers."
+}
+```
+
# Migrating from OpenIddict to IdentityServer4 Step by Step Guide
ABP startup templates use `OpenIddict` OpenID provider from v6.0.0 by default and `IdentityServer` projects are renamed to `AuthServer` in tiered/separated solutions. Since OpenIddict is the default OpenID provider library for ABP templates since v6.0, you may want to keep using [IdentityServer4](https://github.com/IdentityServer/IdentityServer4) library, even it is **archived and no longer maintained by the owners**. ABP doesn't provide support for newer versions of IdentityServer. This guide provides layer-by-layer guidance for migrating your existing [OpenIddict](https://github.com/openiddict/openiddict-core) application to IdentityServer4.
diff --git a/docs/en/release-info/migration-guides/index.md b/docs/en/release-info/migration-guides/index.md
index 9d24cf7e5a..f0d8a78b84 100644
--- a/docs/en/release-info/migration-guides/index.md
+++ b/docs/en/release-info/migration-guides/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to seamlessly migrate your ABP applications between versions with step-by-step guides to ensure a smooth upgrade process."
+}
+```
+
# ABP Migration Guides
The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../upgrading.md).
diff --git a/docs/en/release-info/migration-guides/openiddict-angular.md b/docs/en/release-info/migration-guides/openiddict-angular.md
index b829c87584..293afade4a 100644
--- a/docs/en/release-info/migration-guides/openiddict-angular.md
+++ b/docs/en/release-info/migration-guides/openiddict-angular.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "This guide walks you through migrating your Angular UI to OpenIddict, ensuring seamless integration with ABP Framework for secure authentication."
+}
+```
+
# OpenIddict Angular UI Migration Guide
## Angular Project
diff --git a/docs/en/release-info/migration-guides/openiddict-blazor-server.md b/docs/en/release-info/migration-guides/openiddict-blazor-server.md
index 35e9d81a14..77924c6949 100644
--- a/docs/en/release-info/migration-guides/openiddict-blazor-server.md
+++ b/docs/en/release-info/migration-guides/openiddict-blazor-server.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "This guide details the migration process to OpenIddict for Blazor Server applications, enhancing security and user authentication."
+}
+```
+
# OpenIddict Blazor-Server UI Migration Guide
## Blazor Project (Non-Tiered Solution)
diff --git a/docs/en/release-info/migration-guides/openiddict-blazor.md b/docs/en/release-info/migration-guides/openiddict-blazor.md
index e6be3c6e6d..794fe997d7 100644
--- a/docs/en/release-info/migration-guides/openiddict-blazor.md
+++ b/docs/en/release-info/migration-guides/openiddict-blazor.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to migrate your Blazor Wasm UI to OpenIddict for seamless authentication in your ABP Framework applications."
+}
+```
+
# OpenIddict Blazor Wasm UI Migration Guide
## Blazor Project
diff --git a/docs/en/release-info/migration-guides/openiddict-mvc.md b/docs/en/release-info/migration-guides/openiddict-mvc.md
index b3e4e0e34c..82aff046f0 100644
--- a/docs/en/release-info/migration-guides/openiddict-mvc.md
+++ b/docs/en/release-info/migration-guides/openiddict-mvc.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "This guide provides step-by-step instructions for migrating your MVC/Razor UI project to OpenIddict, enhancing security and authentication."
+}
+```
+
# OpenIddict MVC/Razor UI Migration Guide
## Web Project (Non-Tiered Solution)
diff --git a/docs/en/release-info/migration-guides/openiddict-step-by-step.md b/docs/en/release-info/migration-guides/openiddict-step-by-step.md
index 04866180ad..a9eac47fa7 100644
--- a/docs/en/release-info/migration-guides/openiddict-step-by-step.md
+++ b/docs/en/release-info/migration-guides/openiddict-step-by-step.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Step-by-step guide for migrating from IdentityServer to OpenIddict in ABP Framework, ensuring smooth updates and continued support."
+}
+```
+
# Migrating from IdentityServer to OpenIddict Step by Step Guide
This guide provides layer-by-layer guidance for migrating your existing application to [OpenIddict](https://github.com/openiddict/openiddict-core) from IdentityServer. ABP startup templates use `OpenIddict` OpenId provider from v6.0.0 by default and `IdentityServer` projects are renamed to `AuthServer` in tiered/separated solutions. Since OpenIddict is only available with ABP v6.0, you will need to update your existing application in order to apply OpenIddict changes.
diff --git a/docs/en/release-info/migration-guides/openiddict4-to-5.md b/docs/en/release-info/migration-guides/openiddict4-to-5.md
index b8eb1ffb87..add172e8e2 100644
--- a/docs/en/release-info/migration-guides/openiddict4-to-5.md
+++ b/docs/en/release-info/migration-guides/openiddict4-to-5.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the essential changes for migrating from OpenIddict 4.x to 5.x, including new features and critical updates for a smooth transition."
+}
+```
+
# OpenIddict 4.x to 5.x Migration Guide
The 5.0 release of OpenIddict is a major release that introduces breaking changes.
diff --git a/docs/en/release-info/migration-guides/pro/blazorui-3-3.md b/docs/en/release-info/migration-guides/pro/blazorui-3-3.md
index 2279712264..bebb813574 100644
--- a/docs/en/release-info/migration-guides/pro/blazorui-3-3.md
+++ b/docs/en/release-info/migration-guides/pro/blazorui-3-3.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your Blazor UI from v3.2 to v3.3 with essential changes, package updates, and new footer customization for your project."
+}
+```
+
# Migration Guide for the Blazor UI from the v3.2 to the v3.3
## Startup Template Changes
diff --git a/docs/en/release-info/migration-guides/pro/microservice-4-x-to-5-2.md b/docs/en/release-info/migration-guides/pro/microservice-4-x-to-5-2.md
index c64d11c7ac..1428e56347 100644
--- a/docs/en/release-info/migration-guides/pro/microservice-4-x-to-5-2.md
+++ b/docs/en/release-info/migration-guides/pro/microservice-4-x-to-5-2.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Upgrade your Microservice template from 4.x to 5.2 with this comprehensive guide, covering breaking changes and enhancements like Docker support."
+}
+```
+
# Microservice Template Version 4.x to 5.2 Migration Guide
This document is a guide for upgrading Microservice template version 4.4 to version 5.2. Please read them all since there are some important breaking changes.
diff --git a/docs/en/release-info/migration-guides/pro/migrating-to-yarp.md b/docs/en/release-info/migration-guides/pro/migrating-to-yarp.md
index cdc1c62c11..0fe299c384 100644
--- a/docs/en/release-info/migration-guides/pro/migrating-to-yarp.md
+++ b/docs/en/release-info/migration-guides/pro/migrating-to-yarp.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to seamlessly migrate your API Gateway from Ocelot to YARP in ABP Framework, ensuring better performance and ongoing support."
+}
+```
+
# Migrating API Gateway from Ocelot to YARP
This guide provides guidance for migrating your existing microservice application's API Gateway from [Ocelot](https://github.com/ThreeMammals/Ocelot) to [YARP](https://github.com/microsoft/reverse-proxy). Since YARP is available with ABP v8.0+, you will need to update your existing application in order to apply YARP changes.
diff --git a/docs/en/release-info/migration-guides/pro/openiddict-angular.md b/docs/en/release-info/migration-guides/pro/openiddict-angular.md
index e234cea98d..3f8426e309 100644
--- a/docs/en/release-info/migration-guides/pro/openiddict-angular.md
+++ b/docs/en/release-info/migration-guides/pro/openiddict-angular.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Migrate your Angular UI to OpenIddict with this guide, featuring essential steps for seamless integration with ABP Framework."
+}
+```
+
# OpenIddict Angular UI Migration Guide
## Angular Project
diff --git a/docs/en/release-info/migration-guides/pro/openiddict-blazor-server.md b/docs/en/release-info/migration-guides/pro/openiddict-blazor-server.md
index 28e6771215..f459e8561a 100644
--- a/docs/en/release-info/migration-guides/pro/openiddict-blazor-server.md
+++ b/docs/en/release-info/migration-guides/pro/openiddict-blazor-server.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to migrate your Blazor Server UI to OpenIddict with this comprehensive guide, ensuring a smooth transition for your application."
+}
+```
+
# OpenIddict Blazor-Server UI Migration Guide
## Blazor Project (Non-Tiered Solution)
diff --git a/docs/en/release-info/migration-guides/pro/openiddict-blazor.md b/docs/en/release-info/migration-guides/pro/openiddict-blazor.md
index 0d65f62596..d86436a639 100644
--- a/docs/en/release-info/migration-guides/pro/openiddict-blazor.md
+++ b/docs/en/release-info/migration-guides/pro/openiddict-blazor.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Follow this guide to smoothly migrate your Blazor WebAssembly project to OpenIddict, enhancing authentication capabilities with ABP Framework."
+}
+```
+
# OpenIddict Blazor Wasm UI Migration Guide
## Blazor Project
diff --git a/docs/en/release-info/migration-guides/pro/openiddict-microservice.md b/docs/en/release-info/migration-guides/pro/openiddict-microservice.md
index 33c319111b..1a7e998aa5 100644
--- a/docs/en/release-info/migration-guides/pro/openiddict-microservice.md
+++ b/docs/en/release-info/migration-guides/pro/openiddict-microservice.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to migrate your microservice application to OpenIddict with this comprehensive guide, ensuring a smooth transition with ABP Framework."
+}
+```
+
# Migrating Microservice Application to OpenIddict Guide
This guide provides guidance for migrating your existing microservice application to OpenIddict. Since OpenIddict is only available with ABP v6.0, you will need to update your existing application in order to apply OpenIddict changes.
diff --git a/docs/en/release-info/migration-guides/pro/openiddict-mvc.md b/docs/en/release-info/migration-guides/pro/openiddict-mvc.md
index 620e715c6a..ca3eb02359 100644
--- a/docs/en/release-info/migration-guides/pro/openiddict-mvc.md
+++ b/docs/en/release-info/migration-guides/pro/openiddict-mvc.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to migrate your MVC/Razor UI to OpenIddict with this step-by-step guide, ensuring a smooth transition for your ABP Framework projects."
+}
+```
+
# OpenIddict MVC/Razor UI Migration Guide
## Web Project (Non-Tiered Solution)
diff --git a/docs/en/release-info/migration-guides/pro/openiddict-step-by-step.md b/docs/en/release-info/migration-guides/pro/openiddict-step-by-step.md
index 9934aad753..a530ce0bd5 100644
--- a/docs/en/release-info/migration-guides/pro/openiddict-step-by-step.md
+++ b/docs/en/release-info/migration-guides/pro/openiddict-step-by-step.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Step-by-step guide to migrate from IdentityServer to OpenIddict in ABP v6.0, ensuring a smooth transition for your applications."
+}
+```
+
# Migrating from IdentityServer to OpenIddict Step by Step Guide
This guide provides layer-by-layer guidance for migrating your existing application to OpenIddict. Since OpenIddict is only available with ABP v6.0, you will need to update your existing application in order to apply OpenIddict changes.
diff --git a/docs/en/release-info/migration-guides/upgrading-startup-template.md b/docs/en/release-info/migration-guides/upgrading-startup-template.md
index 96af41c23c..07c19c0499 100644
--- a/docs/en/release-info/migration-guides/upgrading-startup-template.md
+++ b/docs/en/release-info/migration-guides/upgrading-startup-template.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to upgrade your startup template in ABP Framework by comparing existing and new solutions using WinMerge for seamless updates."
+}
+```
+
# Upgrading the Startup Template
Sometimes we introduce new features/changes that requires to **make changes in the startup template**. We already implement the changes in the startup template for new applications. However, in some cases you need to manually make some minor changes in your existing solution.
diff --git a/docs/en/release-info/nightly-builds.md b/docs/en/release-info/nightly-builds.md
index bfe3e595ac..6f0d9909df 100644
--- a/docs/en/release-info/nightly-builds.md
+++ b/docs/en/release-info/nightly-builds.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Access the latest ABP Framework nightly builds effortlessly with our guide on installing and switching to preview packages. Stay ahead of releases!"
+}
+```
+
# Nightly Builds
All framework & module packages (both open-source and pro packages) are deployed to MyGet every night on weekdays. So, you can install the latest dev-branch builds to try out functionality prior to release.
diff --git a/docs/en/release-info/previews.md b/docs/en/release-info/previews.md
index 02358c8789..75e3055db5 100644
--- a/docs/en/release-info/previews.md
+++ b/docs/en/release-info/previews.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP Framework's preview releases, designed for developers to test upcoming features and provide feedback for enhanced stability."
+}
+```
+
# Preview Releases
The preview versions are released **~4 weeks before** releasing a major or minor (feature) version of ABP. They are released for developers to try and provide feedback to have more stable versions.
diff --git a/docs/en/release-info/release-notes.md b/docs/en/release-info/release-notes.md
index 284995d04d..cb6d5f421d 100644
--- a/docs/en/release-info/release-notes.md
+++ b/docs/en/release-info/release-notes.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the latest ABP Framework release notes, highlighting major features and enhancements for each version, including migration guidance."
+}
+```
+
# Release Notes
This document contains **brief release notes** for each release. Release notes only include **major features** and **visible enhancements**. They don't include all the development done in the related version.
diff --git a/docs/en/release-info/road-map.md b/docs/en/release-info/road-map.md
index 7a9ae2161a..f7b432a39d 100644
--- a/docs/en/release-info/road-map.md
+++ b/docs/en/release-info/road-map.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Platform Road Map for insights on upcoming features, release schedules, and improvements in version 9.1, launching January 2025."
+}
+```
+
# ABP Platform Road Map
This document provides a road map, release schedule, and planned features for the ABP Platform.
diff --git a/docs/en/release-info/upgrading.md b/docs/en/release-info/upgrading.md
index 28404c20b4..88ce1249d8 100644
--- a/docs/en/release-info/upgrading.md
+++ b/docs/en/release-info/upgrading.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently upgrade your ABP-based solutions with the ABP CLI, ensuring smooth updates and database management."
+}
+```
+
# Upgrading ABP Based Solutions
This document explains how to upgrade your existing solution when a new ABP version is published.
diff --git a/docs/en/samples/easy-crm.md b/docs/en/samples/easy-crm.md
index 1a0fff3b3f..eb959a38c8 100644
--- a/docs/en/samples/easy-crm.md
+++ b/docs/en/samples/easy-crm.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Easy CRM sample project built on ABP Framework, featuring source code for ASP.NET Core, Angular, and Blazor UIs, exclusive for ABP customers."
+}
+```
+
# Easy CRM - Sample ABP Project
This is a sample solution developed on top of ABP.
diff --git a/docs/en/samples/eshop-on-abp/index.md b/docs/en/samples/eshop-on-abp/index.md
index ac45772150..7d0141e65c 100644
--- a/docs/en/samples/eshop-on-abp/index.md
+++ b/docs/en/samples/eshop-on-abp/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the outdated eShopOnAbp project and transition to the recommended ABP Microservice Solution Template for modern microservices development."
+}
+```
+
# eShopOnAbp
> ⚠️ **Important Notice**
diff --git a/docs/en/samples/index.md b/docs/en/samples/index.md
index 7110dd42f6..9bce96be17 100644
--- a/docs/en/samples/index.md
+++ b/docs/en/samples/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore a variety of ABP Framework samples, complete with live demos, source code, and tutorials to enhance your development skills!"
+}
+```
+
# ABP Samples
This document provides a list of samples built with ABP. Each sample is briefly explained below, along with its live demo (if available), source code, and tutorial links (where applicable).
diff --git a/docs/en/samples/microservice-demo.md b/docs/en/samples/microservice-demo.md
index cf842d1a62..31516b2a55 100644
--- a/docs/en/samples/microservice-demo.md
+++ b/docs/en/samples/microservice-demo.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the microservice demo solution, now replaced by eShopOnAbp, and learn about benefits of microservices in software architecture."
+}
+```
+
# Microservice Demo Solution
> This solution is no longer maintained. See [the eShopOnAbp project](https://github.com/abpframework/eShopOnAbp) for the replacement solution.
diff --git a/docs/en/solution-templates/application-module/index.md b/docs/en/solution-templates/application-module/index.md
index 48013d2d90..19b2294a76 100644
--- a/docs/en/solution-templates/application-module/index.md
+++ b/docs/en/solution-templates/application-module/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Create reusable application modules or microservices with the ABP Framework's module solution template. Start building with ease!"
+}
+```
+
# ABP Application Module Template
This document explains how to create a **reusable [application module](../../modules)** based on the [module development best practices & conventions](../../framework/architecture/best-practices).
diff --git a/docs/en/solution-templates/guide.md b/docs/en/solution-templates/guide.md
index ded0c49f20..944e503c53 100644
--- a/docs/en/solution-templates/guide.md
+++ b/docs/en/solution-templates/guide.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's guide to selecting the right startup template for your project, covering architectures like Microservices, N-Layered, and more."
+}
+```
+
# Solution Templates: A Guide to Select the Right One For You
ABP provides several [startup templates](index.md) to you. It is important to start with the right startup template that is suitable for your **project** and **team**. This guide aims to lead you to select the most proper startup template for your requirements.
diff --git a/docs/en/solution-templates/index.md b/docs/en/solution-templates/index.md
index 739dbc453e..c833b8d508 100644
--- a/docs/en/solution-templates/index.md
+++ b/docs/en/solution-templates/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's production-ready startup solution templates for Single-Layer, Layered, and Microservice architectures to kickstart your project!"
+}
+```
+
# Startup Solution Templates
ABP provides pre-architected and production-ready templates to jump start a new solution.
diff --git a/docs/en/solution-templates/layered-web-application/authentication.md b/docs/en/solution-templates/layered-web-application/authentication.md
index 0133e95246..5ef1526e39 100644
--- a/docs/en/solution-templates/layered-web-application/authentication.md
+++ b/docs/en/solution-templates/layered-web-application/authentication.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn about the common authentication structure in the Layered solution template, utilizing OpenIddict for seamless integration."
+}
+```
+
# Layered Solution: Authentication
```json
diff --git a/docs/en/solution-templates/layered-web-application/background-jobs.md b/docs/en/solution-templates/layered-web-application/background-jobs.md
index beef27d5d0..356186f213 100644
--- a/docs/en/solution-templates/layered-web-application/background-jobs.md
+++ b/docs/en/solution-templates/layered-web-application/background-jobs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently implement and manage background jobs in your layered solution using the ABP Framework for asynchronous tasks."
+}
+```
+
# Layered Solution: Background Jobs
```json
diff --git a/docs/en/solution-templates/layered-web-application/background-workers.md b/docs/en/solution-templates/layered-web-application/background-workers.md
index 500a21756b..b6f1c5806a 100644
--- a/docs/en/solution-templates/layered-web-application/background-workers.md
+++ b/docs/en/solution-templates/layered-web-application/background-workers.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement background workers in your applications for efficient handling of long-running tasks and scheduled processes."
+}
+```
+
# Layered Solution: Background Workers
```json
diff --git a/docs/en/solution-templates/layered-web-application/blob-storing.md b/docs/en/solution-templates/layered-web-application/blob-storing.md
index 9e1332e03a..f5d8804080 100644
--- a/docs/en/solution-templates/layered-web-application/blob-storing.md
+++ b/docs/en/solution-templates/layered-web-application/blob-storing.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively store BLOBs in a layered solution using ABP Framework, enhancing your application's file management capabilities."
+}
+```
+
# Layered Solution: BLOB Storing
```json
diff --git a/docs/en/solution-templates/layered-web-application/built-in-features.md b/docs/en/solution-templates/layered-web-application/built-in-features.md
index b5dba7c444..517c572bfb 100644
--- a/docs/en/solution-templates/layered-web-application/built-in-features.md
+++ b/docs/en/solution-templates/layered-web-application/built-in-features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the built-in features of the Layered solution template to kickstart your web application development with ABP Framework."
+}
+```
+
# Layered Solution: Built-In Features
```json
diff --git a/docs/en/solution-templates/layered-web-application/cors-configuration.md b/docs/en/solution-templates/layered-web-application/cors-configuration.md
index 73e7b6952b..d2ca705f17 100644
--- a/docs/en/solution-templates/layered-web-application/cors-configuration.md
+++ b/docs/en/solution-templates/layered-web-application/cors-configuration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure CORS in ABP Framework's layered solution template for various web application types, enhancing security and functionality."
+}
+```
+
# Layered Solution: CORS Configuration
```json
diff --git a/docs/en/solution-templates/layered-web-application/database-configurations.md b/docs/en/solution-templates/layered-web-application/database-configurations.md
index 0776062c4f..255b098ae2 100644
--- a/docs/en/solution-templates/layered-web-application/database-configurations.md
+++ b/docs/en/solution-templates/layered-web-application/database-configurations.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage database configurations in ABP Framework's Layered Solution Template with customizable connection strings for different environments."
+}
+```
+
# Layered Solution: Database configurations
```json
diff --git a/docs/en/solution-templates/layered-web-application/db-migrator.md b/docs/en/solution-templates/layered-web-application/db-migrator.md
index 50fd38d836..54f6cc619a 100644
--- a/docs/en/solution-templates/layered-web-application/db-migrator.md
+++ b/docs/en/solution-templates/layered-web-application/db-migrator.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the Db Migrator for seamless database migrations and data seeding in your applications with ABP Framework."
+}
+```
+
# Layered Solution: Db Migrator
````json
diff --git a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment.md b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment.md
index 566cf80e32..bdba4f9796 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to deploy your ABP application on Azure using GitHub Actions, tailored for your chosen UI and database options."
+}
+```
+
# Azure Deployment using Application Service
````json
diff --git a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step1-create-azure-resources.md b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step1-create-azure-resources.md
index 9fb4de254b..76ac60976f 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step1-create-azure-resources.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step1-create-azure-resources.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create an Azure Web App Service using the Azure Portal or Terraform, tailored for different UI and database options."
+}
+```
+
````json
//[doc-params]
{
diff --git a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step2-configuration-application.md b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step2-configuration-application.md
index 718446353a..50ccb93652 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step2-configuration-application.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step2-configuration-application.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize your ABP application’s configuration by modifying ConnectionString values across key appsettings.json files."
+}
+```
+
````json
//[doc-params]
{
diff --git a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md
index 42efc9cd7c..78592210d0 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to deploy your ABP application to Azure Web App Service using GitHub Actions, streamlining your deployment process with ease."
+}
+```
+
````json
//[doc-params]
{
diff --git a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/terraform-web-app-service.md b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/terraform-web-app-service.md
index 7b346d0915..2282f1f503 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/terraform-web-app-service.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/terraform-web-app-service.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to provision an Azure Web App using Terraform with this step-by-step guide, including prerequisites and setup for a seamless deployment."
+}
+```
+
# Provisioning an Azure Web App using Terraform
````json
diff --git a/docs/en/solution-templates/layered-web-application/deployment/deployment-docker-compose.md b/docs/en/solution-templates/layered-web-application/deployment/deployment-docker-compose.md
index 7b88e39bb2..d4257cb222 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/deployment-docker-compose.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/deployment-docker-compose.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to deploy your ABP application using Docker Compose, including building images and modifying configurations for production environments."
+}
+```
+
# Docker Deployment using Docker Compose
````json
diff --git a/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md b/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md
index 4f77f3040d..f84b221bb0 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to deploy your ABP Framework application on IIS with this comprehensive guide, covering prerequisites and authentication certificate setup."
+}
+```
+
# IIS Deployment
````json
diff --git a/docs/en/solution-templates/layered-web-application/deployment/identityserver-deployment.md b/docs/en/solution-templates/layered-web-application/deployment/identityserver-deployment.md
index 8cb9438576..db6975e04f 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/identityserver-deployment.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/identityserver-deployment.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure IdentityServer for deployment, including CORS origins and redirect URLs, ensuring a secure and efficient setup for your applications."
+}
+```
+
# IdentityServer Deployment
IdentityServer configuration may be different based on deployment configurations. Basically, you need update identityserver client related data and update your hosting preferences based on your deployment environment.
diff --git a/docs/en/solution-templates/layered-web-application/deployment/index.md b/docs/en/solution-templates/layered-web-application/deployment/index.md
index a81823a7f7..01f13ed065 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/index.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to deploy your ABP Framework applications in staging and production environments with options for Docker, Azure, and IIS."
+}
+```
+
# Deployment
````json
diff --git a/docs/en/solution-templates/layered-web-application/deployment/openiddict-deployment.md b/docs/en/solution-templates/layered-web-application/deployment/openiddict-deployment.md
index 65ac72719c..b2459fcdad 100644
--- a/docs/en/solution-templates/layered-web-application/deployment/openiddict-deployment.md
+++ b/docs/en/solution-templates/layered-web-application/deployment/openiddict-deployment.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to deploy OpenIddict with ABP Framework, including CORS configuration for gateways and microservices in your applications."
+}
+```
+
# OpenIddict Deployment
[OpenIddict](https://github.com/openiddict/openiddict-core) is the default OpenId Provider library used by ABP templates through the [OpenIddict Module](https://docs.abp.io/en/abp/latest/Modules/OpenIddict). It is hosted by the **AuthServer** project in the tiered/seperate-authserver application templates. For non-tiered applications, it is hosted by the Web (MVC/Razor), BlazorServer or the **HttpApi.Host** project for Blazor and Angular applications.
diff --git a/docs/en/solution-templates/layered-web-application/distributed-locking.md b/docs/en/solution-templates/layered-web-application/distributed-locking.md
index 652a9e4376..7c65a1077a 100644
--- a/docs/en/solution-templates/layered-web-application/distributed-locking.md
+++ b/docs/en/solution-templates/layered-web-application/distributed-locking.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement distributed locking in layered applications to synchronize access to shared resources effectively."
+}
+```
+
# Layered Solution: Distributed Locking
```json
diff --git a/docs/en/solution-templates/layered-web-application/helm-charts-and-kubernetes.md b/docs/en/solution-templates/layered-web-application/helm-charts-and-kubernetes.md
index dcdd805e7f..d88fac6b31 100644
--- a/docs/en/solution-templates/layered-web-application/helm-charts-and-kubernetes.md
+++ b/docs/en/solution-templates/layered-web-application/helm-charts-and-kubernetes.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to deploy your ABP layered solution to a Kubernetes cluster using Helm charts, complete with folder structure guidance."
+}
+```
+
# Layered Solution: Helm Charts and Kubernetes
````json
diff --git a/docs/en/solution-templates/layered-web-application/index.md b/docs/en/solution-templates/layered-web-application/index.md
index e1e5997154..04f5adf11d 100644
--- a/docs/en/solution-templates/layered-web-application/index.md
+++ b/docs/en/solution-templates/layered-web-application/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover ABP Studio's Layered Solution Template for building robust monolithic applications using Domain-Driven Design principles."
+}
+```
+
# ABP Studio: Layered Solution Template
````json
diff --git a/docs/en/solution-templates/layered-web-application/logging.md b/docs/en/solution-templates/layered-web-application/logging.md
index 1ee3278bfb..1cbc1e188a 100644
--- a/docs/en/solution-templates/layered-web-application/logging.md
+++ b/docs/en/solution-templates/layered-web-application/logging.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement structured logging with Serilog in your ABP Framework applications, ensuring a consistent and efficient logging setup."
+}
+```
+
# Layered Solution: Logging
```json
diff --git a/docs/en/solution-templates/layered-web-application/main-components.md b/docs/en/solution-templates/layered-web-application/main-components.md
index b7b324069e..2935f6fd3a 100644
--- a/docs/en/solution-templates/layered-web-application/main-components.md
+++ b/docs/en/solution-templates/layered-web-application/main-components.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the main components of a layered solution, including web, mobile applications, and a database migrator, for seamless integration."
+}
+```
+
# Layered Solution: Main Components
````json
diff --git a/docs/en/solution-templates/layered-web-application/mobile-applications.md b/docs/en/solution-templates/layered-web-application/mobile-applications.md
index 4a6b6d057a..5d3c1385f4 100644
--- a/docs/en/solution-templates/layered-web-application/mobile-applications.md
+++ b/docs/en/solution-templates/layered-web-application/mobile-applications.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create and configure mobile applications using ABP Studio for your layered solution, enhancing user accessibility and experience."
+}
+```
+
# Layered Solution: Mobile Applications
```json
diff --git a/docs/en/solution-templates/layered-web-application/multi-tenancy.md b/docs/en/solution-templates/layered-web-application/multi-tenancy.md
index 632b392ebf..2afb1b9c2a 100644
--- a/docs/en/solution-templates/layered-web-application/multi-tenancy.md
+++ b/docs/en/solution-templates/layered-web-application/multi-tenancy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore multi-tenancy in the ABP Framework's layered solution, enabling isolated data and configurations for multiple tenants."
+}
+```
+
# Layered Solution: Multi-Tenancy
```json
diff --git a/docs/en/solution-templates/layered-web-application/overview.md b/docs/en/solution-templates/layered-web-application/overview.md
index bfc3f4a465..4c9678fcb2 100644
--- a/docs/en/solution-templates/layered-web-application/overview.md
+++ b/docs/en/solution-templates/layered-web-application/overview.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Layered Solution template in ABP Framework, featuring pre-installed libraries and services for seamless development and production."
+}
+```
+
# Layered Solution: Overview
````json
diff --git a/docs/en/solution-templates/layered-web-application/solution-structure.md b/docs/en/solution-templates/layered-web-application/solution-structure.md
index 3afd1b1274..4e75b95a5c 100644
--- a/docs/en/solution-templates/layered-web-application/solution-structure.md
+++ b/docs/en/solution-templates/layered-web-application/solution-structure.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the layered solution structure in ABP Studio and learn how to organize your projects effectively for optimal development."
+}
+```
+
# Layered Solution: The Structure
````json
diff --git a/docs/en/solution-templates/layered-web-application/swagger-integration.md b/docs/en/solution-templates/layered-web-application/swagger-integration.md
index 202ab9f892..12045fecb7 100644
--- a/docs/en/solution-templates/layered-web-application/swagger-integration.md
+++ b/docs/en/solution-templates/layered-web-application/swagger-integration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Swagger with ABP Framework for effective API documentation and interaction in your layered web applications."
+}
+```
+
# Layered Solution: Swagger Integration
```json
diff --git a/docs/en/solution-templates/layered-web-application/web-applications.md b/docs/en/solution-templates/layered-web-application/web-applications.md
index ce67866815..58cc3af078 100644
--- a/docs/en/solution-templates/layered-web-application/web-applications.md
+++ b/docs/en/solution-templates/layered-web-application/web-applications.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Layered Solution for Web Applications, including MVC/Razor Pages, to enhance user interaction with your ABP Framework projects."
+}
+```
+
# Layered Solution: Web Applications
````json
diff --git a/docs/en/solution-templates/microservice/adding-new-api-gateways.md b/docs/en/solution-templates/microservice/adding-new-api-gateways.md
index 415452a3bd..eb71df63cf 100644
--- a/docs/en/solution-templates/microservice/adding-new-api-gateways.md
+++ b/docs/en/solution-templates/microservice/adding-new-api-gateways.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to add new API gateways to your microservice solution with ABP Framework, enhancing request routing and system organization."
+}
+```
+
# Microservice Solution: Adding New API Gateways
````json
diff --git a/docs/en/solution-templates/microservice/adding-new-applications.md b/docs/en/solution-templates/microservice/adding-new-applications.md
index 352b18f763..0792e6b0c3 100644
--- a/docs/en/solution-templates/microservice/adding-new-applications.md
+++ b/docs/en/solution-templates/microservice/adding-new-applications.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to add new web applications to your ABP microservice solution, utilizing templates for customization and organization."
+}
+```
+
# Microservice Solution: Adding New Applications
````json
diff --git a/docs/en/solution-templates/microservice/adding-new-microservices.md b/docs/en/solution-templates/microservice/adding-new-microservices.md
index 610beaef7f..ff8b1cb809 100644
--- a/docs/en/solution-templates/microservice/adding-new-microservices.md
+++ b/docs/en/solution-templates/microservice/adding-new-microservices.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to add new microservices to your ABP Framework solution, utilizing templates for customization and independent development."
+}
+```
+
# Microservice Solution: Adding New Microservices
````json
diff --git a/docs/en/solution-templates/microservice/api-gateways.md b/docs/en/solution-templates/microservice/api-gateways.md
index 5bc9a33851..0dcd9c7fda 100644
--- a/docs/en/solution-templates/microservice/api-gateways.md
+++ b/docs/en/solution-templates/microservice/api-gateways.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement API Gateways in your ABP microservice solution, providing a single entry point for diverse client applications."
+}
+```
+
# Microservice Solution: API Gateways
````json
diff --git a/docs/en/solution-templates/microservice/authentication.md b/docs/en/solution-templates/microservice/authentication.md
index b66388ecf8..f079334a24 100644
--- a/docs/en/solution-templates/microservice/authentication.md
+++ b/docs/en/solution-templates/microservice/authentication.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement a common authentication structure using OpenIddict in your ABP microservice solution."
+}
+```
+
# Microservice Solution: Authentication
````json
diff --git a/docs/en/solution-templates/microservice/authoring-unit-and-integration-tests.md b/docs/en/solution-templates/microservice/authoring-unit-and-integration-tests.md
index b79a197ca8..0c2162a5d0 100644
--- a/docs/en/solution-templates/microservice/authoring-unit-and-integration-tests.md
+++ b/docs/en/solution-templates/microservice/authoring-unit-and-integration-tests.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to author unit and integration tests for microservices in ABP Framework, ensuring quality and reliability in your applications."
+}
+```
+
# Microservice Solution: Authoring Unit and Integration Tests
> You must have an ABP Business or a higher license to be able to create a microservice solution.
diff --git a/docs/en/solution-templates/microservice/background-jobs.md b/docs/en/solution-templates/microservice/background-jobs.md
index c0d34650aa..c8d2b1905c 100644
--- a/docs/en/solution-templates/microservice/background-jobs.md
+++ b/docs/en/solution-templates/microservice/background-jobs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement background jobs in your ABP Framework microservice using RabbitMQ for efficient task management."
+}
+```
+
# Microservice Solution: Background Jobs
````json
diff --git a/docs/en/solution-templates/microservice/background-workers.md b/docs/en/solution-templates/microservice/background-workers.md
index 5f3ac8507e..e2575f028f 100644
--- a/docs/en/solution-templates/microservice/background-workers.md
+++ b/docs/en/solution-templates/microservice/background-workers.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement background workers in your microservice solution with ABP Framework for efficient task management and automation."
+}
+```
+
# Microservice Solution: Background Workers
````json
diff --git a/docs/en/solution-templates/microservice/blob-storing.md b/docs/en/solution-templates/microservice/blob-storing.md
index e84c19133e..0e85367f9b 100644
--- a/docs/en/solution-templates/microservice/blob-storing.md
+++ b/docs/en/solution-templates/microservice/blob-storing.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to store BLOBs in a microservice solution using ABP Framework, including database integration for efficient large object management."
+}
+```
+
# Microservice Solution: BLOB Storing
````json
diff --git a/docs/en/solution-templates/microservice/built-in-features.md b/docs/en/solution-templates/microservice/built-in-features.md
index 62c2863d23..2454578211 100644
--- a/docs/en/solution-templates/microservice/built-in-features.md
+++ b/docs/en/solution-templates/microservice/built-in-features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the built-in features of the ABP Microservice Solution template to effectively build and manage distributed systems."
+}
+```
+
# Microservice Solution: Built-In Features
> You must have an ABP Business or a higher license to be able to create a microservice solution.
diff --git a/docs/en/solution-templates/microservice/communication.md b/docs/en/solution-templates/microservice/communication.md
index 8b2b3af9aa..08c1e92d1c 100644
--- a/docs/en/solution-templates/microservice/communication.md
+++ b/docs/en/solution-templates/microservice/communication.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore communication methods in ABP's microservice solution, covering synchronous and asynchronous patterns for seamless service interactions."
+}
+```
+
# Microservice Solution: Communication
> You must have an ABP Business or a higher license to be able to create a microservice solution.
diff --git a/docs/en/solution-templates/microservice/cors-configuration.md b/docs/en/solution-templates/microservice/cors-configuration.md
index 8157bb95ae..11a8741791 100644
--- a/docs/en/solution-templates/microservice/cors-configuration.md
+++ b/docs/en/solution-templates/microservice/cors-configuration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure CORS in ABP microservice solutions to enable secure cross-origin requests for your applications."
+}
+```
+
# Microservice Solution: CORS Configuration
````json
diff --git a/docs/en/solution-templates/microservice/database-configurations.md b/docs/en/solution-templates/microservice/database-configurations.md
index 6978cd0af2..644ee0748e 100644
--- a/docs/en/solution-templates/microservice/database-configurations.md
+++ b/docs/en/solution-templates/microservice/database-configurations.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore how to configure and manage databases in the ABP Microservice solution, focusing on Entity Framework and MongoDB integration."
+}
+```
+
# Microservice Solution: Database Configurations
````json
diff --git a/docs/en/solution-templates/microservice/distributed-cache.md b/docs/en/solution-templates/microservice/distributed-cache.md
index b35a00e8cb..fa785a98ba 100644
--- a/docs/en/solution-templates/microservice/distributed-cache.md
+++ b/docs/en/solution-templates/microservice/distributed-cache.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement distributed caching in ABP Framework microservice solutions using Redis for improved performance."
+}
+```
+
# Microservice Solution: Distributed Cache
````json
diff --git a/docs/en/solution-templates/microservice/distributed-events.md b/docs/en/solution-templates/microservice/distributed-events.md
index 3e1ba140f9..6b23f7cd05 100644
--- a/docs/en/solution-templates/microservice/distributed-events.md
+++ b/docs/en/solution-templates/microservice/distributed-events.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement asynchronous communication in microservices using the ABP Framework's Distributed Event Bus with RabbitMQ."
+}
+```
+
# Microservice Solution: Distributed Events
````json
diff --git a/docs/en/solution-templates/microservice/distributed-locking.md b/docs/en/solution-templates/microservice/distributed-locking.md
index 5902a391c1..4f39374a62 100644
--- a/docs/en/solution-templates/microservice/distributed-locking.md
+++ b/docs/en/solution-templates/microservice/distributed-locking.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement distributed locking in ABP Framework microservices using Redis to ensure safe operation execution across instances."
+}
+```
+
# Microservice Solution: Distributed Locking
````json
diff --git a/docs/en/solution-templates/microservice/feature-management.md b/docs/en/solution-templates/microservice/feature-management.md
index 0c90cb1705..b4d3cfa53d 100644
--- a/docs/en/solution-templates/microservice/feature-management.md
+++ b/docs/en/solution-templates/microservice/feature-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage features in your ABP microservice solution, including application configuration and user tenant details."
+}
+```
+
# Microservice Solution: Feature Management
````json
diff --git a/docs/en/solution-templates/microservice/grpc-calls.md b/docs/en/solution-templates/microservice/grpc-calls.md
index e8f9328a46..1903cce6fe 100644
--- a/docs/en/solution-templates/microservice/grpc-calls.md
+++ b/docs/en/solution-templates/microservice/grpc-calls.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement high-performance gRPC calls in your microservices with ABP Framework for efficient communication and scalability."
+}
+```
+
# Microservice Solution: gRPC Calls
````json
diff --git a/docs/en/solution-templates/microservice/guides.md b/docs/en/solution-templates/microservice/guides.md
index 9edeeef29e..3cfea420ab 100644
--- a/docs/en/solution-templates/microservice/guides.md
+++ b/docs/en/solution-templates/microservice/guides.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore comprehensive guides on building microservice solutions with ABP Framework, covering new services, applications, API gateways, and testing."
+}
+```
+
# Microservice Solution: Guides
> You must have an ABP Business or a higher license to be able to create a microservice solution.
diff --git a/docs/en/solution-templates/microservice/helm-charts-and-kubernetes.md b/docs/en/solution-templates/microservice/helm-charts-and-kubernetes.md
index fc7c2f92dc..46da70e88c 100644
--- a/docs/en/solution-templates/microservice/helm-charts-and-kubernetes.md
+++ b/docs/en/solution-templates/microservice/helm-charts-and-kubernetes.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to deploy your ABP microservice solution on Kubernetes using Helm charts, complete with a guide on folder structure and requirements."
+}
+```
+
# Microservice Solution: Helm Charts and Kubernetes
````json
diff --git a/docs/en/solution-templates/microservice/how-to-use-with-abp-suite.md b/docs/en/solution-templates/microservice/how-to-use-with-abp-suite.md
index 8549032089..83197367d1 100644
--- a/docs/en/solution-templates/microservice/how-to-use-with-abp-suite.md
+++ b/docs/en/solution-templates/microservice/how-to-use-with-abp-suite.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to leverage ABP Suite for visual solution design and code generation, streamlining your microservice development process."
+}
+```
+
# Microservice Solution: How to use with ABP Suite
ABP Suite provides a visual solution designer, code generators, and other tools to make your development process easier and faster.
diff --git a/docs/en/solution-templates/microservice/http-api-calls.md b/docs/en/solution-templates/microservice/http-api-calls.md
index 5a9dee0afd..6efa6055e0 100644
--- a/docs/en/solution-templates/microservice/http-api-calls.md
+++ b/docs/en/solution-templates/microservice/http-api-calls.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to enable HTTP API calls in your ABP microservice solution for seamless communication between services using Integration Services."
+}
+```
+
# Microservice Solution: HTTP API Calls
````json
diff --git a/docs/en/solution-templates/microservice/index.md b/docs/en/solution-templates/microservice/index.md
index 542f9e6021..9b4ed6b3a3 100644
--- a/docs/en/solution-templates/microservice/index.md
+++ b/docs/en/solution-templates/microservice/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Studio Microservice Solution Template to quickly build robust, integrated microservices with best practices and ready-to-use components."
+}
+```
+
# ABP Studio: Microservice Solution Template
````json
diff --git a/docs/en/solution-templates/microservice/localization-system.md b/docs/en/solution-templates/microservice/localization-system.md
index e11232236e..ebc710f840 100644
--- a/docs/en/solution-templates/microservice/localization-system.md
+++ b/docs/en/solution-templates/microservice/localization-system.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how the ABP Framework manages localization in microservice solutions, enhancing resource management across applications seamlessly."
+}
+```
+
# Microservice Solution: Localization System
````json
diff --git a/docs/en/solution-templates/microservice/logging.md b/docs/en/solution-templates/microservice/logging.md
index 41f7dc6861..1ad38a774b 100644
--- a/docs/en/solution-templates/microservice/logging.md
+++ b/docs/en/solution-templates/microservice/logging.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore how to implement structured logging in your ABP microservice solution using Serilog, ensuring efficient log management across services."
+}
+```
+
# Microservice Solution: Logging
````json
diff --git a/docs/en/solution-templates/microservice/main-components.md b/docs/en/solution-templates/microservice/main-components.md
index e2a0f1aaa9..119e2a71cd 100644
--- a/docs/en/solution-templates/microservice/main-components.md
+++ b/docs/en/solution-templates/microservice/main-components.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the main components of the ABP microservice solution, including applications, API gateways, and services for effective development."
+}
+```
+
# Microservice Solution: Main Components
```json
diff --git a/docs/en/solution-templates/microservice/microservices.md b/docs/en/solution-templates/microservice/microservices.md
index 4d2848dc93..1d270be615 100644
--- a/docs/en/solution-templates/microservice/microservices.md
+++ b/docs/en/solution-templates/microservice/microservices.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Microservice solution, including core microservices like Administration and Identity, to kickstart your scalable applications."
+}
+```
+
# Microservice Solution: The Microservices
````json
diff --git a/docs/en/solution-templates/microservice/mobile-applications.md b/docs/en/solution-templates/microservice/mobile-applications.md
index d3e8fe19d0..c14895b7b9 100644
--- a/docs/en/solution-templates/microservice/mobile-applications.md
+++ b/docs/en/solution-templates/microservice/mobile-applications.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore how to integrate mobile applications with ABP's microservice solution, featuring options like MAUI and React Native for seamless development."
+}
+```
+
# Microservice Solution: Mobile Applications
````json
diff --git a/docs/en/solution-templates/microservice/monitoring.md b/docs/en/solution-templates/microservice/monitoring.md
index 78ad83fa7b..e95df177de 100644
--- a/docs/en/solution-templates/microservice/monitoring.md
+++ b/docs/en/solution-templates/microservice/monitoring.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure monitoring for your microservice solution using Prometheus and Grafana to ensure system health and performance."
+}
+```
+
# Microservice Solution: Monitoring
````json
diff --git a/docs/en/solution-templates/microservice/mono-repo-vs-multiple-repository-approaches.md b/docs/en/solution-templates/microservice/mono-repo-vs-multiple-repository-approaches.md
index 0ed10d4b9d..68a1888e38 100644
--- a/docs/en/solution-templates/microservice/mono-repo-vs-multiple-repository-approaches.md
+++ b/docs/en/solution-templates/microservice/mono-repo-vs-multiple-repository-approaches.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the advantages of mono-repo vs. multiple repository approaches for microservices in ABP Framework, enhancing your development strategy."
+}
+```
+
# Microservice Solution: Mono-repo vs Multiple Repository Approaches
````json
diff --git a/docs/en/solution-templates/microservice/multi-tenancy.md b/docs/en/solution-templates/microservice/multi-tenancy.md
index a33d2fad7f..0b3ce5a4a6 100644
--- a/docs/en/solution-templates/microservice/multi-tenancy.md
+++ b/docs/en/solution-templates/microservice/multi-tenancy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement multi-tenancy in ABP Framework's microservice solutions, enabling seamless tenant isolation and management."
+}
+```
+
# Microservice Solution: Multi-Tenancy
````json
diff --git a/docs/en/solution-templates/microservice/overview.md b/docs/en/solution-templates/microservice/overview.md
index 8f9a0fbc7a..6f0e2e9399 100644
--- a/docs/en/solution-templates/microservice/overview.md
+++ b/docs/en/solution-templates/microservice/overview.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Microservice solution template for ABP Framework, featuring pre-installed libraries and services for seamless development and production."
+}
+```
+
# Microservice Solution: Overview
````json
diff --git a/docs/en/solution-templates/microservice/permission-management.md b/docs/en/solution-templates/microservice/permission-management.md
index d2d6f38eaf..e4e721a2cd 100644
--- a/docs/en/solution-templates/microservice/permission-management.md
+++ b/docs/en/solution-templates/microservice/permission-management.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage permissions in ABP's microservice solution, ensuring efficient access control across your applications."
+}
+```
+
# Microservice Solution: Permission Management
````json
diff --git a/docs/en/solution-templates/microservice/solution-structure.md b/docs/en/solution-templates/microservice/solution-structure.md
index c7e94830fb..90fd211136 100644
--- a/docs/en/solution-templates/microservice/solution-structure.md
+++ b/docs/en/solution-templates/microservice/solution-structure.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the folder structure of ABP Studio's microservice solution template, essential for effective project organization and development."
+}
+```
+
# Microservice Solution: The Structure
````json
diff --git a/docs/en/solution-templates/microservice/swagger-integration.md b/docs/en/solution-templates/microservice/swagger-integration.md
index 3ae77a031d..879ab61402 100644
--- a/docs/en/solution-templates/microservice/swagger-integration.md
+++ b/docs/en/solution-templates/microservice/swagger-integration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Swagger for API documentation in ABP Framework microservices, enhancing usability and client SDK generation."
+}
+```
+
# Microservice Solution: Swagger Integration
````json
diff --git a/docs/en/solution-templates/microservice/web-applications.md b/docs/en/solution-templates/microservice/web-applications.md
index 48918dbc09..6c50a7801a 100644
--- a/docs/en/solution-templates/microservice/web-applications.md
+++ b/docs/en/solution-templates/microservice/web-applications.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Framework's microservice solution template, featuring integrated web applications and API gateways for seamless development."
+}
+```
+
# Microservice Solution: Web Applications
````json
diff --git a/docs/en/solution-templates/single-layer-web-application/_index.md b/docs/en/solution-templates/single-layer-web-application/_index.md
index d5720f5602..e5883ec44f 100644
--- a/docs/en/solution-templates/single-layer-web-application/_index.md
+++ b/docs/en/solution-templates/single-layer-web-application/_index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Single Layer Application Solution Template to learn how to create a straightforward .NET solution structure with ease."
+}
+```
+
# Single Layer Application Solution Template
This template provides a simple solution structure with a single project. This document explains that solution structure in details.
diff --git a/docs/en/solution-templates/single-layer-web-application/authentication.md b/docs/en/solution-templates/single-layer-web-application/authentication.md
index 17a6f0f2c5..eaef43922d 100644
--- a/docs/en/solution-templates/single-layer-web-application/authentication.md
+++ b/docs/en/solution-templates/single-layer-web-application/authentication.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Single Layer solution for authentication using OpenIddict, offering a streamlined setup for developers with ABP Framework."
+}
+```
+
# Single Layer Solution: Authentication
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/background-jobs.md b/docs/en/solution-templates/single-layer-web-application/background-jobs.md
index 1a3d592a5e..3b4afbd0dc 100644
--- a/docs/en/solution-templates/single-layer-web-application/background-jobs.md
+++ b/docs/en/solution-templates/single-layer-web-application/background-jobs.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement and manage background jobs in your Single Layer solution using ABP Framework for efficient task handling."
+}
+```
+
# Single Layer Solution: Background Jobs
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/background-workers.md b/docs/en/solution-templates/single-layer-web-application/background-workers.md
index 15cad61797..929f478cf0 100644
--- a/docs/en/solution-templates/single-layer-web-application/background-workers.md
+++ b/docs/en/solution-templates/single-layer-web-application/background-workers.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement background workers in your application for efficient, long-running tasks that enhance performance and reliability."
+}
+```
+
# Single Layer Solution: Background Workers
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/blob-storing.md b/docs/en/solution-templates/single-layer-web-application/blob-storing.md
index d316c009c6..4c1d0fe3fd 100644
--- a/docs/en/solution-templates/single-layer-web-application/blob-storing.md
+++ b/docs/en/solution-templates/single-layer-web-application/blob-storing.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively store BLOBs in a single-layer solution with ABP Framework, enhancing your distributed systems capabilities."
+}
+```
+
# Single Layer Solution: BLOB Storing
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/built-in-features.md b/docs/en/solution-templates/single-layer-web-application/built-in-features.md
index 2700c1d8dd..9d9dd46f0e 100644
--- a/docs/en/solution-templates/single-layer-web-application/built-in-features.md
+++ b/docs/en/solution-templates/single-layer-web-application/built-in-features.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the built-in features of the Single Layer solution template to kickstart your web application development with ABP Framework."
+}
+```
+
# Single Layer Solution: Built-In Features
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/cors-configuration.md b/docs/en/solution-templates/single-layer-web-application/cors-configuration.md
index 71f1991e59..48dc8000f7 100644
--- a/docs/en/solution-templates/single-layer-web-application/cors-configuration.md
+++ b/docs/en/solution-templates/single-layer-web-application/cors-configuration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to configure CORS for single-layer solutions in ABP Framework, ensuring secure cross-origin requests for your web applications."
+}
+```
+
# Single Layer Solution: CORS Configuration
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/database-configurations.md b/docs/en/solution-templates/single-layer-web-application/database-configurations.md
index ec48fcf6f0..75d6639159 100644
--- a/docs/en/solution-templates/single-layer-web-application/database-configurations.md
+++ b/docs/en/solution-templates/single-layer-web-application/database-configurations.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage database configurations in ABP Framework's Single-Layer Solution, including connection string customization for various environments."
+}
+```
+
# Single Layer Solution: Database configurations
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/db-migrator.md b/docs/en/solution-templates/single-layer-web-application/db-migrator.md
index 988b16cef6..016e69b7e1 100644
--- a/docs/en/solution-templates/single-layer-web-application/db-migrator.md
+++ b/docs/en/solution-templates/single-layer-web-application/db-migrator.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to manage database migrations in a Single Layer solution with ABP Framework using scripts and commands for seamless operations."
+}
+```
+
# Single Layer Solution: Db Migrator
````json
diff --git a/docs/en/solution-templates/single-layer-web-application/distributed-locking.md b/docs/en/solution-templates/single-layer-web-application/distributed-locking.md
index f99adba265..e1eb6079e2 100644
--- a/docs/en/solution-templates/single-layer-web-application/distributed-locking.md
+++ b/docs/en/solution-templates/single-layer-web-application/distributed-locking.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement distributed locking in single-layer solutions with ABP Framework, ensuring synchronized access to shared resources."
+}
+```
+
# Single Layer Solution: Distributed Locking
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/index.md b/docs/en/solution-templates/single-layer-web-application/index.md
index ce295f20a9..22b2a6b244 100644
--- a/docs/en/solution-templates/single-layer-web-application/index.md
+++ b/docs/en/solution-templates/single-layer-web-application/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Studio Single Layer Solution Template for building monolithic systems efficiently, following DDD principles and best practices."
+}
+```
+
# ABP Studio: Single Layer Solution Template
````json
diff --git a/docs/en/solution-templates/single-layer-web-application/logging.md b/docs/en/solution-templates/single-layer-web-application/logging.md
index 5b3483822b..1a1ac06662 100644
--- a/docs/en/solution-templates/single-layer-web-application/logging.md
+++ b/docs/en/solution-templates/single-layer-web-application/logging.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement structured logging in ABP Framework using Serilog, with common configuration for easy integration."
+}
+```
+
# Single Layer Solution: Logging
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/main-components.md b/docs/en/solution-templates/single-layer-web-application/main-components.md
index d219c69155..606e83f97a 100644
--- a/docs/en/solution-templates/single-layer-web-application/main-components.md
+++ b/docs/en/solution-templates/single-layer-web-application/main-components.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the main components of the single-layer solution template, designed for building monolithic applications with ease and efficiency."
+}
+```
+
# Single Layer Solution: Main Components
````json
diff --git a/docs/en/solution-templates/single-layer-web-application/multi-tenancy.md b/docs/en/solution-templates/single-layer-web-application/multi-tenancy.md
index b2cd042d0e..632081d598 100644
--- a/docs/en/solution-templates/single-layer-web-application/multi-tenancy.md
+++ b/docs/en/solution-templates/single-layer-web-application/multi-tenancy.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore how multi-tenancy works in ABP Framework's single-layer solution, enabling isolated environments for multiple tenants."
+}
+```
+
# Single Layer Solution: Multi-Tenancy
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/overview.md b/docs/en/solution-templates/single-layer-web-application/overview.md
index 8592dc1e8a..a0e1e50093 100644
--- a/docs/en/solution-templates/single-layer-web-application/overview.md
+++ b/docs/en/solution-templates/single-layer-web-application/overview.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Single Layer solution template in ABP Framework, featuring pre-installed libraries and services for streamlined development and production."
+}
+```
+
# Single Layer Solution: Overview
````json
diff --git a/docs/en/solution-templates/single-layer-web-application/solution-structure.md b/docs/en/solution-templates/single-layer-web-application/solution-structure.md
index 45448b46b4..ffb085855f 100644
--- a/docs/en/solution-templates/single-layer-web-application/solution-structure.md
+++ b/docs/en/solution-templates/single-layer-web-application/solution-structure.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the folder structure of ABP Studio's single-layer solution template, essential for organizing your web application efficiently."
+}
+```
+
# Single Layer Solution: The Structure
````json
diff --git a/docs/en/solution-templates/single-layer-web-application/swagger-integration.md b/docs/en/solution-templates/single-layer-web-application/swagger-integration.md
index 6de24705ee..dd20999f3b 100644
--- a/docs/en/solution-templates/single-layer-web-application/swagger-integration.md
+++ b/docs/en/solution-templates/single-layer-web-application/swagger-integration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate Swagger with ABP Framework for effective API documentation and interaction in your single-layer applications."
+}
+```
+
# Single Layer Solution: Swagger Integration
```json
diff --git a/docs/en/solution-templates/single-layer-web-application/web-applications.md b/docs/en/solution-templates/single-layer-web-application/web-applications.md
index 94945ba757..f454b3630e 100644
--- a/docs/en/solution-templates/single-layer-web-application/web-applications.md
+++ b/docs/en/solution-templates/single-layer-web-application/web-applications.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the single-layer solution for web applications, featuring ASP.NET Core MVC and Angular options for building robust web apps."
+}
+```
+
# Single Layer Solution: Web Applications
````json
diff --git a/docs/en/studio/_notes-quick-start-microservice.md b/docs/en/studio/_notes-quick-start-microservice.md
index 8dec2ee08a..cc539f7e01 100644
--- a/docs/en/studio/_notes-quick-start-microservice.md
+++ b/docs/en/studio/_notes-quick-start-microservice.md
@@ -1,2 +1,9 @@
+```json
+//[doc-seo]
+{
+ "Description": "Quickly set up a microservice solution with our aligned wizard steps, guiding you through templates, frameworks, and configurations."
+}
+```
+
* Create new solution -> Microservice dialog
* Wizard steps are not aligned with the application template. True order can be: Solution Template -> Solution Properties -> UI Framework -> Mobile Framework -> Database Provider -> Database Configurations -> UI Theme -> Optional Modules (if we change that, the document flow should also be updated)
\ No newline at end of file
diff --git a/docs/en/studio/_notes.md b/docs/en/studio/_notes.md
index 41300c7a76..d3d3248e7b 100644
--- a/docs/en/studio/_notes.md
+++ b/docs/en/studio/_notes.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Framework documentation for a comprehensive guide on creating layered web applications with customizable options and configurations."
+}
+```
+
* Document Notes
* Quick Start: Creating a Layered Web Application
* **Disable the DEMO PLUGIN and re-take all screenshots**. Also, wait for the followings done:
diff --git a/docs/en/studio/_planning.md b/docs/en/studio/_planning.md
index 95eba552b3..4a175cda28 100644
--- a/docs/en/studio/_planning.md
+++ b/docs/en/studio/_planning.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Studio documentation for comprehensive guidance on installation, solution templates, and building modular applications with ease."
+}
+```
+
# ABP Studio Documentation Content Planning
* ~~[DONE] Installation~~
diff --git a/docs/en/studio/concepts.md b/docs/en/studio/concepts.md
index 995519e191..1e6afb4fab 100644
--- a/docs/en/studio/concepts.md
+++ b/docs/en/studio/concepts.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore essential concepts and terms used in ABP Studio to enhance your understanding and streamline your development experience."
+}
+```
+
# ABP Studio Concepts
````json
diff --git a/docs/en/studio/index.md b/docs/en/studio/index.md
index ccac3c375d..9b2fc0d36c 100644
--- a/docs/en/studio/index.md
+++ b/docs/en/studio/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover ABP Studio, a cross-platform tool that simplifies .NET development by automating tasks and providing valuable insights for your projects."
+}
+```
+
# ABP Studio
````json
diff --git a/docs/en/studio/installation.md b/docs/en/studio/installation.md
index 8da2fa79d7..1b1ba2cf04 100644
--- a/docs/en/studio/installation.md
+++ b/docs/en/studio/installation.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to install ABP Studio, including system requirements and optional tools, to kickstart your development with ABP Framework."
+}
+```
+
# Installing ABP Studio
This document explains how to install the ABP Studio tool.
diff --git a/docs/en/studio/kubernetes.md b/docs/en/studio/kubernetes.md
index f05a30ee04..ae23989f6c 100644
--- a/docs/en/studio/kubernetes.md
+++ b/docs/en/studio/kubernetes.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to manage your applications in a Kubernetes cluster using ABP Studio, perfect for both microservices and monolithic projects."
+}
+```
+
# ABP Studio: Working with Kubernetes
````json
diff --git a/docs/en/studio/monitoring-applications.md b/docs/en/studio/monitoring-applications.md
index be0387c5bb..75390bf904 100644
--- a/docs/en/studio/monitoring-applications.md
+++ b/docs/en/studio/monitoring-applications.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP Studio's centralized monitoring solution to effectively oversee your applications, track performance, and collect telemetry data seamlessly."
+}
+```
+
# ABP Studio: Monitoring Applications
````json
diff --git a/docs/en/studio/overview.md b/docs/en/studio/overview.md
index ecfdda52bc..3f5835c998 100644
--- a/docs/en/studio/overview.md
+++ b/docs/en/studio/overview.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP Studio's key features like Solution Explorer and Kubernetes Integration to optimize your ABP application development and management."
+}
+```
+
# ABP Studio: Overview
````json
diff --git a/docs/en/studio/release-notes.md b/docs/en/studio/release-notes.md
index 3ea73d9111..b0627a887e 100644
--- a/docs/en/studio/release-notes.md
+++ b/docs/en/studio/release-notes.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the latest features and enhancements in ABP Studio with release notes detailing major updates and improvements for developers."
+}
+```
+
# ABP Studio Release Notes
This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version.
diff --git a/docs/en/studio/running-applications.md b/docs/en/studio/running-applications.md
index 40b73a1e0a..c922c1b501 100644
--- a/docs/en/studio/running-applications.md
+++ b/docs/en/studio/running-applications.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to use the ABP Studio's Solution Runner to efficiently run applications and organize projects with customizable profiles."
+}
+```
+
# ABP Studio: Running Applications
````json
diff --git a/docs/en/studio/solution-explorer.md b/docs/en/studio/solution-explorer.md
index df0ca04a4f..21dde505e5 100644
--- a/docs/en/studio/solution-explorer.md
+++ b/docs/en/studio/solution-explorer.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP Studio's Solution Explorer for managing projects and understanding your solution structure with clarity."
+}
+```
+
# ABP Studio: Solution Explorer
````json
diff --git a/docs/en/studio/version-mapping.md b/docs/en/studio/version-mapping.md
index fbbf68c769..6bd879f2ab 100644
--- a/docs/en/studio/version-mapping.md
+++ b/docs/en/studio/version-mapping.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the version mappings between ABP Studio and ABP Solution Templates to streamline your development process and ensure compatibility."
+}
+```
+
# ABP Studio and ABP Startup Template Version Mappings
This document provides a general overview of the relationship between various versions of ABP Studio and the ABP version of the [ABP Solution Templates](../solution-templates/index.md) used when generating a new solution. Each version of ABP Studio is configured to create solutions with a specific ABP version. However, once a solution is created, you can easily update it to the latest version of ABP via ABP Studio or [ABP CLI](../cli/index.md#update).
diff --git a/docs/en/studio/working-with-suite.md b/docs/en/studio/working-with-suite.md
index ceb7d8c924..b436b7b0f8 100644
--- a/docs/en/studio/working-with-suite.md
+++ b/docs/en/studio/working-with-suite.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to seamlessly integrate and run ABP Suite within ABP Studio, enhancing your development workflow with unified access and efficiency."
+}
+```
+
# ABP Studio: Working with ABP Suite
````json
diff --git a/docs/en/suite/add-solution.md b/docs/en/suite/add-solution.md
index e318a45f98..f98f142e66 100644
--- a/docs/en/suite/add-solution.md
+++ b/docs/en/suite/add-solution.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to add an existing ABP solution to ABP Suite, enabling seamless project management and development integration."
+}
+```
+
# Adding existing ABP solution
````json
diff --git a/docs/en/suite/configuration.md b/docs/en/suite/configuration.md
index 0852fdd8a2..e650f556ab 100644
--- a/docs/en/suite/configuration.md
+++ b/docs/en/suite/configuration.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize ABP Suite's directory and file paths through the configuration file for optimal project management."
+}
+```
+
# ABP Suite configuration
ABP Suite automatically finds your project directories, but when you customize your solution, you can change the directories and file paths from the Suite configuration file. The configuration file is located
diff --git a/docs/en/suite/create-module-solution.md b/docs/en/suite/create-module-solution.md
index 90edd18f5f..e5cba3140c 100644
--- a/docs/en/suite/create-module-solution.md
+++ b/docs/en/suite/create-module-solution.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create a new ABP module solution using ABP Suite with step-by-step guidance and helpful visuals for a seamless setup."
+}
+```
+
# Creating a new ABP module solution
````json
diff --git a/docs/en/suite/create-solution.md b/docs/en/suite/create-solution.md
index a87e73b480..39d3fb925e 100644
--- a/docs/en/suite/create-solution.md
+++ b/docs/en/suite/create-solution.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create a new ABP solution using ABP Studio or ABP CLI, and discover how to generate CRUD pages seamlessly."
+}
+```
+
# Creating a new ABP solution
````json
diff --git a/docs/en/suite/creating-many-to-many-relationship.md b/docs/en/suite/creating-many-to-many-relationship.md
index 49b1760ded..f711c2a891 100644
--- a/docs/en/suite/creating-many-to-many-relationship.md
+++ b/docs/en/suite/creating-many-to-many-relationship.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create many-to-many relationships in ABP Suite using navigation collections for efficient CRUD page management."
+}
+```
+
# Creating Many-To-Many Relationship
````json
diff --git a/docs/en/suite/creating-master-detail-relationship.md b/docs/en/suite/creating-master-detail-relationship.md
index 84e418c0f5..b1d8874d5b 100644
--- a/docs/en/suite/creating-master-detail-relationship.md
+++ b/docs/en/suite/creating-master-detail-relationship.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to establish Master-Detail relationships in your applications, enhancing data organization and management with ABP Framework."
+}
+```
+
# Master-Detail Relationship
````json
diff --git a/docs/en/suite/customizing-the-generated-code.md b/docs/en/suite/customizing-the-generated-code.md
index 4c0cc688a6..e5061ca700 100644
--- a/docs/en/suite/customizing-the-generated-code.md
+++ b/docs/en/suite/customizing-the-generated-code.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize generated code in ABP Suite, preserve changes, and utilize hook points for seamless CRUD page generation."
+}
+```
+
# Customizing the Generated Code
ABP Suite allows you to customize the generated code blocks and preserve your custom code changes in the next CRUD Page Generation. It specifies hook points to allow adding custom code blocks. Then, the code written by you to these hook points will be respected and will not be overridden in the next CRUD Page Generation.
diff --git a/docs/en/suite/editing-templates.md b/docs/en/suite/editing-templates.md
index 4a555568bb..9c859ba0de 100644
--- a/docs/en/suite/editing-templates.md
+++ b/docs/en/suite/editing-templates.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to edit templates in ABP Suite, customize code generation for UI frameworks and database providers to fit your project needs."
+}
+```
+
# Editing templates
ABP Suite uses templates to generate the code files. You can see the template files by clicking "Edit Templates" menu item.
diff --git a/docs/en/suite/generating-crud-page.md b/docs/en/suite/generating-crud-page.md
index 00c5ca07a2..cc9df3ee32 100644
--- a/docs/en/suite/generating-crud-page.md
+++ b/docs/en/suite/generating-crud-page.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to efficiently generate a CRUD page in ABP Framework, enhancing your development process with streamlined entity management."
+}
+```
+
# Generating a CRUD page
````json
diff --git a/docs/en/suite/generating-entities-from-an-existing-database-table.md b/docs/en/suite/generating-entities-from-an-existing-database-table.md
index 481bd32ff5..df1a836af4 100644
--- a/docs/en/suite/generating-entities-from-an-existing-database-table.md
+++ b/docs/en/suite/generating-entities-from-an-existing-database-table.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to generate CRUD pages from existing database tables using ABP Suite, streamlining your development process with ease."
+}
+```
+
# Generating CRUD Pages From an Existing Database Table
````json
diff --git a/docs/en/suite/how-to-install.md b/docs/en/suite/how-to-install.md
index bff1bc6e1f..d89460dbb9 100644
--- a/docs/en/suite/how-to-install.md
+++ b/docs/en/suite/how-to-install.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to install ABP Suite easily, ensuring you’re set up for seamless development with the ABP Framework."
+}
+```
+
# How to install ABP Suite?
````json
diff --git a/docs/en/suite/how-to-start.md b/docs/en/suite/how-to-start.md
index b8469ce26b..da839ac1e8 100644
--- a/docs/en/suite/how-to-start.md
+++ b/docs/en/suite/how-to-start.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to start ABP Suite seamlessly with ABP Studio or via command line, enhancing your development experience with ease."
+}
+```
+
# How to start ABP Suite?
````json
diff --git a/docs/en/suite/how-to-uninstall.md b/docs/en/suite/how-to-uninstall.md
index dfe197528e..87a4de71f1 100644
--- a/docs/en/suite/how-to-uninstall.md
+++ b/docs/en/suite/how-to-uninstall.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to uninstall ABP Suite effectively with step-by-step terminal commands and clean-up instructions for a seamless experience."
+}
+```
+
# How to uninstall ABP Suite?
You can simply uninstall ABP Suite with the terminal command:
diff --git a/docs/en/suite/index.md b/docs/en/suite/index.md
index 1c99ed7198..20005ecb21 100644
--- a/docs/en/suite/index.md
+++ b/docs/en/suite/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover ABP Suite, a powerful .NET Core tool for quickly building web pages and generating CRUD applications with ease."
+}
+```
+
# ABP Suite
````json
diff --git a/docs/en/suite/solution-structure.md b/docs/en/suite/solution-structure.md
index ad6a2d69e6..d36ea35e7f 100644
--- a/docs/en/suite/solution-structure.md
+++ b/docs/en/suite/solution-structure.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the ABP Framework's solution structure, detailing project organization, dependencies, and shared domain elements for efficient development."
+}
+```
+
# Solution structure
You will get a slightly different solution structure, based on the options you have specified.
diff --git a/docs/en/suite/source-code.md b/docs/en/suite/source-code.md
index 7a2d2dbe36..93585e0853 100644
--- a/docs/en/suite/source-code.md
+++ b/docs/en/suite/source-code.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to access and integrate module source code into your ABP Framework solution using ABP Suite for enhanced customization and development."
+}
+```
+
# Accessing Source Code Of Modules
**If your [license plan](https://abp.io/pricing) allows you to access the source code of [modules](https://abp.io/modules)**, you can use ABP Suite to download the source code and add downloaded source code of modules to your solution structure.
diff --git a/docs/en/suite/updating-packages.md b/docs/en/suite/updating-packages.md
index 7d8590ac6f..d8d39349e0 100644
--- a/docs/en/suite/updating-packages.md
+++ b/docs/en/suite/updating-packages.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Easily update NPM and NuGet packages in your ABP Suite solution with a simple scan of your project files for seamless version management."
+}
+```
+
# Updating packages
ABP Suite allows you to update `NPM` and `NuGet` packages in a solution.
diff --git a/docs/en/testing/integration-tests.md b/docs/en/testing/integration-tests.md
index ac524be05a..dce7813e45 100644
--- a/docs/en/testing/integration-tests.md
+++ b/docs/en/testing/integration-tests.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively write integration tests using ABP's pre-configured infrastructure, ensuring reliable application performance and database interactions."
+}
+```
+
# Integration Tests
````json
diff --git a/docs/en/testing/overall.md b/docs/en/testing/overall.md
index b174b9ecbc..154c169d5b 100644
--- a/docs/en/testing/overall.md
+++ b/docs/en/testing/overall.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP Framework's automated testing strategies, including unit, integration, and UI tests, to enhance your application's reliability and performance."
+}
+```
+
# Automated Testing
````json
diff --git a/docs/en/testing/ui-tests.md b/docs/en/testing/ui-tests.md
index c784c7dde2..ac9e6eb91f 100644
--- a/docs/en/testing/ui-tests.md
+++ b/docs/en/testing/ui-tests.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to implement UI Tests with ABP Framework, covering Non Visual and Visual Tests for various UI technologies like MVC, Angular, and Blazor."
+}
+```
+
# UI Tests
````json
diff --git a/docs/en/testing/unit-tests.md b/docs/en/testing/unit-tests.md
index b7c0ff10ca..cfc63a4848 100644
--- a/docs/en/testing/unit-tests.md
+++ b/docs/en/testing/unit-tests.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to effectively write unit tests in ABP Framework, including strategies for testing classes with and without dependencies."
+}
+```
+
# Unit Tests
````json
diff --git a/docs/en/tools.md b/docs/en/tools.md
index cf3053b48f..d503f0d0cb 100644
--- a/docs/en/tools.md
+++ b/docs/en/tools.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's powerful tools like CLI, Suite, and Studio to boost your development productivity and streamline your workflow."
+}
+```
+
# Tools
ABP provides a comprehensive set of tools designed to enhance the development experience and improve productivity:
diff --git a/docs/en/tutorials/book-store-with-abp-suite/index.md b/docs/en/tutorials/book-store-with-abp-suite/index.md
index bc52fb75da..9a2f9372b7 100644
--- a/docs/en/tutorials/book-store-with-abp-suite/index.md
+++ b/docs/en/tutorials/book-store-with-abp-suite/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build a web application with ABP Suite, automating code generation for your Acme.BookStore project. Perfect for ABP Team members!"
+}
+```
+
# Web Application Development Tutorial (with ABP Suite)
````json
diff --git a/docs/en/tutorials/book-store-with-abp-suite/part-01.md b/docs/en/tutorials/book-store-with-abp-suite/part-01.md
index 30cec4441a..da40c77db6 100644
--- a/docs/en/tutorials/book-store-with-abp-suite/part-01.md
+++ b/docs/en/tutorials/book-store-with-abp-suite/part-01.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create a new web application solution using ABP Suite, with step-by-step guidance tailored for MVC, Blazor, and various databases."
+}
+```
+
# Web Application Development Tutorial (with ABP Suite) - Part 1: Creating the Solution
````json
diff --git a/docs/en/tutorials/book-store-with-abp-suite/part-02.md b/docs/en/tutorials/book-store-with-abp-suite/part-02.md
index 0dd87aec07..11725201cb 100644
--- a/docs/en/tutorials/book-store-with-abp-suite/part-02.md
+++ b/docs/en/tutorials/book-store-with-abp-suite/part-02.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create a `Book` entity and generate CRUD pages effortlessly using ABP Suite in this web app development tutorial."
+}
+```
+
# Web Application Development Tutorial (with ABP Suite) - Part 2: Creating the Books
````json
@@ -38,7 +45,7 @@ After clicking the related command, pre-integrated browser of ABP Studio should
## Creating the Book Entity
-Before creating the `Book` entity, first we can create a `BookType` enum in the `Acme.BookStore.Domain.Shared` project under the **Books** folder as follows:
+Before creating the `Book` entity, we need to create a `BookType` enum. This enum will be used as a property type in ABP Suite while defining the entity. So, open your code editor, create a new file named `BookType.cs` in the `Acme.BookStore.Domain.Shared\Books` folder and add the following content:
```csharp
namespace Acme.BookStore.Books;
@@ -57,7 +64,7 @@ public enum BookType
}
```
-After creating an _enum_ file in your project, you can define it as a property while creating the entity. ABP Suite asks for an enum path to read the enum file, and set the namespace, and enum name in the generated code accordingly. Then, you can create the `Book` entity with some properties.
+After creating the _enum_ file in your project, you can use it as a property type when creating entities in ABP Suite. When you specify an enum property, ABP Suite will prompt you to provide the path to the enum file. It then reads the file and automatically sets the namespace and enum name in the generated code. Now, let's create the `Book` entity with its properties.
Type `Book` for the *Name* field and leave the other options as is. ABP Suite automatically calculates proper values for the rest of the inputs for you:
@@ -128,10 +135,12 @@ It will take some time to complete the process. After the process is completed,
{{ end }}
-After the application is started, you can right-click and *Browse* on the application to open it in the ABP Studio's pre-integrated browser. After logging in using the default credentials (`admin` / `1q2w3E*`), you can see the Books page in the following figure with a single record:
+After the application is started, you can right-click and *Browse* on the application to open it in the ABP Studio's pre-integrated browser. After logging in using the default credentials (`admin` / `1q2w3E*`), you can see the Books page like in the following figure:

+> By default, ABP Suite doesn't generate data seed contributors for entities, as you'll need to create them manually. This is intentional since having dummy data in development or production environments may not be suitable for your specific needs. However, if you selected the **Create unit & integration tests** option while creating the entity, you can see the sample data-seed contributors under the *Acme.BookStore.Domain.Tests* project to simplify the testing process by having initial data for the entities, which we will see in [the part 4 of this tutorial](part-04.md).
+
On this page, you can create a new book, update an existing book, delete a book, export all records (or the filtered records) to excel, filter the records by using the advanced filter section, bulk delete multiple records and so on.
## Summary
diff --git a/docs/en/tutorials/book-store-with-abp-suite/part-03.md b/docs/en/tutorials/book-store-with-abp-suite/part-03.md
index 4399910fb5..ca93f67f9b 100644
--- a/docs/en/tutorials/book-store-with-abp-suite/part-03.md
+++ b/docs/en/tutorials/book-store-with-abp-suite/part-03.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create the Author entity in your web application using ABP Suite, enhancing your project with one-to-many relationships effortlessly."
+}
+```
+
# Web Application Development Tutorial (with ABP Suite) - Part 3: Creating the Authors
````json
diff --git a/docs/en/tutorials/book-store-with-abp-suite/part-04.md b/docs/en/tutorials/book-store-with-abp-suite/part-04.md
index 77b99ac4e4..ca8f85eef7 100644
--- a/docs/en/tutorials/book-store-with-abp-suite/part-04.md
+++ b/docs/en/tutorials/book-store-with-abp-suite/part-04.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to establish a one-to-many relationship between Book and Author entities in your ABP Suite application with this step-by-step tutorial."
+}
+```
+
# Web Application Development Tutorial (with ABP Suite) - Part 4: Book to Author Relation
````json
diff --git a/docs/en/tutorials/book-store-with-abp-suite/part-05.md b/docs/en/tutorials/book-store-with-abp-suite/part-05.md
index 0283ce2425..73a1d9c348 100644
--- a/docs/en/tutorials/book-store-with-abp-suite/part-05.md
+++ b/docs/en/tutorials/book-store-with-abp-suite/part-05.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize generated code in ABP Suite, preserving your changes for future CRUD page generations. Enhance your web app effortlessly!"
+}
+```
+
# Web Application Development Tutorial (with ABP Suite) - Part 5: Customizing the Generated Code
````json
diff --git a/docs/en/tutorials/book-store/index.md b/docs/en/tutorials/book-store/index.md
index 178aa75214..a06c8cb45e 100644
--- a/docs/en/tutorials/book-store/index.md
+++ b/docs/en/tutorials/book-store/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build a web application using ABP Framework with this step-by-step tutorial series on managing books and authors."
+}
+```
+
# Web Application Development Tutorial
````json
//[doc-params]
diff --git a/docs/en/tutorials/book-store/part-01.md b/docs/en/tutorials/book-store/part-01.md
index 4634a68c67..a90b7ae828 100644
--- a/docs/en/tutorials/book-store/part-01.md
+++ b/docs/en/tutorials/book-store/part-01.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create the server side of your web application with ABP Framework, including setting up your solution and installing client-side packages."
+}
+```
+
# Web Application Development Tutorial - Part 1: Creating the Server Side
````json
//[doc-params]
diff --git a/docs/en/tutorials/book-store/part-02.md b/docs/en/tutorials/book-store/part-02.md
index e0a869c79f..750808fe4d 100644
--- a/docs/en/tutorials/book-store/part-02.md
+++ b/docs/en/tutorials/book-store/part-02.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore Part 2 of our Web Application Development Tutorial, focusing on the Book List Page and leveraging dynamic JavaScript proxies in ABP Framework."
+}
+```
+
# Web Application Development Tutorial - Part 2: The Book List Page
````json
//[doc-params]
@@ -515,7 +522,7 @@ Now you can see the final result on your browser:

-{{else if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp"}}
+{{else if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp" || UI == "MAUIBlazor"}}
## Create a Books Page
diff --git a/docs/en/tutorials/book-store/part-03.md b/docs/en/tutorials/book-store/part-03.md
index ae96f8a8e0..546b4a743d 100644
--- a/docs/en/tutorials/book-store/part-03.md
+++ b/docs/en/tutorials/book-store/part-03.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create, update, and delete books in your web application using MVC, Blazor, or Angular with ABP Framework in this tutorial."
+}
+```
+
# Web Application Development Tutorial - Part 3: Creating, Updating and Deleting Books
````json
//[doc-params]
diff --git a/docs/en/tutorials/book-store/part-04.md b/docs/en/tutorials/book-store/part-04.md
index fba15db253..9d97344cae 100644
--- a/docs/en/tutorials/book-store/part-04.md
+++ b/docs/en/tutorials/book-store/part-04.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to implement server-side integration tests in your ABP Framework web applications, ensuring robust functionality across various UIs and databases."
+}
+```
+
# Web Application Development Tutorial - Part 4: Integration Tests
````json
//[doc-params]
diff --git a/docs/en/tutorials/book-store/part-05.md b/docs/en/tutorials/book-store/part-05.md
index 0f84a945d3..b7b05103c9 100644
--- a/docs/en/tutorials/book-store/part-05.md
+++ b/docs/en/tutorials/book-store/part-05.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement a robust authorization system in your web applications using ABP Framework, including managing permissions for roles and users."
+}
+```
+
# Web Application Development Tutorial - Part 5: Authorization
````json
//[doc-params]
diff --git a/docs/en/tutorials/book-store/part-06.md b/docs/en/tutorials/book-store/part-06.md
index d24b68f569..14dfec694c 100644
--- a/docs/en/tutorials/book-store/part-06.md
+++ b/docs/en/tutorials/book-store/part-06.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to implement the domain layer for authors in your web app using ABP Framework, enhancing your development efficiency and structure."
+}
+```
+
# Web Application Development Tutorial - Part 6: Authors: Domain Layer
````json
//[doc-params]
diff --git a/docs/en/tutorials/book-store/part-07.md b/docs/en/tutorials/book-store/part-07.md
index 92108c4a35..b0fc37fefa 100644
--- a/docs/en/tutorials/book-store/part-07.md
+++ b/docs/en/tutorials/book-store/part-07.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate the database for the Author entity in your web application using EF and various UI frameworks in this tutorial."
+}
+```
+
# Web Application Development Tutorial - Part 7: Authors: Database Integration
````json
//[doc-params]
diff --git a/docs/en/tutorials/book-store/part-08.md b/docs/en/tutorials/book-store/part-08.md
index ac49c6aee4..68796b99eb 100644
--- a/docs/en/tutorials/book-store/part-08.md
+++ b/docs/en/tutorials/book-store/part-08.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build the application layer for the Author entity in this tutorial, enhancing your skills with ABP Framework's structured approach."
+}
+```
+
# Web Application Development Tutorial - Part 8: Authors: Application Layer
````json
//[doc-params]
diff --git a/docs/en/tutorials/book-store/part-09.md b/docs/en/tutorials/book-store/part-09.md
index 95de6ccd61..c30b018494 100644
--- a/docs/en/tutorials/book-store/part-09.md
+++ b/docs/en/tutorials/book-store/part-09.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build a CRUD interface for the Author entity in your web app using ABP Framework, featuring MVC, Blazor, and more!"
+}
+```
+
# Web Application Development Tutorial - Part 9: Authors: User Interface
````json
//[doc-params]
diff --git a/docs/en/tutorials/book-store/part-10.md b/docs/en/tutorials/book-store/part-10.md
index ccb6755468..5e0235ad14 100644
--- a/docs/en/tutorials/book-store/part-10.md
+++ b/docs/en/tutorials/book-store/part-10.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to establish a 1 to N relationship between Book and Author entities in your ABP Framework application with this step-by-step tutorial."
+}
+```
+
# Web Application Development Tutorial - Part 10: Book to Author Relation
````json
//[doc-params]
diff --git a/docs/en/tutorials/index.md b/docs/en/tutorials/index.md
index 0572ea33aa..b96192d76f 100644
--- a/docs/en/tutorials/index.md
+++ b/docs/en/tutorials/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP tutorials to quickly build applications, apply DDD practices, and leverage ABP Suite for efficient development. Perfect for all developers!"
+}
+```
+
# ABP Tutorials
The following introductory tutorials explain how to build applications based on the ABP platform:
diff --git a/docs/en/tutorials/microservice/index.md b/docs/en/tutorials/microservice/index.md
index 76715d9b5e..938d9b9108 100644
--- a/docs/en/tutorials/microservice/index.md
+++ b/docs/en/tutorials/microservice/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build microservice solutions with ABP Framework, starting from creating services to API gateway integration. Perfect for developers!"
+}
+```
+
# Microservice Development Tutorial
````json
diff --git a/docs/en/tutorials/microservice/part-01.md b/docs/en/tutorials/microservice/part-01.md
index 8e741b9a47..a3529019a5 100644
--- a/docs/en/tutorials/microservice/part-01.md
+++ b/docs/en/tutorials/microservice/part-01.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create your initial microservice solution with ABP Framework, using Entity Framework Core and SQL Server in this tutorial."
+}
+```
+
# Microservice Tutorial Part 01: Creating the Initial Solution
````json
diff --git a/docs/en/tutorials/microservice/part-02.md b/docs/en/tutorials/microservice/part-02.md
index f54ee4fe56..230296e3a4 100644
--- a/docs/en/tutorials/microservice/part-02.md
+++ b/docs/en/tutorials/microservice/part-02.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create and integrate a Catalog service into your microservice solution with this step-by-step tutorial."
+}
+```
+
# Microservice Tutorial Part 02: Creating the initial Catalog service
````json
diff --git a/docs/en/tutorials/microservice/part-03.md b/docs/en/tutorials/microservice/part-03.md
index f75b3bd23f..a7dd0c7c4e 100644
--- a/docs/en/tutorials/microservice/part-03.md
+++ b/docs/en/tutorials/microservice/part-03.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to build the Catalog service in a microservice architecture using ABP Suite, streamlining product management with automatic code generation."
+}
+```
+
# Microservice Tutorial Part 03: Building the Catalog service
````json
diff --git a/docs/en/tutorials/microservice/part-04.md b/docs/en/tutorials/microservice/part-04.md
index 0cae944d07..90bcf58d20 100644
--- a/docs/en/tutorials/microservice/part-04.md
+++ b/docs/en/tutorials/microservice/part-04.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create the initial Ordering microservice using ABP Framework, building on the Catalog service from the previous tutorial."
+}
+```
+
# Microservice Tutorial Part 04: Creating the initial Ordering service
````json
diff --git a/docs/en/tutorials/microservice/part-05.md b/docs/en/tutorials/microservice/part-05.md
index 26bd3e3306..24da71a716 100644
--- a/docs/en/tutorials/microservice/part-05.md
+++ b/docs/en/tutorials/microservice/part-05.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build the Ordering microservice step-by-step, implementing core functionalities and creating the Order entity without ABP Suite."
+}
+```
+
# Microservice Tutorial Part 05: Building the Ordering service
````json
diff --git a/docs/en/tutorials/microservice/part-06.md b/docs/en/tutorials/microservice/part-06.md
index f268ba6fff..bf54602936 100644
--- a/docs/en/tutorials/microservice/part-06.md
+++ b/docs/en/tutorials/microservice/part-06.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate microservices using HTTP API calls in ABP Framework, enhancing communication between services for seamless functionality."
+}
+```
+
# Microservice Tutorial Part 06: Integrating the services: HTTP API Calls
````json
diff --git a/docs/en/tutorials/microservice/part-07.md b/docs/en/tutorials/microservice/part-07.md
index 620d49f6c5..5dc638dd04 100644
--- a/docs/en/tutorials/microservice/part-07.md
+++ b/docs/en/tutorials/microservice/part-07.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate microservices using distributed events with ABP Framework for efficient inter-process communication."
+}
+```
+
# Microservice Tutorial Part 07: Integrating the services: Using Distributed Events
````json
diff --git a/docs/en/tutorials/mobile/index.md b/docs/en/tutorials/mobile/index.md
index 51db427363..4a487f84bc 100644
--- a/docs/en/tutorials/mobile/index.md
+++ b/docs/en/tutorials/mobile/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build a mobile bookstore app with step-by-step tutorials for .NET MAUI or React Native, following your web development journey!"
+}
+```
+
# Mobile Application Development Tutorial: Book Store Application
> You must have an ABP Team or a higher license to be able to create a mobile application.
diff --git a/docs/en/tutorials/mobile/maui/index.md b/docs/en/tutorials/mobile/maui/index.md
index c9bb520e57..fcd337f141 100644
--- a/docs/en/tutorials/mobile/maui/index.md
+++ b/docs/en/tutorials/mobile/maui/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to develop a MAUI mobile app with ABP Framework, focusing on UI and CRUD operations using the MVVM pattern."
+}
+```
+
# Mobile Application Development Tutorial - MAUI
## About This Tutorial
diff --git a/docs/en/tutorials/mobile/react-native/index.md b/docs/en/tutorials/mobile/react-native/index.md
index 76b4e59983..5b43df18e6 100644
--- a/docs/en/tutorials/mobile/react-native/index.md
+++ b/docs/en/tutorials/mobile/react-native/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to develop a mobile application using React Native with ABP Framework, focusing on UI for the Acme.BookStore app."
+}
+```
+
# Mobile Application Development Tutorial - React Native
React Native mobile option is *available for* ***Team*** *or higher licenses*. Therefore, if you don't have a commercial license, it's suggested to follow the article by downloading the source code of the sample application as described in the next chapter.
diff --git a/docs/en/tutorials/modular-crm/index.md b/docs/en/tutorials/modular-crm/index.md
index 0d16f81a9a..856fe7957f 100644
--- a/docs/en/tutorials/modular-crm/index.md
+++ b/docs/en/tutorials/modular-crm/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build modular web applications with ABP Framework in this tutorial, focusing on creating and communicating application modules."
+}
+```
+
# Modular Monolith Application Development Tutorial
````json
diff --git a/docs/en/tutorials/modular-crm/part-01.md b/docs/en/tutorials/modular-crm/part-01.md
index c3dfb50f22..862f5ecc6b 100644
--- a/docs/en/tutorials/modular-crm/part-01.md
+++ b/docs/en/tutorials/modular-crm/part-01.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create an initial solution for a Modular CRM application using ASP.NET Core MVC and Entity Framework Core with ABP Framework."
+}
+```
+
# Creating the Initial Solution
````json
diff --git a/docs/en/tutorials/modular-crm/part-02.md b/docs/en/tutorials/modular-crm/part-02.md
index 383f5bd2a9..9e715b6c30 100644
--- a/docs/en/tutorials/modular-crm/part-02.md
+++ b/docs/en/tutorials/modular-crm/part-02.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create and organize a product management module within your CRM application using ABP Framework in this step-by-step guide."
+}
+```
+
# Setting Up the Catalog Module
````json
diff --git a/docs/en/tutorials/modular-crm/part-03.md b/docs/en/tutorials/modular-crm/part-03.md
index bbb0339b50..36b418c7fb 100644
--- a/docs/en/tutorials/modular-crm/part-03.md
+++ b/docs/en/tutorials/modular-crm/part-03.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to create entities, services, and a basic UI for the products module in ABP Framework, focusing on modularity for effective development."
+}
+```
+
# Building the Catalog Module
````json
diff --git a/docs/en/tutorials/modular-crm/part-04.md b/docs/en/tutorials/modular-crm/part-04.md
index ea3147d97d..bc2fa9fa4c 100644
--- a/docs/en/tutorials/modular-crm/part-04.md
+++ b/docs/en/tutorials/modular-crm/part-04.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create and integrate an Ordering module in your CRM application using ABP Framework’s Standard Module template."
+}
+```
+
# Creating the Initial Ordering Module
````json
diff --git a/docs/en/tutorials/modular-crm/part-05.md b/docs/en/tutorials/modular-crm/part-05.md
index 46a693a963..fa3c2769a4 100644
--- a/docs/en/tutorials/modular-crm/part-05.md
+++ b/docs/en/tutorials/modular-crm/part-05.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to build the Ordering Module by creating an Order entity and adding functionality to manage orders in your ABP Framework application."
+}
+```
+
# Building the Ordering Module
````json
diff --git a/docs/en/tutorials/modular-crm/part-06.md b/docs/en/tutorials/modular-crm/part-06.md
index 1c04cd56d1..c4ad6a5e6f 100644
--- a/docs/en/tutorials/modular-crm/part-06.md
+++ b/docs/en/tutorials/modular-crm/part-06.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to integrate modules in ABP Framework by implementing integration services for seamless communication between Products and Orders modules."
+}
+```
+
# Integrating the Modules: Implementing Integration Services
````json
diff --git a/docs/en/tutorials/modular-crm/part-07.md b/docs/en/tutorials/modular-crm/part-07.md
index 49eb24b71f..454c62d780 100644
--- a/docs/en/tutorials/modular-crm/part-07.md
+++ b/docs/en/tutorials/modular-crm/part-07.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate modules using messaging in ABP Framework, enabling loose coupling and efficient communication between components."
+}
+```
+
# Integrating the Modules: Communication via Messages (Events)
````json
diff --git a/docs/en/tutorials/modular-crm/part-08.md b/docs/en/tutorials/modular-crm/part-08.md
index 0046f3d82d..d4a78a6b53 100644
--- a/docs/en/tutorials/modular-crm/part-08.md
+++ b/docs/en/tutorials/modular-crm/part-08.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to perform database-level JOINs on multiple modules in ABP Framework, enhancing data integration and modularity."
+}
+```
+
# Integrating the Modules: Joining the Products and Orders Data
````json
diff --git a/docs/en/tutorials/todo/index.md b/docs/en/tutorials/todo/index.md
index 3cd91cb515..bcd642e81b 100644
--- a/docs/en/tutorials/todo/index.md
+++ b/docs/en/tutorials/todo/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to quickly build a simple application using ABP Framework with our easy-to-follow tutorial on single-layer and layered solutions."
+}
+```
+
# TODO Application Tutorial
**Welcome to the ABP**. This is a single-part, quick-start tutorial to build a simple application. Start with this tutorial if you want to quickly understand how ABP works.
diff --git a/docs/en/tutorials/todo/layered/index.md b/docs/en/tutorials/todo/layered/index.md
index b990704c7a..08c463e81c 100644
--- a/docs/en/tutorials/todo/layered/index.md
+++ b/docs/en/tutorials/todo/layered/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build a simple todo application using the ABP Framework with this quick-start tutorial, complete with source code and video guide!"
+}
+```
+
# TODO Application Tutorial with Layered Solution
````json
@@ -54,11 +61,11 @@ This documentation has a video tutorial on **YouTube**!! You can watch it here:
* An IDE (e.g. [Visual Studio](https://visualstudio.microsoft.com/vs/)) that supports [.NET 9.0+](https://dotnet.microsoft.com/download/dotnet) development.
* [Node v20.11+](https://nodejs.org/)
-
+{{if DB=="EF"}}
+* [SQL Server Express LocalDB](https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/sql-server-express-localdb)
+{{end}}
{{if DB=="Mongo"}}
-
* [MongoDB Server 4.0+](https://docs.mongodb.com/manual/administration/install-community/)
-
{{end}}
## Install ABP CLI Tool
@@ -115,7 +122,7 @@ abp install-libs
{{if UI=="MVC" || UI=="BlazorServer" || UI=="BlazorWebApp"}}
-It is good to run the application before starting the development. Ensure the {{if UI=="BlazorServer"}}`TodoApp.Blazor`{{else}}`TodoApp.Web`{{end}} project is the startup project, then run the application (Ctrl+F5 in Visual Studio) to see the initial UI:
+It is good to run the application before starting the development. Ensure the {{if UI=="Blazor" || UI=="BlazorServer" || UI=="BlazorWebApp"}}`TodoApp.Blazor`{{else}}`TodoApp.Web`{{end}} project is the startup project, then run the application (Ctrl+F5 in Visual Studio) to see the initial UI:
{{else if UI=="Blazor" || UI=="MAUIBlazor"}}
@@ -165,7 +172,7 @@ All ready. We can start coding!
## Domain Layer
-This application has a single [entity](../../../framework/architecture/domain-driven-design/entities.md) and we'll start by creating it. Create a new `TodoItem` class inside the *TodoApp.Domain* project:
+This application has a single [entity](../../../framework/architecture/domain-driven-design/entities.md) and we'll start by creating it. Create a new `TodoItem` class inside the *TodoApp.Domain* project under the `Entities` folder, as shown below:
````csharp
using System;
@@ -578,7 +585,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
{{if UI=="Blazor" || UI=="BlazorWebApp"}}
-namespace TodoApp.Blazor.Client.Pages;
+amespace TodoApp.Blazor.Client.Pages
{{else if UI=="BlazorServer"}}
namespace TodoApp.Blazor.Pages;
{{else if UI=="MAUIBlazor"}}
@@ -756,6 +763,7 @@ import { TodoItemDto, TodoService } from '@proxy';
@Component({
selector: 'app-home',
+ standalone: false,
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
diff --git a/docs/en/tutorials/todo/single-layer/index.md b/docs/en/tutorials/todo/single-layer/index.md
index a823e91dc0..16206b9bd7 100644
--- a/docs/en/tutorials/todo/single-layer/index.md
+++ b/docs/en/tutorials/todo/single-layer/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn to build a simple todo application using the ABP Framework in this quick-start tutorial, featuring multiple UI and database options."
+}
+```
+
# TODO Application Tutorial with Single-Layer Solution
````json
@@ -50,11 +57,11 @@ This documentation has a video tutorial on **YouTube**!! You can watch it here:
* An IDE (e.g. [Visual Studio](https://visualstudio.microsoft.com/vs/)) that supports [.NET 9.0+](https://dotnet.microsoft.com/download/dotnet) development.
* [Node v20.11+](https://nodejs.org/)
-
+{{if DB=="EF"}}
+* [SQL Server Express LocalDB](https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/sql-server-express-localdb)
+{{end}}
{{if DB=="Mongo"}}
-
* [MongoDB Server 4.0+](https://docs.mongodb.com/manual/administration/install-community/)
-
{{end}}
## Creating a New Solution
diff --git a/docs/en/ui-themes/basic-theme/index.md b/docs/en/ui-themes/basic-theme/index.md
index f1d1a3d39c..c87491d1b4 100644
--- a/docs/en/ui-themes/basic-theme/index.md
+++ b/docs/en/ui-themes/basic-theme/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the Basic Theme, a minimalist foundation for customizing Bootstrap styles across MVC, Blazor, and Angular UIs in your ABP Framework projects."
+}
+```
+
# Basic Theme
The Basic Theme is a minimalist theme that doesn't add any styling on top of the plain [Bootstrap](https://getbootstrap.com/) styles. You can take the Basic Theme as the base theme and build your own theme or styling on top of it. Here, a screenshot from the theme:
diff --git a/docs/en/ui-themes/index.md b/docs/en/ui-themes/index.md
index 8c16677e47..2beaa0dc05 100644
--- a/docs/en/ui-themes/index.md
+++ b/docs/en/ui-themes/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore ABP's official theming system, featuring the LeptonX and Basic themes, to enhance your application's UI effortlessly."
+}
+```
+
# The Official Themes
ABP provides a complete UI theming system. While you can build your own themes, you can directly use the following pre-built themes in your applications.
diff --git a/docs/en/ui-themes/lepton-x-lite/angular.md b/docs/en/ui-themes/lepton-x-lite/angular.md
index 4abe6c86ff..1ab5212462 100644
--- a/docs/en/ui-themes/lepton-x-lite/angular.md
+++ b/docs/en/ui-themes/lepton-x-lite/angular.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to install and use the LeptonX Lite Angular UI theme for ABP Framework, enhancing your project's professional look effortlessly."
+}
+```
+
# LeptonX Lite Angular UI
LeptonX Lite has implementation for the ABP Angular Client. It's a simplified variation of the [LeptonX Theme](https://x.leptontheme.com/).
diff --git a/docs/en/ui-themes/lepton-x-lite/asp-net-core.md b/docs/en/ui-themes/lepton-x-lite/asp-net-core.md
index dfe431176b..8b152175ac 100644
--- a/docs/en/ui-themes/lepton-x-lite/asp-net-core.md
+++ b/docs/en/ui-themes/lepton-x-lite/asp-net-core.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement the LeptonX Lite MVC UI theme in your ABP applications for a sleek, professional look."
+}
+```
+
# LeptonX Lite MVC UI
LeptonX Lite has implementation for the ABP Razor Pages. It's a simplified variation of the [LeptonX Theme](https://x.leptontheme.com/).
diff --git a/docs/en/ui-themes/lepton-x-lite/blazor.md b/docs/en/ui-themes/lepton-x-lite/blazor.md
index 3f9a7ce7a5..7190ac1fc2 100644
--- a/docs/en/ui-themes/lepton-x-lite/blazor.md
+++ b/docs/en/ui-themes/lepton-x-lite/blazor.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to implement the LeptonX Lite Blazor UI for your ABP applications, featuring easy installation and professional design."
+}
+```
+
# LeptonX Lite Blazor UI
````json
diff --git a/docs/en/ui-themes/lepton-x-lite/index.md b/docs/en/ui-themes/lepton-x-lite/index.md
index 2fc30ca7ec..1302f66a3a 100644
--- a/docs/en/ui-themes/lepton-x-lite/index.md
+++ b/docs/en/ui-themes/lepton-x-lite/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the LeptonX Lite Theme, the default UI for new ABP solutions, with guides for MVC, Blazor, and Angular UI types."
+}
+```
+
# LeptonX Lite Theme
This is the official and default UI theme when you create a new free ABP solution. It is a lite version of the [LeptonX Theme](../lepton-x). See the following documents based on the UI type you are using:
diff --git a/docs/en/ui-themes/lepton-x/angular-customization.md b/docs/en/ui-themes/lepton-x/angular-customization.md
index 4189ed6cba..ccef281d52 100644
--- a/docs/en/ui-themes/lepton-x/angular-customization.md
+++ b/docs/en/ui-themes/lepton-x/angular-customization.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to customize layouts in the Angular version of LeptonX, including pre-defined layouts and component replacement for your UI."
+}
+```
+
# Customization
### Layouts
diff --git a/docs/en/ui-themes/lepton-x/angular.md b/docs/en/ui-themes/lepton-x/angular.md
index af1713cec8..efafbe442d 100644
--- a/docs/en/ui-themes/lepton-x/angular.md
+++ b/docs/en/ui-themes/lepton-x/angular.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to integrate the LeptonX Angular UI into your project with step-by-step instructions and essential configuration tips."
+}
+```
+
# LeptonX Angular UI
To add `LeptonX` into your existing projects, follow the steps below.
diff --git a/docs/en/ui-themes/lepton-x/angular/how-to-add-a-new-variation-to-lepton-x-for-angular.md b/docs/en/ui-themes/lepton-x/angular/how-to-add-a-new-variation-to-lepton-x-for-angular.md
index dc858715d0..885a897fbf 100644
--- a/docs/en/ui-themes/lepton-x/angular/how-to-add-a-new-variation-to-lepton-x-for-angular.md
+++ b/docs/en/ui-themes/lepton-x/angular/how-to-add-a-new-variation-to-lepton-x-for-angular.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to add a new appearance to LeptonX for Angular by defining a custom theme and integrating it seamlessly into your project."
+}
+```
+
# How to Add a New Appearance to LeptonX for Angular
LeptonX has four appearances: light, dim, dark, and system. You can add a new appearance to LeptonX for Angular. In this document, we will show you how to add a new appearance to LeptonX for Angular.
diff --git a/docs/en/ui-themes/lepton-x/angular/how-to-change-default-theme-option.md b/docs/en/ui-themes/lepton-x/angular/how-to-change-default-theme-option.md
index 264091b561..19325dac13 100644
--- a/docs/en/ui-themes/lepton-x/angular/how-to-change-default-theme-option.md
+++ b/docs/en/ui-themes/lepton-x/angular/how-to-change-default-theme-option.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to easily configure the default theme for your LeptonX application using the ThemeLeptonXModule for a personalized visual experience."
+}
+```
+
# Configuring the Default Theme for LeptonX
The LeptonX theme offers multiple appearances to suit your application's visual style. You can easily configure the default theme for your application using the `provideThemeLeptonX` provided by LeptonX.
diff --git a/docs/en/ui-themes/lepton-x/blazor.md b/docs/en/ui-themes/lepton-x/blazor.md
index 2287b5aeac..29e8deb6c3 100644
--- a/docs/en/ui-themes/lepton-x/blazor.md
+++ b/docs/en/ui-themes/lepton-x/blazor.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to easily implement the LeptonX Blazor UI theme in your ABP applications with straightforward installation steps."
+}
+```
+
# LeptonX Blazor UI
````json
diff --git a/docs/en/ui-themes/lepton-x/comparison-obsolete.md b/docs/en/ui-themes/lepton-x/comparison-obsolete.md
index e14dcfc368..49f49aa18e 100644
--- a/docs/en/ui-themes/lepton-x/comparison-obsolete.md
+++ b/docs/en/ui-themes/lepton-x/comparison-obsolete.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the feature set of LeptonX, comparing standalone and ABP options for HTML, Angular, and Blazor frameworks."
+}
+```
+
# Feature Set
### Frontend Choices
diff --git a/docs/en/ui-themes/lepton-x/how-to-use-lepton-x-components-with-angular-custom-layout.md b/docs/en/ui-themes/lepton-x/how-to-use-lepton-x-components-with-angular-custom-layout.md
index 57cdcd0ec9..934506dbd3 100644
--- a/docs/en/ui-themes/lepton-x/how-to-use-lepton-x-components-with-angular-custom-layout.md
+++ b/docs/en/ui-themes/lepton-x/how-to-use-lepton-x-components-with-angular-custom-layout.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to create and implement custom layouts using Lepton X components in Angular applications for enhanced UI flexibility."
+}
+```
+
# Custom layout usage with Lepton X components
diff --git a/docs/en/ui-themes/lepton-x/index.md b/docs/en/ui-themes/lepton-x/index.md
index e2b09358a4..6cac738f69 100644
--- a/docs/en/ui-themes/lepton-x/index.md
+++ b/docs/en/ui-themes/lepton-x/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the LeptonX Theme for ABP: a professional, responsive theme built on Bootstrap 5, offering various styles and easy installation."
+}
+```
+
# LeptonX Theme Module
> You must have an ABP Team or a higher license to use this theme.
diff --git a/docs/en/ui-themes/lepton-x/mvc.md b/docs/en/ui-themes/lepton-x/mvc.md
index e41d12a331..392af280fe 100644
--- a/docs/en/ui-themes/lepton-x/mvc.md
+++ b/docs/en/ui-themes/lepton-x/mvc.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover how to easily implement the LeptonX MVC UI theme in your ABP project with step-by-step installation instructions."
+}
+```
+
# LeptonX MVC UI
LeptonX theme is implemented and ready to use with ABP. No custom implementation is needed for Razor Pages.
diff --git a/docs/en/ui-themes/lepton-x/source-files.md b/docs/en/ui-themes/lepton-x/source-files.md
index cd980cb343..66d2bff3cb 100644
--- a/docs/en/ui-themes/lepton-x/source-files.md
+++ b/docs/en/ui-themes/lepton-x/source-files.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Explore the structure of Lepton X SCSS files, designed for efficient theme management and style optimization in your projects."
+}
+```
+
# Lepton X SCSS Files
The LeptonX scss file structure is divided into different bundles. The purpose of this is to exclude unnecessary styles (for example, the top menu layer styles when using side menu layout) in the project. To reload only relevant files on theme changes.
diff --git a/docs/en/ui-themes/lepton/customizing-lepton-theme.md b/docs/en/ui-themes/lepton/customizing-lepton-theme.md
index d626fd2769..eb8c36ed2b 100644
--- a/docs/en/ui-themes/lepton/customizing-lepton-theme.md
+++ b/docs/en/ui-themes/lepton/customizing-lepton-theme.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Learn how to customize the Lepton Theme in your ABP application with custom CSS, enhancing your website's appearance effortlessly."
+}
+```
+
# Customize Lepton Theme with Custom CSS
````json
@@ -38,9 +45,16 @@ export const appConfig: ApplicationConfig = {
Import your style file to `src/style.scss`
-```css
+```scss
+/* style.scss */
+@import 'your-custom-style';
+```
+
+or
+
+```scss
/* style.scss */
-import 'your-custom-style';
+@use 'your-custom-style';
```
Or add your style file to the `styles` arrays which in `angular.json` file
diff --git a/docs/en/ui-themes/lepton/index.md b/docs/en/ui-themes/lepton/index.md
index ed5c222c39..3a61bcde1c 100644
--- a/docs/en/ui-themes/lepton/index.md
+++ b/docs/en/ui-themes/lepton/index.md
@@ -1,3 +1,10 @@
+```json
+//[doc-seo]
+{
+ "Description": "Discover the Lepton Theme for ABP: a responsive, Bootstrap 5-compatible theme with multiple styles and easy installation options."
+}
+```
+
# Lepton Theme Module
> You must have an ABP Team or a higher license to use this theme.
diff --git a/framework/Volo.Abp.slnx b/framework/Volo.Abp.slnx
index f4c0d2b373..3d74af9f95 100644
--- a/framework/Volo.Abp.slnx
+++ b/framework/Volo.Abp.slnx
@@ -1,5 +1,7 @@
+
+
@@ -164,8 +166,6 @@
-
-
@@ -173,6 +173,7 @@
+
@@ -255,4 +256,4 @@
-
\ No newline at end of file
+
diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs
index 81d3866199..82a8148679 100644
--- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs
+++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/AbpAIModule.cs
@@ -34,6 +34,7 @@ public class AbpAIModule : AbpModule
}
context.Services.TryAddTransient(typeof(IChatClient<>), typeof(TypedChatClient<>));
+ context.Services.TryAddTransient(typeof(IChatClientAccessor<>), typeof(ChatClientAccessor<>));
context.Services.TryAddTransient(typeof(IKernelAccessor<>), typeof(KernelAccessor<>));
}
@@ -99,5 +100,19 @@ public class AbpAIModule : AbpModule
sp => sp.GetRequiredKeyedService(serviceName)
);
}
+
+ if (workspaceConfig.Kernel.Builder is null)
+ {
+ context.Services.AddKeyedTransient(
+ AbpAIWorkspaceOptions.GetKernelServiceKeyName(workspaceConfig.Name),
+ (sp, _) =>
+ {
+ var chatClient = sp.GetRequiredKeyedService(serviceName);
+ var builder = Kernel.CreateBuilder();
+ builder.Services.AddSingleton(chatClient);
+ return builder.Build();
+ }
+ );
+ }
}
}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientAccessor.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientAccessor.cs
index 1a852838fc..247e6e354e 100644
--- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientAccessor.cs
+++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/ChatClientAccessor.cs
@@ -5,9 +5,9 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AI;
-[Dependency(ReplaceServices = true, TryRegister = true)]
+[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IChatClientAccessor))]
-public class ChatClientAccessor : IChatClientAccessor
+public class ChatClientAccessor : IChatClientAccessor, ITransientDependency
{
public IChatClient? ChatClient { get; }
@@ -19,8 +19,6 @@ public class ChatClientAccessor : IChatClientAccessor
}
}
-[Dependency(ReplaceServices = true, TryRegister = true)]
-[ExposeServices(typeof(IChatClientAccessor))]
public class ChatClientAccessor : IChatClientAccessor
where TWorkSpace : class
{
diff --git a/framework/src/Volo.Abp.AI/Volo/Abp/AI/DefaultKernelAccessor.cs b/framework/src/Volo.Abp.AI/Volo/Abp/AI/DefaultKernelAccessor.cs
index 5370a41dd1..11e8587045 100644
--- a/framework/src/Volo.Abp.AI/Volo/Abp/AI/DefaultKernelAccessor.cs
+++ b/framework/src/Volo.Abp.AI/Volo/Abp/AI/DefaultKernelAccessor.cs
@@ -13,6 +13,8 @@ public class DefaultKernelAccessor : IKernelAccessor, ITransientDependency
public DefaultKernelAccessor(IServiceProvider serviceProvider)
{
Kernel = serviceProvider.GetKeyedService(
- AbpAIModule.DefaultWorkspaceName);
+ AbpAIWorkspaceOptions.GetKernelServiceKeyName(
+ AbpAIModule.DefaultWorkspaceName
+ ));
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCachedApplicationConfigurationClient.cs
index e4a2f8a3cc..7d615dc185 100644
--- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCachedApplicationConfigurationClient.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCachedApplicationConfigurationClient.cs
@@ -1,14 +1,11 @@
-using System;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Authorization;
-using Microsoft.JSInterop;
using Volo.Abp.AspNetCore.Components.Web.Security;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies;
using Volo.Abp.AspNetCore.Mvc.Client;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
-using Volo.Abp.Timing;
namespace Volo.Abp.AspNetCore.Components.MauiBlazor
{
@@ -22,33 +19,21 @@ namespace Volo.Abp.AspNetCore.Components.MauiBlazor
protected ICurrentTenantAccessor CurrentTenantAccessor { get; }
- protected ICurrentTimezoneProvider CurrentTimezoneProvider { get; }
-
protected ApplicationConfigurationChangedService ApplicationConfigurationChangedService { get; }
- protected IJSRuntime JSRuntime { get; }
-
- protected IClock Clock { get; }
-
public MauiBlazorCachedApplicationConfigurationClient(
AbpApplicationConfigurationClientProxy applicationConfigurationClientProxy,
ApplicationConfigurationCache cache,
ICurrentTenantAccessor currentTenantAccessor,
- ICurrentTimezoneProvider currentTimezoneProvider,
AuthenticationStateProvider authenticationStateProvider,
AbpApplicationLocalizationClientProxy applicationLocalizationClientProxy,
- ApplicationConfigurationChangedService applicationConfigurationChangedService,
- IJSRuntime jsRuntime,
- IClock clock)
+ ApplicationConfigurationChangedService applicationConfigurationChangedService)
{
ApplicationConfigurationClientProxy = applicationConfigurationClientProxy;
Cache = cache;
CurrentTenantAccessor = currentTenantAccessor;
- CurrentTimezoneProvider = currentTimezoneProvider;
ApplicationLocalizationClientProxy = applicationLocalizationClientProxy;
ApplicationConfigurationChangedService = applicationConfigurationChangedService;
- JSRuntime = jsRuntime;
- Clock = clock;
authenticationStateProvider.AuthenticationStateChanged += async _ => { await InitializeAsync(); };
}
@@ -78,15 +63,6 @@ namespace Volo.Abp.AspNetCore.Components.MauiBlazor
configurationDto.CurrentTenant.Id,
configurationDto.CurrentTenant.Name);
- if (Clock.SupportsMultipleTimezone)
- {
- CurrentTimezoneProvider.TimeZone = !configurationDto.Timing.TimeZone.Iana.TimeZoneName.IsNullOrWhiteSpace()
- ? configurationDto.Timing.TimeZone.Iana.TimeZoneName
- : await JSRuntime.InvokeAsync("abp.clock.getBrowserTimeZone");
-
- await JSRuntime.InvokeAsync("abp.clock.setBrowserTimeZoneToCookie");
- }
-
ApplicationConfigurationChangedService.NotifyChanged();
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCurrentTimezoneService.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCurrentTimezoneService.cs
new file mode 100644
index 0000000000..fadbe57eb9
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCurrentTimezoneService.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.JSInterop;
+using Volo.Abp.AspNetCore.Mvc.Client;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Timing;
+
+namespace Volo.Abp.AspNetCore.Components.MauiBlazor;
+
+public class MauiBlazorCurrentTimezoneService : ITransientDependency
+{
+ protected IClock Clock { get; }
+ protected ICachedApplicationConfigurationClient ApplicationConfigurationClient { get; }
+ protected IJSRuntime JsRuntime { get; }
+ protected ICurrentTimezoneProvider CurrentTimezoneProvider { get; }
+
+ public MauiBlazorCurrentTimezoneService(
+ IClock clock,
+ ICachedApplicationConfigurationClient applicationConfigurationClient,
+ IJSRuntime jsRuntime,
+ ICurrentTimezoneProvider currentTimezoneProvider)
+ {
+ Clock = clock;
+ ApplicationConfigurationClient = applicationConfigurationClient;
+ JsRuntime = jsRuntime;
+ CurrentTimezoneProvider = currentTimezoneProvider;
+ }
+
+ public virtual async Task InitializeAsync()
+ {
+ if (Clock.SupportsMultipleTimezone)
+ {
+ var configurationDto = await ApplicationConfigurationClient.GetAsync();
+ CurrentTimezoneProvider.TimeZone = !configurationDto.Timing.TimeZone.Iana.TimeZoneName.IsNullOrEmpty()
+ ? configurationDto.Timing.TimeZone.Iana.TimeZoneName
+ : await JsRuntime.InvokeAsync("abp.clock.getBrowserTimeZone");
+
+ await JsRuntime.InvokeAsync("abp.clock.setBrowserTimeZoneToCookie");
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelper.cs
index 0135d136ba..a9cdd76200 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelper.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelper.cs
@@ -12,6 +12,11 @@ public class AbpRadioInputTagHelper : AbpTagHelper
{
private readonly IAbpTagHelperLocalizer _tagHelperLocalizer;
-
- public AbpRadioInputTagHelperService(IAbpTagHelperLocalizer tagHelperLocalizer)
+ private readonly IHtmlGenerator _generator;
+ private readonly HtmlEncoder _encoder;
+ private readonly IStringLocalizerFactory _stringLocalizerFactory;
+ private readonly IAbpEnumLocalizer _abpEnumLocalizer;
+
+ public AbpRadioInputTagHelperService(
+ IAbpTagHelperLocalizer tagHelperLocalizer,
+ IHtmlGenerator generator,
+ HtmlEncoder encoder,
+ IStringLocalizerFactory stringLocalizerFactory,
+ IAbpEnumLocalizer abpEnumLocalizer)
{
_tagHelperLocalizer = tagHelperLocalizer;
+ _generator = generator;
+ _encoder = encoder;
+ _stringLocalizerFactory = stringLocalizerFactory;
+ _abpEnumLocalizer = abpEnumLocalizer;
}
- public override void Process(TagHelperContext context, TagHelperOutput output)
+ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var selectItems = GetSelectItems(context, output);
SetSelectedValue(context, output, selectItems);
var order = TagHelper.AspFor.ModelExplorer.GetDisplayOrder();
- var html = GetHtml(context, output, selectItems);
+ var html = await GetRadioInputGroupAsHtmlAsync(context, output, selectItems);
AddGroupToFormGroupContents(context, TagHelper.AspFor.Name, html, order, out var suppress);
@@ -44,6 +62,21 @@ public class AbpRadioInputTagHelperService : AbpTagHelperService GetRadioInputGroupAsHtmlAsync(TagHelperContext context, TagHelperOutput output, List selectItems)
+ {
+ var radioGroupHtml = GetHtml(context, output, selectItems);
+ var label = await GetLabelAsHtmlAsync(context, output);
+ var infoText = GetInfoAsHtml(context, output);
+
+ var tagBuilder = new TagBuilder("div");
+ tagBuilder.AddCssClass("mb-3");
+ tagBuilder.InnerHtml.AppendHtml(label);
+ tagBuilder.InnerHtml.AppendHtml(radioGroupHtml);
+ tagBuilder.InnerHtml.AppendHtml(infoText);
+
+ return tagBuilder.ToHtmlString();
+ }
+
protected virtual string GetHtml(TagHelperContext context, TagHelperOutput output, List selectItems)
{
var html = new StringBuilder("");
@@ -77,14 +110,92 @@ public class AbpRadioInputTagHelperService : AbpTagHelperService GetLabelAsHtmlAsync(TagHelperContext context, TagHelperOutput output)
+ {
+ if (TagHelper.SuppressLabel)
+ {
+ return string.Empty;
+ }
+
+ if (string.IsNullOrEmpty(TagHelper.Label))
+ {
+ return await GetLabelAsHtmlUsingTagHelperAsync(context, output);
+ }
+
+ var label = new TagBuilder("label");
+ label.AddCssClass("form-label");
+ label.InnerHtml.AppendHtml(TagHelper.Label);
+ label.InnerHtml.AppendHtml(GetRequiredSymbol(context, output));
+
+ return label.ToHtmlString();
+ }
+
+ protected virtual async Task GetLabelAsHtmlUsingTagHelperAsync(TagHelperContext context, TagHelperOutput output)
+ {
+ var labelTagHelper = new LabelTagHelper(_generator)
+ {
+ For = TagHelper.AspFor,
+ ViewContext = TagHelper.ViewContext,
+ };
+
+ var innerOutput = await labelTagHelper.ProcessAndGetOutputAsync(
+ new TagHelperAttributeList { { "class", "form-label" } },
+ context,
+ "label",
+ TagMode.StartTagAndEndTag);
+
+ innerOutput.Content.AppendHtml(GetRequiredSymbol(context, output));
+
+ return innerOutput.Render(_encoder);
+ }
+
+ protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output)
+ {
+ var isHaveRequiredAttribute = context.AllAttributes.Any(a => a.Name == "required");
+
+ return TagHelper.AspFor.ModelExplorer.GetAttribute() != null || isHaveRequiredAttribute
+ ? " * "
+ : "";
+ }
+
+ protected virtual string GetInfoAsHtml(TagHelperContext context, TagHelperOutput output)
+ {
+ var text = string.Empty;
+ var infoAttribute = TagHelper.AspFor.ModelExplorer.GetAttribute();
+
+ if (!string.IsNullOrEmpty(TagHelper.InfoText))
+ {
+ text = TagHelper.InfoText!;
+ }
+ else if (infoAttribute != null)
+ {
+ text = _tagHelperLocalizer.GetLocalizedText(infoAttribute.Text, TagHelper.AspFor.ModelExplorer);
+ }
+ else
+ {
+ return "";
+ }
+
+ var small = new TagBuilder("small");
+ small.Attributes.Add("id", TagHelper.AspFor.Name.Replace('.', '_') + "InfoText");
+ small.AddCssClass("form-text");
+ small.InnerHtml.Append(text);
+
+ return small.ToHtmlString();
}
protected virtual List GetSelectItems(TagHelperContext context, TagHelperOutput output)
@@ -110,10 +221,32 @@ public class AbpRadioInputTagHelperService : AbpTagHelperService GetSelectItemsFromEnum(TagHelperContext context, TagHelperOutput output, ModelExplorer explorer)
{
- var localizer = _tagHelperLocalizer.GetLocalizerOrNull(explorer);
+ var selectItems = new List();
+ var isNullableType = Nullable.GetUnderlyingType(explorer.ModelType) != null;
+ var enumType = explorer.ModelType;
+
+ if (isNullableType)
+ {
+ enumType = Nullable.GetUnderlyingType(explorer.ModelType)!;
+ selectItems.Add(new SelectListItem());
+ }
+
+ var containerLocalizer = _tagHelperLocalizer.GetLocalizerOrNull(explorer.Container.ModelType.Assembly);
- var selectItems = explorer.Metadata.IsEnum ? explorer.ModelType.GetTypeInfo().GetMembers(BindingFlags.Public | BindingFlags.Static)
- .Select((t, i) => new SelectListItem { Value = i.ToString(), Text = GetLocalizedPropertyName(localizer, explorer.ModelType, t.Name) }).ToList() : new List();
+ foreach (var enumValue in enumType.GetEnumValuesAsUnderlyingType())
+ {
+ var localizedMemberName = _abpEnumLocalizer.GetString(enumType, enumValue,
+ new[]
+ {
+ containerLocalizer,
+ _stringLocalizerFactory.CreateDefaultOrNull()
+ }!);
+ selectItems.Add(new SelectListItem
+ {
+ Value = enumValue.ToString(),
+ Text = localizedMemberName
+ });
+ }
return selectItems;
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js
index 63f514b4c4..19759d3fa0 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/sweetalert2/abp-sweetalert2.js
@@ -29,6 +29,12 @@ var abp = abp || {};
title: 'Are you sure?',
showCancelButton: true,
reverseButtons: true
+ },
+ prompt: {
+ icon: 'question',
+ input: 'text',
+ showCancelButton: true,
+ reverseButtons: true
}
}
};
@@ -92,13 +98,43 @@ var abp = abp || {};
);
return $.Deferred(function ($dfd) {
- Swal.fire(opts).then(result => {
+ Swal.fire(opts).then(result => {
callback && callback(result.value);
$dfd.resolve(result.value);
})
});
};
+ abp.message.prompt = function (message, titleOrOptionsOrCallback, callback) {
+
+ var userOpts = {
+ html: abp.utils.htmlEscape(message).replace(/\n/g, ' ')
+ };
+
+ if ($.isFunction(titleOrOptionsOrCallback)) {
+ callback = titleOrOptionsOrCallback;
+ } else if (typeof titleOrOptionsOrCallback === 'string') {
+ userOpts.title = titleOrOptionsOrCallback;
+ } else if ($.isPlainObject(titleOrOptionsOrCallback)) {
+ userOpts = $.extend(userOpts, titleOrOptionsOrCallback);
+ }
+
+ var opts = $.extend(
+ {},
+ abp.libs.sweetAlert.config['default'],
+ abp.libs.sweetAlert.config.prompt,
+ userOpts
+ );
+
+ return $.Deferred(function ($dfd) {
+ Swal.fire(opts).then(function (result) {
+ var value = result && result.isConfirmed ? result.value : null;
+ callback && callback(value);
+ $dfd.resolve(value);
+ });
+ });
+ };
+
abp.event.on('abp.configurationInitialized', function () {
var l = abp.localization.getResource('AbpUi');
diff --git a/framework/src/Volo.Abp.BlobStoring.Minio/Microsoft/Extensions/DependencyInjection/MinioHttpClientFactoryServiceCollectionExtensions.cs b/framework/src/Volo.Abp.BlobStoring.Minio/Microsoft/Extensions/DependencyInjection/MinioHttpClientFactoryServiceCollectionExtensions.cs
new file mode 100644
index 0000000000..8838a1a7f1
--- /dev/null
+++ b/framework/src/Volo.Abp.BlobStoring.Minio/Microsoft/Extensions/DependencyInjection/MinioHttpClientFactoryServiceCollectionExtensions.cs
@@ -0,0 +1,18 @@
+using System.Net.Http;
+
+namespace Microsoft.Extensions.DependencyInjection;
+internal static class MinioHttpClientFactoryServiceCollectionExtensions
+{
+ private const string HttpClientName = "__MinioApiClient";
+ public static IServiceCollection AddMinioHttpClient(this IServiceCollection services)
+ {
+ services.AddHttpClient(HttpClientName);
+
+ return services;
+ }
+
+ public static HttpClient CreateMinioHttpClient(this IHttpClientFactory httpClientFactory)
+ {
+ return httpClientFactory.CreateClient(HttpClientName);
+ }
+}
diff --git a/framework/src/Volo.Abp.BlobStoring.Minio/Volo.Abp.BlobStoring.Minio.csproj b/framework/src/Volo.Abp.BlobStoring.Minio/Volo.Abp.BlobStoring.Minio.csproj
index 0b5f33e146..98d3481999 100644
--- a/framework/src/Volo.Abp.BlobStoring.Minio/Volo.Abp.BlobStoring.Minio.csproj
+++ b/framework/src/Volo.Abp.BlobStoring.Minio/Volo.Abp.BlobStoring.Minio.csproj
@@ -18,6 +18,7 @@
+
diff --git a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/AbpBlobStoringMinioModule.cs b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/AbpBlobStoringMinioModule.cs
index 31d023ecf2..b1746a0e34 100644
--- a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/AbpBlobStoringMinioModule.cs
+++ b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/AbpBlobStoringMinioModule.cs
@@ -1,9 +1,13 @@
-using Volo.Abp.Modularity;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
namespace Volo.Abp.BlobStoring.Minio;
[DependsOn(typeof(AbpBlobStoringModule))]
public class AbpBlobStoringMinioModule : AbpModule
{
-
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddMinioHttpClient();
+ }
}
diff --git a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs
index 5fa1ceb0ce..82490c177a 100644
--- a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs
+++ b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProvider.cs
@@ -1,22 +1,27 @@
-using Minio;
-using Minio.Exceptions;
-using System;
+using System;
using System.IO;
+using System.Net.Http;
using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using Minio;
using Minio.DataModel.Args;
+using Minio.Exceptions;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BlobStoring.Minio;
public class MinioBlobProvider : BlobProviderBase, ITransientDependency
{
+ protected IHttpClientFactory HttpClientFactory { get; }
protected IMinioBlobNameCalculator MinioBlobNameCalculator { get; }
protected IBlobNormalizeNamingService BlobNormalizeNamingService { get; }
public MinioBlobProvider(
+ IHttpClientFactory httpClientFactory,
IMinioBlobNameCalculator minioBlobNameCalculator,
IBlobNormalizeNamingService blobNormalizeNamingService)
{
+ HttpClientFactory = httpClientFactory;
MinioBlobNameCalculator = minioBlobNameCalculator;
BlobNormalizeNamingService = blobNormalizeNamingService;
}
@@ -81,21 +86,16 @@ public class MinioBlobProvider : BlobProviderBase, ITransientDependency
return null;
}
- var memoryStream = new MemoryStream();
- await client.GetObjectAsync(new GetObjectArgs().WithBucket(containerName).WithObject(blobName).WithCallbackStream(stream =>
- {
- if (stream != null)
- {
- stream.CopyTo(memoryStream);
- memoryStream.Seek(0, SeekOrigin.Begin);
- }
- else
- {
- memoryStream = null;
- }
- }));
+ var configuration = args.Configuration.GetMinioConfiguration();
+ var downloadUrl = await client.PresignedGetObjectAsync(
+ new PresignedGetObjectArgs()
+ .WithBucket(containerName)
+ .WithObject(blobName)
+ .WithExpiry(configuration.PresignedGetExpirySeconds));
+
+ var httpClient = HttpClientFactory.CreateMinioHttpClient();
- return memoryStream;
+ return await httpClient.GetStreamAsync(downloadUrl, args.CancellationToken);
}
protected virtual IMinioClient GetMinioClient(BlobProviderArgs args)
diff --git a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfiguration.cs b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfiguration.cs
index e626a6837e..740a24f04f 100644
--- a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfiguration.cs
+++ b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfiguration.cs
@@ -47,6 +47,16 @@ public class MinioBlobProviderConfiguration
set => _containerConfiguration.SetConfiguration(MinioBlobProviderConfigurationNames.CreateBucketIfNotExists, value);
}
+ ///
+ /// Default value: 7 * 24 * 3600.
+ ///
+ public int PresignedGetExpirySeconds {
+ get => _containerConfiguration.GetConfigurationOrDefault(MinioBlobProviderConfigurationNames.PresignedGetExpirySeconds, _defaultExpirySeconds);
+ set => _containerConfiguration.SetConfiguration(MinioBlobProviderConfigurationNames.PresignedGetExpirySeconds, value);
+ }
+
+ private int _defaultExpirySeconds = 7 * 24 * 3600;
+
private readonly BlobContainerConfiguration _containerConfiguration;
public MinioBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration)
diff --git a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfigurationNames.cs b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfigurationNames.cs
index 8a8a121ef7..1c32bd8aa0 100644
--- a/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfigurationNames.cs
+++ b/framework/src/Volo.Abp.BlobStoring.Minio/Volo/Abp/BlobStoring/Minio/MinioBlobProviderConfigurationNames.cs
@@ -8,4 +8,5 @@ public static class MinioBlobProviderConfigurationNames
public const string SecretKey = "Minio.SecretKey";
public const string WithSSL = "Minio.WithSSL";
public const string CreateBucketIfNotExists = "Minio.CreateBucketIfNotExists";
+ public const string PresignedGetExpirySeconds = "Minio.PresignedGetExpirySeconds";
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemDotNetProjectBuildConfigReader.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemDotNetProjectBuildConfigReader.cs
index 47daa1d401..b421ea0dd4 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemDotNetProjectBuildConfigReader.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Build/FileSystemDotNetProjectBuildConfigReader.cs
@@ -21,8 +21,9 @@ public class FileSystemDotNetProjectBuildConfigReader : IDotNetProjectBuildConfi
public DotNetProjectBuildConfig Read(string directoryPath)
{
var buildConfig = new DotNetProjectBuildConfig();
- var solutionFiles = Directory.GetFiles(directoryPath, "*.sln", SearchOption.TopDirectoryOnly);
- if (solutionFiles.Length == 1)
+ var solutionFiles = Directory.GetFiles(directoryPath, "*.sln", SearchOption.TopDirectoryOnly)
+ .Concat(Directory.GetFiles(directoryPath, "*.slnx", SearchOption.TopDirectoryOnly)).ToList();
+ if (solutionFiles.Count == 1)
{
buildConfig.SlFilePath = solutionFiles.First();
var configFile = GetClosestFile(directoryPath, _buildConfigName);
@@ -86,7 +87,7 @@ public class FileSystemDotNetProjectBuildConfigReader : IDotNetProjectBuildConfi
directoryInfo = directoryInfo.Parent;
} while (directoryInfo?.Parent != null);
- throw new Exception("There is no solution file (*.sln) and " + _buildConfigName +
+ throw new Exception("There is no solution file (*.sln or *.slnx) and " + _buildConfigName +
" in the working directory and working directory is not a GIT repository !");
}
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 1791a5e928..4756c3f99b 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
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.Linq;
using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@@ -118,7 +119,7 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency
sb.AppendLine("");
sb.AppendLine("'add-module' command is used to add a multi-package ABP module to a solution.");
- sb.AppendLine("It should be used in a folder containing a .sln file.");
+ sb.AppendLine("It should be used in a folder containing a .sln or .slnx file.");
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine(" abp add-module [options]");
@@ -166,20 +167,21 @@ public class AddModuleCommand : IConsoleCommand, ITransientDependency
return providedSolutionFile;
}
- var foundSolutionFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln");
- if (foundSolutionFiles.Length == 1)
+ var foundSolutionFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln")
+ .Concat(Directory.GetFiles(Directory.GetCurrentDirectory(), "*.slnx")).ToList();
+ if (foundSolutionFiles.Count == 1)
{
return foundSolutionFiles[0];
}
- if (foundSolutionFiles.Length == 0)
+ if (foundSolutionFiles.Count == 0)
{
- throw new CliUsageException("'abp add-module' command should be used inside a folder containing a .sln file!");
+ throw new CliUsageException("'abp add-module' command should be used inside a folder containing a .sln or .slnx file!");
}
//foundSolutionFiles.Length > 1
- var sb = new StringBuilder("There are multiple solution (.sln) files in the current directory. Please specify one of the files below:");
+ var sb = new StringBuilder("There are multiple solution (.sln or .slnx) files in the current directory. Please specify one of the files below:");
foreach (var foundSolutionFile in foundSolutionFiles)
{
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs
index 32d9f49799..e9acb7ae24 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/AddPackageCommand.cs
@@ -83,7 +83,7 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency
sb.AppendLine("");
sb.AppendLine("'add-package' command is used to add an ABP package to a project.");
- sb.AppendLine("It should be used in a folder containing a .csproj file, .sln file or packages.json.");
+ sb.AppendLine("It should be used in a folder containing a .csproj file, .sln file, .slnx file or packages.json.");
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine("");
@@ -146,7 +146,8 @@ public class AddPackageCommand : IConsoleCommand, ITransientDependency
return providedSolutionFile;
}
- return Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln").FirstOrDefault();
+ return Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln")
+ .Concat(Directory.GetFiles(Directory.GetCurrentDirectory(), "*.slnx")).FirstOrDefault();
}
protected virtual string GetAngularDirectory(CommandLineArgs commandLineArgs)
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs
index dabc6b6862..51ade9be0c 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs
@@ -175,9 +175,10 @@ public abstract class ProjectCreationCommandBase
if (slnPath == null)
{
- slnPath = Directory.GetFiles(outputFolderRoot, "*.sln").FirstOrDefault();
+ slnPath = Directory.GetFiles(outputFolderRoot, "*.sln")
+ .Concat(Directory.GetFiles(outputFolderRoot, "*.slnx")).FirstOrDefault();
}
- else if (slnPath.EndsWith(".sln"))
+ else if (slnPath.EndsWith(".sln") || slnPath.EndsWith(".slnx"))
{
Directory.SetCurrentDirectory(Path.GetDirectoryName(slnPath));
outputFolderRoot = Path.GetDirectoryName(slnPath);
@@ -190,7 +191,8 @@ public abstract class ProjectCreationCommandBase
{
Directory.SetCurrentDirectory(slnPath);
outputFolderRoot = slnPath;
- slnPath = Directory.GetFiles(outputFolderRoot, "*.sln").FirstOrDefault();
+ slnPath = Directory.GetFiles(outputFolderRoot, "*.sln")
+ .Concat(Directory.GetFiles(outputFolderRoot, "*.slnx")).FirstOrDefault();
}
if (slnPath == null)
@@ -198,7 +200,7 @@ public abstract class ProjectCreationCommandBase
throw new CliUsageException($"This command should be run inside a folder that contains a microservice solution! Or use -{Options.MainSolution.Short} parameter.");
}
- var microserviceSolutionName = Path.GetFileName(slnPath).RemovePostFix(".sln");
+ var microserviceSolutionName = Path.GetFileName(slnPath).RemovePostFix(".slnx", ".sln");
version ??= SolutionPackageVersionFinder.FindByCsprojVersion(slnPath);
solutionName = SolutionName.Parse(microserviceSolutionName, projectName);
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs
index 48f5eca5f8..80d5a5a13b 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs
@@ -119,7 +119,7 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency
var solutionFile = args.Options.GetOrNull(Options.Crud.Solution.Short, Options.Crud.Solution.Long);
if (entityFile.IsNullOrEmpty() || !entityFile.EndsWith(".json") || !File.Exists(entityFile) ||
- solutionFile.IsNullOrEmpty() || !solutionFile.EndsWith(".sln"))
+ solutionFile.IsNullOrEmpty() || !(solutionFile.EndsWith(".sln") || solutionFile.EndsWith(".slnx")))
{
throw new UserFriendlyException("Invalid Arguments!");
}
@@ -476,7 +476,8 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency
private object GetTargetSolutionOrNull(CommandLineArgs commandLineArgs)
{
return commandLineArgs.Options.GetOrNull(Options.Crud.Solution.Short, Options.Crud.Solution.Long)
- ?? Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln", SearchOption.TopDirectoryOnly).FirstOrDefault();
+ ?? Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln", SearchOption.TopDirectoryOnly)
+ .Concat(Directory.GetFiles(Directory.GetCurrentDirectory(), "*.slnx", SearchOption.TopDirectoryOnly)).FirstOrDefault();
}
private Process StartSuite()
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToLocalCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToLocalCommand.cs
index b0889e9557..4837b2b5a0 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToLocalCommand.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SwitchToLocalCommand.cs
@@ -70,7 +70,7 @@ public class SwitchToLocal : IConsoleCommand, ITransientDependency
return null;
}
- if (path.EndsWith(".sln") || path.EndsWith(".csproj"))
+ if (path.EndsWith(".sln") || path.EndsWith(".slnx") || path.EndsWith(".csproj"))
{
return Path.GetDirectoryName(path);
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
index 8c6df3b0b9..ae3cda8723 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
@@ -64,6 +64,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency
if (givenSolution.IsNullOrWhiteSpace())
{
solutions.AddRange(Directory.GetFiles(directory, "*.sln", SearchOption.AllDirectories));
+ solutions.AddRange(Directory.GetFiles(directory, "*.slnx", SearchOption.AllDirectories));
}
else
{
@@ -76,7 +77,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency
{
foreach (var solution in solutions)
{
- var solutionName = Path.GetFileName(solution).RemovePostFix(".sln");
+ var solutionName = Path.GetFileName(solution).RemovePostFix(".slnx", ".sln");
await _nugetPackagesVersionUpdater.UpdateSolutionAsync(solution, checkAll: checkAll, version: version, leptonXVersion: leptonXVersion);
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/AppNoLayersMoveProjectsStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/AppNoLayersMoveProjectsStep.cs
index e9af25d28a..fc34c8a00d 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/AppNoLayersMoveProjectsStep.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/AppNoLayersMoveProjectsStep.cs
@@ -41,7 +41,7 @@ public class AppNoLayersMoveProjectsStep : ProjectBuildPipelineStep
public void ModifySolutionFile(ProjectBuildContext context, string pathInSlnFile, string newPathInSlnFile)
{
- var slnFile = context.Files.First(file => file.Name.EndsWith(".sln"));
+ var slnFile = context.Files.First(file => file.Name.EndsWith(".sln") ||file.Name.EndsWith(".slnx"));
slnFile.SetContent(slnFile.Content.Replace($"\"{pathInSlnFile}\"", $"\"{newPathInSlnFile}\""));
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectRenameStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectRenameStep.cs
index a109d21f7a..75d24a66f6 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectRenameStep.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ProjectRenameStep.cs
@@ -24,7 +24,7 @@ public class ProjectRenameStep : ProjectBuildPipelineStep
}
}
- var files = context.Files.Where(f => f.Name.EndsWith(".sln") || f.Name.EndsWith(".cs"));
+ var files = context.Files.Where(f => f.Name.EndsWith(".sln") || f.Name.EndsWith(".slnx") || f.Name.EndsWith(".cs"));
foreach (var file in files)
{
file.NormalizeLineEndings();
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs
index 3866d2c33f..0e22d62480 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/RemoveProjectFromSolutionStep.cs
@@ -1,49 +1,120 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
-using Newtonsoft.Json;
+using System.Xml;
using Newtonsoft.Json.Linq;
+using Volo.Abp.Cli.ProjectBuilding.Files;
+using Formatting = Newtonsoft.Json.Formatting;
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps;
public class RemoveProjectFromSolutionStep : ProjectBuildPipelineStep
{
private readonly string _projectName;
- private string _solutionFilePath;
+ private string _solutionFilePathWithoutFileExtension;
private string _projectFolderPath;
private string ProjectNameWithQuotes => $"\"{_projectName}\"";
public RemoveProjectFromSolutionStep(
string projectName,
- string solutionFilePath = null,
+ string solutionFilePathWithoutFileExtension = null,
string projectFolderPath = null)
{
_projectName = projectName;
- _solutionFilePath = solutionFilePath;
_projectFolderPath = projectFolderPath;
+
+ if (solutionFilePathWithoutFileExtension != null && solutionFilePathWithoutFileExtension.EndsWith(".sln"))
+ {
+ _solutionFilePathWithoutFileExtension = solutionFilePathWithoutFileExtension.RemovePostFix(".sln");
+ }
+
+ if (solutionFilePathWithoutFileExtension != null && solutionFilePathWithoutFileExtension.EndsWith(".slnx"))
+ {
+ _solutionFilePathWithoutFileExtension = solutionFilePathWithoutFileExtension.RemovePostFix(".slnx");
+ }
+ else
+ {
+ _solutionFilePathWithoutFileExtension = solutionFilePathWithoutFileExtension;
+ }
}
public override void Execute(ProjectBuildContext context)
{
SetSolutionAndProjectPathsIfNull(context);
- if (_solutionFilePath == null || _projectFolderPath == null)
+ if (_solutionFilePathWithoutFileExtension == null || _projectFolderPath == null)
{
return;
}
new RemoveFolderStep(_projectFolderPath).Execute(context);
- var solutionFile = context.GetFile(_solutionFilePath);
- solutionFile.NormalizeLineEndings();
- solutionFile.SetLines(RemoveProject(solutionFile.GetLines().ToList()));
+ var solutionFile = context.FindFile(_solutionFilePathWithoutFileExtension + ".sln")
+ ?? context.GetFile(_solutionFilePathWithoutFileExtension + ".slnx");
+
+ if (solutionFile.Name.EndsWith(".sln"))
+ {
+ RemoveProjectFromSlnFile(solutionFile);
+ }
+ else
+ {
+ RemoveProjectFromSlnxFile(solutionFile);
+ }
RemoveProjectFromAbpmdlFile(context);
}
+ private void RemoveProjectFromSlnxFile(FileEntry solutionFile)
+ {
+ var document = new XmlDocument { PreserveWhitespace = true };
+ document.LoadXml(solutionFile.Content);
+ var projectNodes = document.SelectNodes("//Project");
+
+ if (projectNodes == null || projectNodes.Count < 1)
+ {
+ return;
+ }
+
+ var nodesToBeRemoved = new List();
+ foreach (XmlNode projectNode in projectNodes)
+ {
+ var pathAttr = projectNode.Attributes?["Path"]?.Value;
+ if (string.IsNullOrWhiteSpace(pathAttr))
+ {
+ continue;
+ }
+
+ var normalized = pathAttr.Replace('\\', '/');
+ var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(normalized);
+
+ if (string.Equals(fileNameWithoutExtension, _projectName, StringComparison.OrdinalIgnoreCase))
+ {
+ nodesToBeRemoved.Add(projectNode);
+ }
+ }
+
+ foreach (var node in nodesToBeRemoved)
+ {
+ node.ParentNode!.RemoveChild(node);
+ }
+
+ solutionFile.SetContent(
+ document.OuterXml
+ .SplitToLines()
+ .Where(x=> !x.Trim().Equals(string.Empty))
+ .JoinAsString(Environment.NewLine));
+ }
+
+ private void RemoveProjectFromSlnFile(FileEntry solutionFile)
+ {
+ solutionFile.NormalizeLineEndings();
+ solutionFile.SetLines(RemoveProject(solutionFile.GetLines().ToList()));
+ }
+
private void RemoveProjectFromAbpmdlFile(ProjectBuildContext context)
{
- var abpmdlFile = context.FindFile(_solutionFilePath.RemovePostFix(".sln") + ".abpmdl");
+ var abpmdlFile = context.FindFile(_solutionFilePathWithoutFileExtension + ".abpmdl");
if (abpmdlFile == null)
{
@@ -106,11 +177,14 @@ public class RemoveProjectFromSolutionStep : ProjectBuildPipelineStep
private void SetSolutionAndProjectPathsIfNull(ProjectBuildContext context)
{
- if (_solutionFilePath == null)
+ if (_solutionFilePathWithoutFileExtension == null)
{
- _solutionFilePath = context.FindFile("/aspnet-core/MyCompanyName.MyProjectName.sln")?.Name ??
- context.FindFile("/MyCompanyName.MyProjectName.sln")?.Name ??
- context.FindFile("/MyCompanyName.MyProjectName.MicroserviceName.sln")?.Name;
+ _solutionFilePathWithoutFileExtension = context.FindFile("/aspnet-core/MyCompanyName.MyProjectName.sln")?.Name.RemovePostFix(".sln") ??
+ context.FindFile("/aspnet-core/MyCompanyName.MyProjectName.slnx")?.Name.RemovePostFix(".slnx") ??
+ context.FindFile("/MyCompanyName.MyProjectName.sln")?.Name.RemovePostFix(".sln") ??
+ context.FindFile("/MyCompanyName.MyProjectName.slnx")?.Name.RemovePostFix(".slnx") ??
+ context.FindFile("/MyCompanyName.MyProjectName.MicroserviceName.sln")?.Name.RemovePostFix(".sln") ??
+ context.FindFile("/MyCompanyName.MyProjectName.MicroserviceName.slnx")?.Name.RemovePostFix(".slnx");
}
if (_projectFolderPath == null)
{
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MicroserviceServiceStringEncryptionStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MicroserviceServiceStringEncryptionStep.cs
index 7e25cb2b96..9ae8e14a8d 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MicroserviceServiceStringEncryptionStep.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/MicroserviceServiceStringEncryptionStep.cs
@@ -17,7 +17,8 @@ public class MicroserviceServiceStringEncryptionStep : RandomizeStringEncryption
var directoryInfo = new DirectoryInfo(context.BuildArgs.OutputFolder);
do
{
- var msSolution = Directory.GetFiles(directoryInfo.FullName, "*.sln", SearchOption.TopDirectoryOnly).FirstOrDefault();
+ var msSolution = Directory.GetFiles(directoryInfo.FullName, "*.sln", SearchOption.TopDirectoryOnly)
+ .Concat(Directory.GetFiles(directoryInfo.FullName, "*.slnx", SearchOption.TopDirectoryOnly)).FirstOrDefault();
if (msSolution != null)
{
var appSettings = Directory.GetFiles(Path.Combine(directoryInfo.FullName, "apps", "auth-server"),
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackagePreviewSwitcher.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackagePreviewSwitcher.cs
index 7cf1d0da7a..13046dae78 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackagePreviewSwitcher.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/PackagePreviewSwitcher.cs
@@ -269,7 +269,8 @@ public class PackagePreviewSwitcher : ITransientDependency
private List GetSolutionPaths(CommandLineArgs commandLineArgs)
{
- return Directory.GetFiles(GetDirectory(commandLineArgs), "*.sln", SearchOption.AllDirectories).ToList();
+ return Directory.GetFiles(GetDirectory(commandLineArgs), "*.sln", SearchOption.AllDirectories)
+ .Concat(Directory.GetFiles(GetDirectory(commandLineArgs), "*.slnx", SearchOption.AllDirectories)).ToList();
}
private List GetProjectPaths(CommandLineArgs commandLineArgs)
@@ -317,7 +318,8 @@ public class PackagePreviewSwitcher : ITransientDependency
return Path.GetDirectoryName(projectFile);
}
- if (Directory.GetFiles(targetFolder, "*.sln", SearchOption.TopDirectoryOnly).Any())
+ if (Directory.GetFiles(targetFolder, "*.sln", SearchOption.TopDirectoryOnly)
+ .Concat(Directory.GetFiles(targetFolder, "*.slnx", SearchOption.TopDirectoryOnly)).Any())
{
break;
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs
index 9d9d7e159e..f118892b5a 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ProjectNugetPackageAdder.cs
@@ -214,7 +214,8 @@ public class ProjectNugetPackageAdder : ITransientDependency
{
var folder = FindSolutionFolder(projectFile);
- return Directory.GetFiles(folder, "*.sln", SearchOption.TopDirectoryOnly).FirstOrDefault();
+ return Directory.GetFiles(folder, "*.sln", SearchOption.TopDirectoryOnly)
+ .Concat(Directory.GetFiles(folder, "*.slnx", SearchOption.TopDirectoryOnly)).FirstOrDefault();
}
protected virtual string FindSolutionFolder(string projectFile)
@@ -232,7 +233,8 @@ public class ProjectNugetPackageAdder : ITransientDependency
return Path.GetDirectoryName(projectFile);
}
- if (Directory.GetFiles(targetFolder, "*.sln", SearchOption.TopDirectoryOnly).Any())
+ if (Directory.GetFiles(targetFolder, "*.sln", SearchOption.TopDirectoryOnly)
+ .Concat(Directory.GetFiles(targetFolder, "*.slnx", SearchOption.TopDirectoryOnly)).Any())
{
break;
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionFileModifier.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionFileModifier.cs
index b1678eaca9..7a815df81d 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionFileModifier.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionFileModifier.cs
@@ -4,34 +4,31 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Xml;
+using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectModification;
public class SolutionFileModifier : ITransientDependency
{
- public static Encoding DefaultEncoding = Encoding.UTF8;
+ private readonly ICmdHelper _cmdHelper;
+ public SolutionFileModifier(ICmdHelper cmdHelper)
+ {
+ _cmdHelper = cmdHelper;
+ }
+
public async Task RemoveProjectFromSolutionFileAsync(string solutionFile, string projectName)
{
- using (var fileStream = File.Open(solutionFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
+ var list = _cmdHelper.RunCmdAndGetOutput($"dotnet sln \"{solutionFile}\" list");
+
+ foreach (var line in list.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None))
{
- using (var sr = new StreamReader(fileStream, Encoding.Default, true))
+ if (Path.GetFileNameWithoutExtension(line.Trim()).Equals(projectName, StringComparison.InvariantCultureIgnoreCase))
{
- var solutionFileContent = await sr.ReadToEndAsync();
- solutionFileContent.NormalizeLineEndings();
-
- var lines = solutionFileContent.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None);
- var updatedContent = RemoveProject(lines.ToList(), projectName).JoinAsString(Environment.NewLine);
-
- fileStream.Seek(0, SeekOrigin.Begin);
- fileStream.SetLength(0);
-
- using (var sw = new StreamWriter(fileStream, DefaultEncoding))
- {
- await sw.WriteAsync(updatedContent);
- await sw.FlushAsync();
- }
+ _cmdHelper.RunCmd($"dotnet sln \"{solutionFile}\" remove \"{line.Trim()}\"");
+ break;
}
}
}
@@ -48,105 +45,16 @@ public class SolutionFileModifier : ITransientDependency
private async Task AddPackageAsync(NugetPackageInfo package, string solutionFile)
{
- var srcFolderId = await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, "src");
-
- var solutionFileContent = File.ReadAllText(solutionFile);
- var lines = solutionFileContent.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None).ToList();
-
- if (lines.Any(l => l.Contains($"\"{package.Name}\"")))
- {
- return;
- }
-
- var projectGuid = Guid.NewGuid().ToString();
-
- var newProjectLine = "Project(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"" + package.Name + "\"," +
- " \"packages\\" + package.Name + "\\" +
- "\\" + package.Name + ".csproj\", \"{" + projectGuid + "}\""
- + Environment.NewLine + "EndProject";
-
- lines.InsertAfter(l => l.Trim().Equals("EndProject"), newProjectLine);
-
- var newPostSolutionLine =
- " {" + projectGuid + "}.Debug|Any CPU.ActiveCfg = Debug|Any CPU" + Environment.NewLine +
- " {" + projectGuid + "}.Debug|Any CPU.Build.0 = Debug|Any CPU" + Environment.NewLine +
- " {" + projectGuid + "}.Release|Any CPU.ActiveCfg = Release|Any CPU" + Environment.NewLine +
- " {" + projectGuid + "}.Release|Any CPU.Build.0 = Release|Any CPU";
-
- lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("ProjectConfigurationPlatforms"),
- newPostSolutionLine);
-
- var newPreSolutionLine =
- " {" + projectGuid + "} = {" + srcFolderId + "}";
-
- lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"), newPreSolutionLine);
-
- File.WriteAllText(solutionFile, string.Join(Environment.NewLine, lines), DefaultEncoding);
- }
-
- private List RemoveProject(List solutionFileLines, string projectName)
- {
- var projectKey = FindProjectKey(solutionFileLines, projectName);
-
- if (projectKey == null)
- {
- return solutionFileLines;
- }
-
- var newSolutionFileLines = new List();
- var firstOccurence = true;
-
- for (var i = 0; i < solutionFileLines.Count; ++i)
- {
- if (solutionFileLines[i].Contains(projectKey))
- {
- if (firstOccurence)
- {
- firstOccurence = false;
- ++i; //Skip "EndProject" line too.
- }
-
- continue;
- }
-
- newSolutionFileLines.Add(solutionFileLines[i]);
- }
-
- return newSolutionFileLines;
- }
-
- private string FindProjectKey(List solutionFileLines, string projectName)
- {
- var projectNameWithQuotes = $"\"{projectName}\"";
- foreach (var solutionFileLine in solutionFileLines)
- {
- if (solutionFileLine.Contains(projectNameWithQuotes))
- {
- var curlyBracketStartIndex = solutionFileLine.LastIndexOf("{", StringComparison.OrdinalIgnoreCase);
- var curlyBracketEndIndex = solutionFileLine.LastIndexOf("}", StringComparison.OrdinalIgnoreCase);
- return solutionFileLine.Substring(curlyBracketStartIndex + 1,
- curlyBracketEndIndex - curlyBracketStartIndex - 1);
- }
- }
-
- return null;
+ _cmdHelper.RunCmd($"dotnet sln \"{solutionFile}\" add \"packages\\{package.Name}\\{package.Name}.csproj\" --solution-folder src");
}
private async Task AddModuleAsync(ModuleWithMastersInfo module, string solutionFile)
{
- var srcModuleFolderId = await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, module.Name,
- await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, "modules"));
- var testModuleFolderId = await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, module.Name + ".Tests",
- await AddNewFolderAndGetIdOrGetExistingIdAsync(solutionFile, "test"));
-
- var file = File.ReadAllText(solutionFile);
- var lines = file.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None).ToList();
-
var projectsUnderModule = Directory.GetFiles(
Path.Combine(Path.GetDirectoryName(solutionFile), "modules", module.Name),
"*.csproj",
SearchOption.AllDirectories);
-
+
var projectsUnderTest = new List();
if (Directory.Exists(Path.Combine(Path.GetDirectoryName(solutionFile), "modules", module.Name, "test")))
{
@@ -158,41 +66,14 @@ public class SolutionFileModifier : ITransientDependency
foreach (var projectPath in projectsUnderModule)
{
- var parentFolderId = projectsUnderTest.Contains(projectPath) ? testModuleFolderId : srcModuleFolderId;
- var projectId = Path.GetFileName(projectPath).Replace(".csproj", "");
- var projectParentFolderInModule = projectsUnderTest.Contains(projectPath) ? "test" : "src";
-
- if (lines.Any(l => l.Contains($"\"{projectId}\"")))
- {
- continue;
- }
-
- var projectGuid = Guid.NewGuid().ToString();
-
- var newProjectLine = "Project(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"" + projectId + "\"," +
- " \"modules\\" + module.Name + "\\" + projectParentFolderInModule + "\\" +
- projectId + "\\" + projectId + ".csproj\", \"{" + projectGuid + "}\""
- + Environment.NewLine + "EndProject";
-
- lines.InsertAfter(l => l.Trim().Equals("EndProject"), newProjectLine);
+ var folder = projectsUnderTest.Contains(projectPath) ? "test" : "src";
- var newPostSolutionLine =
- " {" + projectGuid + "}.Debug|Any CPU.ActiveCfg = Debug|Any CPU" + Environment.NewLine +
- " {" + projectGuid + "}.Debug|Any CPU.Build.0 = Debug|Any CPU" + Environment.NewLine +
- " {" + projectGuid + "}.Release|Any CPU.ActiveCfg = Release|Any CPU" + Environment.NewLine +
- " {" + projectGuid + "}.Release|Any CPU.Build.0 = Release|Any CPU";
-
- lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("ProjectConfigurationPlatforms"),
- newPostSolutionLine);
-
- var newPreSolutionLine =
- " {" + projectGuid + "} = {" + parentFolderId + "}";
-
- lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"), newPreSolutionLine);
+ var projectId = Path.GetFileName(projectPath).Replace(".csproj", "");
+ var package = @$"modules\{module.Name}\{folder}\{projectId}\{projectId}.csproj";
+
+ _cmdHelper.RunCmd($"dotnet sln \"{solutionFile}\" add \"{package}\" --solution-folder {folder}");
}
-
- File.WriteAllText(solutionFile, string.Join(Environment.NewLine, lines), Encoding.UTF8);
-
+
if (module.MasterModuleInfos != null)
{
foreach (var masterModule in module.MasterModuleInfos)
@@ -201,43 +82,4 @@ public class SolutionFileModifier : ITransientDependency
}
}
}
-
- private async Task AddNewFolderAndGetIdOrGetExistingIdAsync(string solutionFile, string folderName,
- string parentFolderId = null)
- {
- var file = File.ReadAllText(solutionFile);
- var lines = file.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.None).ToList();
- string folderId;
-
- var folderLineIndex = lines.FindIndex(l =>
- l.Contains("2150E333-8FDC-42A3-9474-1A3956D46DE8") && l.Contains("\"" + folderName + "\""));
-
- if (folderLineIndex < 0)
- {
- folderId = Guid.NewGuid().ToString();
- var newFolderLine = "Project(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"" + folderName + "\", \"" +
- folderName + "\", \"{" + folderId + "}\""
- + Environment.NewLine + "EndProject";
-
- lines.InsertAfter(l => l.Trim().Equals("EndProject"), newFolderLine);
-
- if (parentFolderId != null)
- {
- var newPreSolutionLine =
- " {" + folderId + "} = {" + parentFolderId + "}";
-
- lines.InsertAfter(l => l.Contains("GlobalSection") && l.Contains("NestedProjects"),
- newPreSolutionLine);
- }
- }
- else
- {
- folderId = lines[folderLineIndex].Replace("\"", " ").Replace("{", " ").Replace("}", " ").TrimEnd()
- .Split(" ").Last();
- }
-
- File.WriteAllText(solutionFile, string.Join(Environment.NewLine, lines), Encoding.UTF8);
-
- return folderId;
- }
}
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 8a703a8deb..cf2abe3857 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
@@ -335,7 +335,8 @@ public class SolutionModuleAdder : ITransientDependency
{
var projectsToRemove = new List();
var moduleDirectory = Path.Combine(solutionDirectory, "modules", module.Name);
- var moduleSolutionFile = Directory.GetFiles(moduleDirectory, "*.sln", SearchOption.TopDirectoryOnly).First();
+ var moduleSolutionFile = Directory.GetFiles(moduleDirectory, "*.sln", SearchOption.TopDirectoryOnly)
+ .Concat(Directory.GetFiles(moduleDirectory, "*.slnx", SearchOption.TopDirectoryOnly)).First();
var isProjectTiered = await IsProjectTiered(projectFiles);
var webPackagesWillBeAddedToBlazorServerProject = false;
@@ -609,7 +610,8 @@ public class SolutionModuleAdder : ITransientDependency
private async Task DeleteRedundantHostProjects(string targetModuleFolder, string folderName)
{
- var moduleSolutionFile = Directory.GetFiles(targetModuleFolder, "*.sln", SearchOption.TopDirectoryOnly).First();
+ var moduleSolutionFile = Directory.GetFiles(targetModuleFolder, "*.sln", SearchOption.TopDirectoryOnly)
+ .Concat(Directory.GetFiles(targetModuleFolder, "*.slnx", SearchOption.TopDirectoryOnly)).First();
var folder = Path.Combine(targetModuleFolder, folderName);
if (Directory.Exists(folder))
diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
index def4aa417d..3cf595367d 100644
--- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
+++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
@@ -4,7 +4,7 @@
- netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0
+ netstandard2.0;net8.0;net9.0;net10.0enableNullableVolo.Abp.Core
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextMySQLExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextMySQLExtensions.cs
index b869109a80..f04f8fd4f3 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextMySQLExtensions.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextMySQLExtensions.cs
@@ -13,11 +13,19 @@ public static class AbpDbContextConfigurationContextMySQLExtensions
{
if (context.ExistingConnection != null)
{
- return context.DbContextOptions.UseMySQL(context.ExistingConnection, mySQLOptionsAction);
+ return context.DbContextOptions.UseMySQL(context.ExistingConnection, optionsBuilder =>
+ {
+ optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
+ mySQLOptionsAction?.Invoke(optionsBuilder);
+ });
}
else
{
- return context.DbContextOptions.UseMySQL(context.ConnectionString, mySQLOptionsAction);
+ return context.DbContextOptions.UseMySQL(context.ConnectionString, optionsBuilder =>
+ {
+ optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
+ mySQLOptionsAction?.Invoke(optionsBuilder);
+ });
}
}
}
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj
index 063f956379..ffeebf2c41 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj
+++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj
@@ -22,6 +22,8 @@
+
+
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
index c661799837..45fe447e88 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
@@ -117,6 +117,17 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext,
{
optionsBuilder.ConfigureWarnings(c => c.Ignore(RelationalEventId.PendingModelChangesWarning));
base.OnConfiguring(optionsBuilder);
+
+ if (LazyServiceProvider == null || Options == null)
+ {
+ return;
+ }
+
+ Options.Value.DefaultOnConfiguringAction?.Invoke(this, optionsBuilder);
+ foreach (var onConfiguringAction in Options.Value.OnConfiguringActions.GetOrDefault(typeof(TDbContext)) ?? [])
+ {
+ onConfiguringAction.As>().Invoke(this, optionsBuilder);
+ }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
@@ -798,7 +809,7 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext,
modelBuilder,
mutableEntityType
);
-
+
entityTypeBuilder.ConfigureByConvention();
ConfigureGlobalFilters(modelBuilder, mutableEntityType, entityTypeBuilder);
@@ -815,7 +826,7 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext,
protected virtual void ConfigureGlobalFilters(
ModelBuilder modelBuilder,
- IMutableEntityType mutableEntityType,
+ IMutableEntityType mutableEntityType,
EntityTypeBuilder entityTypeBuilder)
where TEntity : class
{
@@ -846,7 +857,7 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext,
{
return;
}
-
+
foreach (var property in mutableEntityType.GetProperties().
Where(property => property.PropertyInfo != null &&
@@ -858,7 +869,7 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext,
modelBuilder,
mutableEntityType
);
-
+
entityTypeBuilder
.Property(property.Name)
.HasConversion(property.ClrType == typeof(DateTime)
@@ -868,7 +879,7 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext,
}
protected virtual void ConfigureValueGenerated(
- ModelBuilder modelBuilder,
+ ModelBuilder modelBuilder,
IMutableEntityType mutableEntityType)
where TEntity : class
{
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs
index acde97340b..a179bb3ee8 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs
@@ -26,8 +26,12 @@ public class AbpDbContextOptions
internal Dictionary> ConventionActions { get; }
internal Action? DefaultOnModelCreatingAction { get; set; }
+
+ internal Action? DefaultOnConfiguringAction { get; set; }
internal Dictionary> OnModelCreatingActions { get; }
+
+ internal Dictionary> OnConfiguringActions { get; }
public AbpDbContextOptions()
{
@@ -37,6 +41,7 @@ public class AbpDbContextOptions
DbContextReplacements = new Dictionary();
ConventionActions = new Dictionary>();
OnModelCreatingActions = new Dictionary>();
+ OnConfiguringActions = new Dictionary>();
}
public void PreConfigure([NotNull] Action action)
@@ -84,6 +89,13 @@ public class AbpDbContextOptions
DefaultOnModelCreatingAction = action;
}
+
+ public void ConfigureDefaultOnConfiguring([NotNull] Action action)
+ {
+ Check.NotNull(action, nameof(action));
+
+ DefaultOnConfiguringAction = action;
+ }
public void ConfigureOnModelCreating([NotNull] Action action)
where TDbContext : AbpDbContext
@@ -102,6 +114,24 @@ public class AbpDbContextOptions
actions.Add(action);
}
+
+ public void ConfigureOnConfiguring([NotNull] Action action)
+ where TDbContext : AbpDbContext
+ {
+ Check.NotNull(action, nameof(action));
+
+ var actions = OnConfiguringActions.GetOrDefault(typeof(TDbContext));
+ if (actions == null)
+ {
+ OnConfiguringActions[typeof(TDbContext)] = new List