@ngxtm/devkit 3.4.0 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/rules/README.md +141 -0
- package/rules/dart/best-practices/SKILL.md +23 -0
- package/rules/dart/language/SKILL.md +52 -0
- package/rules/dart/tooling/SKILL.md +43 -0
- package/rules/dotnet/aspnet-core/SKILL.md +92 -0
- package/rules/dotnet/aspnet-core/references/REFERENCE.md +335 -0
- package/rules/dotnet/best-practices/SKILL.md +101 -0
- package/rules/dotnet/best-practices/references/REFERENCE.md +256 -0
- package/rules/dotnet/blazor/SKILL.md +146 -0
- package/rules/dotnet/blazor/references/REFERENCE.md +392 -0
- package/rules/dotnet/language/SKILL.md +82 -0
- package/rules/dotnet/language/references/REFERENCE.md +222 -0
- package/rules/dotnet/patterns.rule.md +388 -0
- package/rules/dotnet/razor-pages/SKILL.md +124 -0
- package/rules/dotnet/razor-pages/references/REFERENCE.md +321 -0
- package/rules/dotnet/security/SKILL.md +89 -0
- package/rules/dotnet/security/references/REFERENCE.md +295 -0
- package/rules/dotnet/tooling/SKILL.md +92 -0
- package/rules/dotnet/tooling/references/REFERENCE.md +300 -0
- package/rules/flutter/auto-route-navigation/SKILL.md +43 -0
- package/rules/flutter/auto-route-navigation/references/REFERENCE.md +19 -0
- package/rules/flutter/auto-route-navigation/references/router-config.md +62 -0
- package/rules/flutter/bloc-state-management/SKILL.md +64 -0
- package/rules/flutter/bloc-state-management/references/REFERENCE.md +20 -0
- package/rules/flutter/bloc-state-management/references/auth-bloc-example.md +52 -0
- package/rules/flutter/bloc-state-management/references/equatable-usage.md +56 -0
- package/rules/flutter/bloc-state-management/references/property-based-state.md +68 -0
- package/rules/flutter/bloc.rule.md +76 -0
- package/rules/flutter/cicd/SKILL.md +48 -0
- package/rules/flutter/cicd/references/advanced-workflow.md +66 -0
- package/rules/flutter/cicd/references/fastlane.md +139 -0
- package/rules/flutter/cicd/references/github-actions.md +59 -0
- package/rules/flutter/dependency-injection/SKILL.md +42 -0
- package/rules/flutter/dependency-injection/references/REFERENCE.md +15 -0
- package/rules/flutter/dependency-injection/references/modules.md +37 -0
- package/rules/flutter/error-handling/SKILL.md +32 -0
- package/rules/flutter/error-handling/references/REFERENCE.md +19 -0
- package/rules/flutter/error-handling/references/error-mapping.md +31 -0
- package/rules/flutter/feature-based-clean-architecture/SKILL.md +46 -0
- package/rules/flutter/feature-based-clean-architecture/references/REFERENCE.md +14 -0
- package/rules/flutter/feature-based-clean-architecture/references/folder-structure.md +36 -0
- package/rules/flutter/getx-navigation/SKILL.md +70 -0
- package/rules/flutter/getx-navigation/references/app-pages.md +40 -0
- package/rules/flutter/getx-navigation/references/middleware-example.md +29 -0
- package/rules/flutter/getx-state-management/SKILL.md +76 -0
- package/rules/flutter/getx-state-management/references/binding-example.md +32 -0
- package/rules/flutter/getx-state-management/references/reactive-vs-simple.md +39 -0
- package/rules/flutter/go-router-navigation/SKILL.md +57 -0
- package/rules/flutter/idiomatic-flutter/SKILL.md +20 -0
- package/rules/flutter/layer-based-clean-architecture/SKILL.md +50 -0
- package/rules/flutter/layer-based-clean-architecture/references/REFERENCE.md +60 -0
- package/rules/flutter/layer-based-clean-architecture/references/repository-mapping.md +50 -0
- package/rules/flutter/localization/SKILL.md +50 -0
- package/rules/flutter/localization/references/REFERENCE.md +48 -0
- package/rules/flutter/localization/references/sheet-loader.md +33 -0
- package/rules/flutter/navigator-v1-navigation/SKILL.md +71 -0
- package/rules/flutter/navigator-v1-navigation/references/on-generate-route.md +48 -0
- package/rules/flutter/performance/SKILL.md +24 -0
- package/rules/flutter/retrofit-networking/SKILL.md +51 -0
- package/rules/flutter/retrofit-networking/references/REFERENCE.md +19 -0
- package/rules/flutter/retrofit-networking/references/token-refresh.md +40 -0
- package/rules/flutter/riverpod-state-management/SKILL.md +53 -0
- package/rules/flutter/riverpod-state-management/references/architecture.md +124 -0
- package/rules/flutter/riverpod-state-management/references/best-practices.md +89 -0
- package/rules/flutter/riverpod-state-management/references/testing.md +73 -0
- package/rules/flutter/riverpod.rule.md +78 -0
- package/rules/flutter/security/SKILL.md +33 -0
- package/rules/flutter/security/references/REFERENCE.md +15 -0
- package/rules/flutter/security/references/network-security.md +28 -0
- package/rules/flutter/testing/SKILL.md +44 -0
- package/rules/flutter/testing/references/REFERENCE.md +21 -0
- package/rules/flutter/testing/references/bloc-testing.md +38 -0
- package/rules/flutter/testing/references/integration-testing.md +128 -0
- package/rules/flutter/testing/references/robot-pattern.md +82 -0
- package/rules/flutter/testing/references/unit-testing.md +130 -0
- package/rules/flutter/testing/references/widget-testing.md +120 -0
- package/rules/flutter/widgets/SKILL.md +37 -0
- package/rules/golang/chi-router/SKILL.md +219 -0
- package/rules/golang/chi-router/references/REFERENCE.md +13 -0
- package/rules/golang/chi-router/references/routing-patterns.md +205 -0
- package/rules/golang/cobra-cli/SKILL.md +227 -0
- package/rules/golang/cobra-cli/references/REFERENCE.md +13 -0
- package/rules/golang/cobra-cli/references/command-patterns.md +224 -0
- package/rules/golang/core/SKILL.md +210 -0
- package/rules/golang/core/references/REFERENCE.md +14 -0
- package/rules/golang/core/references/concurrency-patterns.md +114 -0
- package/rules/golang/core/references/error-handling.md +87 -0
- package/rules/golang/echo-framework/SKILL.md +215 -0
- package/rules/golang/echo-framework/references/REFERENCE.md +14 -0
- package/rules/golang/echo-framework/references/middleware-patterns.md +141 -0
- package/rules/golang/echo-framework/references/routing-patterns.md +140 -0
- package/rules/golang/ent-orm/SKILL.md +239 -0
- package/rules/golang/ent-orm/references/REFERENCE.md +13 -0
- package/rules/golang/ent-orm/references/schema-patterns.md +255 -0
- package/rules/golang/fiber-framework/SKILL.md +196 -0
- package/rules/golang/fiber-framework/references/REFERENCE.md +13 -0
- package/rules/golang/fiber-framework/references/routing-patterns.md +191 -0
- package/rules/golang/gin-framework/SKILL.md +205 -0
- package/rules/golang/gin-framework/references/REFERENCE.md +14 -0
- package/rules/golang/gin-framework/references/middleware-patterns.md +119 -0
- package/rules/golang/gorm-orm/SKILL.md +196 -0
- package/rules/golang/gorm-orm/references/REFERENCE.md +14 -0
- package/rules/golang/gorm-orm/references/model-definitions.md +167 -0
- package/rules/golang/gorm-orm/references/query-patterns.md +161 -0
- package/rules/golang/grpc/SKILL.md +231 -0
- package/rules/golang/grpc/references/REFERENCE.md +13 -0
- package/rules/golang/grpc/references/service-patterns.md +276 -0
- package/rules/golang/testify/SKILL.md +239 -0
- package/rules/golang/testify/references/REFERENCE.md +13 -0
- package/rules/golang/testify/references/assert-patterns.md +170 -0
- package/rules/golang/validator/SKILL.md +234 -0
- package/rules/golang/validator/references/REFERENCE.md +13 -0
- package/rules/golang/validator/references/validation-tags.md +211 -0
- package/rules/golang/viper-config/SKILL.md +244 -0
- package/rules/golang/viper-config/references/REFERENCE.md +13 -0
- package/rules/golang/viper-config/references/config-loading.md +181 -0
- package/rules/golang/wire-di/SKILL.md +243 -0
- package/rules/golang/wire-di/references/REFERENCE.md +13 -0
- package/rules/golang/wire-di/references/provider-patterns.md +193 -0
- package/rules/golang/zap-logging/SKILL.md +203 -0
- package/rules/golang/zap-logging/references/REFERENCE.md +13 -0
- package/rules/golang/zap-logging/references/logger-config.md +165 -0
- package/rules/java/build-gradle/SKILL.md +92 -0
- package/rules/java/build-gradle/references/REFERENCE.md +14 -0
- package/rules/java/build-gradle/references/kotlin-dsl.md +118 -0
- package/rules/java/build-gradle/references/task-configuration.md +132 -0
- package/rules/java/build-maven/SKILL.md +86 -0
- package/rules/java/build-maven/references/REFERENCE.md +14 -0
- package/rules/java/build-maven/references/dependency-management.md +111 -0
- package/rules/java/build-maven/references/lifecycle-phases.md +114 -0
- package/rules/java/graalvm-native/SKILL.md +105 -0
- package/rules/java/graalvm-native/references/REFERENCE.md +12 -0
- package/rules/java/java-collections-streams/SKILL.md +148 -0
- package/rules/java/java-collections-streams/references/REFERENCE.md +15 -0
- package/rules/java/java-collections-streams/references/collectors-patterns.md +178 -0
- package/rules/java/java-collections-streams/references/stream-pipelines.md +165 -0
- package/rules/java/java-concurrency/SKILL.md +187 -0
- package/rules/java/java-concurrency/references/REFERENCE.md +17 -0
- package/rules/java/java-concurrency/references/completable-future.md +165 -0
- package/rules/java/java-concurrency/references/executor-patterns.md +176 -0
- package/rules/java/java-concurrency/references/virtual-threads.md +190 -0
- package/rules/java/java-core-language/SKILL.md +121 -0
- package/rules/java/java-core-language/references/REFERENCE.md +15 -0
- package/rules/java/java-core-language/references/jvm-memory-model.md +160 -0
- package/rules/java/java-core-language/references/modern-java-features.md +168 -0
- package/rules/java/java-project-structure/SKILL.md +195 -0
- package/rules/java/java-project-structure/references/REFERENCE.md +15 -0
- package/rules/java/java-project-structure/references/maven-project-layout.md +199 -0
- package/rules/java/java-project-structure/references/module-system.md +159 -0
- package/rules/java/micronaut-core/SKILL.md +99 -0
- package/rules/java/micronaut-core/references/REFERENCE.md +12 -0
- package/rules/java/micronaut-reactive/SKILL.md +68 -0
- package/rules/java/micronaut-reactive/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-core/SKILL.md +85 -0
- package/rules/java/quarkus-core/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-reactive/SKILL.md +67 -0
- package/rules/java/quarkus-reactive/references/REFERENCE.md +12 -0
- package/rules/java/spring-batch/SKILL.md +102 -0
- package/rules/java/spring-batch/references/REFERENCE.md +12 -0
- package/rules/java/spring-boot-architecture/SKILL.md +206 -0
- package/rules/java/spring-boot-architecture/references/REFERENCE.md +15 -0
- package/rules/java/spring-boot-architecture/references/auto-configuration.md +158 -0
- package/rules/java/spring-boot-architecture/references/configuration-properties.md +202 -0
- package/rules/java/spring-boot-web/SKILL.md +217 -0
- package/rules/java/spring-boot-web/references/REFERENCE.md +17 -0
- package/rules/java/spring-cloud/SKILL.md +109 -0
- package/rules/java/spring-cloud/references/REFERENCE.md +13 -0
- package/rules/java/spring-data-jpa/SKILL.md +241 -0
- package/rules/java/spring-data-jpa/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/SKILL.md +161 -0
- package/rules/java/spring-security/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/references/jwt-auth-flow.md +213 -0
- package/rules/java/testing-junit-mockito/SKILL.md +135 -0
- package/rules/java/testing-junit-mockito/references/REFERENCE.md +15 -0
- package/rules/java/testing-junit-mockito/references/junit5-patterns.md +159 -0
- package/rules/java/testing-junit-mockito/references/mockito-patterns.md +148 -0
- package/rules/java/testing-junit-mockito/references/spring-boot-testing.md +152 -0
- package/rules/javascript/best-practices/SKILL.md +64 -0
- package/rules/javascript/best-practices/references/REFERENCE.md +91 -0
- package/rules/javascript/language/SKILL.md +71 -0
- package/rules/javascript/language/references/REFERENCE.md +106 -0
- package/rules/javascript/tooling/SKILL.md +60 -0
- package/rules/javascript/tooling/references/REFERENCE.md +107 -0
- package/rules/metadata.json +54 -0
- package/rules/nestjs/api-standards/SKILL.md +47 -0
- package/rules/nestjs/api-standards/references/pagination-wrapper.md +87 -0
- package/rules/nestjs/architecture/SKILL.md +68 -0
- package/rules/nestjs/architecture/references/dynamic-module.md +53 -0
- package/rules/nestjs/caching/SKILL.md +51 -0
- package/rules/nestjs/caching/references/REFERENCE.md +13 -0
- package/rules/nestjs/caching/references/cache-patterns.md +183 -0
- package/rules/nestjs/configuration/SKILL.md +41 -0
- package/rules/nestjs/configuration/references/REFERENCE.md +13 -0
- package/rules/nestjs/configuration/references/config-patterns.md +184 -0
- package/rules/nestjs/controllers-services/SKILL.md +63 -0
- package/rules/nestjs/controllers-services/references/REFERENCE.md +14 -0
- package/rules/nestjs/controllers-services/references/controller-patterns.md +119 -0
- package/rules/nestjs/controllers-services/references/service-patterns.md +129 -0
- package/rules/nestjs/database/SKILL.md +102 -0
- package/rules/nestjs/database/references/REFERENCE.md +14 -0
- package/rules/nestjs/database/references/typeorm-patterns.md +156 -0
- package/rules/nestjs/deployment/SKILL.md +36 -0
- package/rules/nestjs/deployment/references/REFERENCE.md +13 -0
- package/rules/nestjs/deployment/references/deployment-patterns.md +140 -0
- package/rules/nestjs/documentation/SKILL.md +64 -0
- package/rules/nestjs/documentation/references/REFERENCE.md +13 -0
- package/rules/nestjs/documentation/references/swagger-patterns.md +139 -0
- package/rules/nestjs/error-handling/SKILL.md +55 -0
- package/rules/nestjs/error-handling/references/REFERENCE.md +13 -0
- package/rules/nestjs/error-handling/references/exception-filters.md +152 -0
- package/rules/nestjs/file-uploads/SKILL.md +35 -0
- package/rules/nestjs/file-uploads/references/REFERENCE.md +13 -0
- package/rules/nestjs/file-uploads/references/upload-patterns.md +125 -0
- package/rules/nestjs/observability/SKILL.md +39 -0
- package/rules/nestjs/observability/references/REFERENCE.md +13 -0
- package/rules/nestjs/observability/references/logging-metrics.md +175 -0
- package/rules/nestjs/performance/SKILL.md +60 -0
- package/rules/nestjs/performance/references/REFERENCE.md +13 -0
- package/rules/nestjs/performance/references/performance-patterns.md +107 -0
- package/rules/nestjs/real-time/SKILL.md +45 -0
- package/rules/nestjs/real-time/references/REFERENCE.md +13 -0
- package/rules/nestjs/real-time/references/websocket-patterns.md +121 -0
- package/rules/nestjs/scheduling/SKILL.md +39 -0
- package/rules/nestjs/scheduling/references/REFERENCE.md +13 -0
- package/rules/nestjs/scheduling/references/scheduling-patterns.md +137 -0
- package/rules/nestjs/search/SKILL.md +41 -0
- package/rules/nestjs/search/references/REFERENCE.md +13 -0
- package/rules/nestjs/search/references/search-patterns.md +137 -0
- package/rules/nestjs/security/SKILL.md +87 -0
- package/rules/nestjs/security/references/REFERENCE.md +14 -0
- package/rules/nestjs/security/references/authentication.md +151 -0
- package/rules/nestjs/testing/SKILL.md +40 -0
- package/rules/nestjs/testing/references/REFERENCE.md +14 -0
- package/rules/nestjs/testing/references/unit-testing.md +179 -0
- package/rules/nestjs/transport/SKILL.md +45 -0
- package/rules/nestjs/transport/references/REFERENCE.md +13 -0
- package/rules/nestjs/transport/references/microservices-patterns.md +170 -0
- package/rules/nextjs/app-router/SKILL.md +46 -0
- package/rules/nextjs/app-router/references/REFERENCE.md +14 -0
- package/rules/nextjs/app-router/references/routing-patterns.md +182 -0
- package/rules/nextjs/architecture/SKILL.md +44 -0
- package/rules/nextjs/architecture/references/fsd-structure.md +77 -0
- package/rules/nextjs/authentication/SKILL.md +29 -0
- package/rules/nextjs/authentication/references/auth-implementation.md +73 -0
- package/rules/nextjs/caching/SKILL.md +66 -0
- package/rules/nextjs/caching/references/REFERENCE.md +13 -0
- package/rules/nextjs/caching/references/cache-strategies.md +168 -0
- package/rules/nextjs/data-access-layer/SKILL.md +33 -0
- package/rules/nextjs/data-access-layer/references/patterns.md +66 -0
- package/rules/nextjs/data-fetching/SKILL.md +59 -0
- package/rules/nextjs/data-fetching/references/REFERENCE.md +13 -0
- package/rules/nextjs/data-fetching/references/fetch-patterns.md +160 -0
- package/rules/nextjs/internationalization/SKILL.md +105 -0
- package/rules/nextjs/internationalization/references/REFERENCE.md +13 -0
- package/rules/nextjs/internationalization/references/i18n-patterns.md +180 -0
- package/rules/nextjs/optimization/SKILL.md +64 -0
- package/rules/nextjs/optimization/references/REFERENCE.md +13 -0
- package/rules/nextjs/optimization/references/optimization-patterns.md +190 -0
- package/rules/nextjs/rendering/SKILL.md +91 -0
- package/rules/nextjs/rendering/references/REFERENCE.md +13 -0
- package/rules/nextjs/rendering/references/rendering-modes.md +163 -0
- package/rules/nextjs/server-actions/SKILL.md +46 -0
- package/rules/nextjs/server-actions/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-actions/references/action-patterns.md +188 -0
- package/rules/nextjs/server-components/SKILL.md +52 -0
- package/rules/nextjs/server-components/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-components/references/component-patterns.md +175 -0
- package/rules/nextjs/state-management/SKILL.md +73 -0
- package/rules/nextjs/state-management/references/REFERENCE.md +13 -0
- package/rules/nextjs/state-management/references/state-patterns.md +218 -0
- package/rules/nextjs/styling/SKILL.md +31 -0
- package/rules/nextjs/styling/references/implementation.md +56 -0
- package/rules/react/component-patterns/SKILL.md +66 -0
- package/rules/react/component-patterns/references/REFERENCE.md +126 -0
- package/rules/react/hooks/SKILL.md +60 -0
- package/rules/react/hooks/references/REFERENCE.md +132 -0
- package/rules/react/hooks.rule.md +79 -0
- package/rules/react/performance/SKILL.md +69 -0
- package/rules/react/performance/references/REFERENCE.md +143 -0
- package/rules/react/security/SKILL.md +46 -0
- package/rules/react/security/references/REFERENCE.md +170 -0
- package/rules/react/state-management/SKILL.md +56 -0
- package/rules/react/state-management/references/REFERENCE.md +137 -0
- package/rules/react/testing/SKILL.md +45 -0
- package/rules/react/testing/references/REFERENCE.md +149 -0
- package/rules/react/tooling/SKILL.md +39 -0
- package/rules/react/typescript/SKILL.md +53 -0
- package/rules/rust/actix-web/SKILL.md +160 -0
- package/rules/rust/actix-web/references/REFERENCE.md +13 -0
- package/rules/rust/actix-web/references/handler-patterns.md +198 -0
- package/rules/rust/async-graphql/SKILL.md +228 -0
- package/rules/rust/async-graphql/references/REFERENCE.md +13 -0
- package/rules/rust/async-graphql/references/schema-patterns.md +215 -0
- package/rules/rust/axum/SKILL.md +161 -0
- package/rules/rust/axum/references/REFERENCE.md +14 -0
- package/rules/rust/axum/references/handler-patterns.md +97 -0
- package/rules/rust/bevy/SKILL.md +206 -0
- package/rules/rust/bevy/references/REFERENCE.md +13 -0
- package/rules/rust/bevy/references/ecs-patterns.md +226 -0
- package/rules/rust/clap/SKILL.md +217 -0
- package/rules/rust/clap/references/REFERENCE.md +13 -0
- package/rules/rust/clap/references/derive-patterns.md +205 -0
- package/rules/rust/core/SKILL.md +154 -0
- package/rules/rust/core/references/REFERENCE.md +14 -0
- package/rules/rust/core/references/error-handling.md +92 -0
- package/rules/rust/diesel-orm/SKILL.md +176 -0
- package/rules/rust/diesel-orm/references/REFERENCE.md +13 -0
- package/rules/rust/diesel-orm/references/schema-patterns.md +206 -0
- package/rules/rust/rocket/SKILL.md +182 -0
- package/rules/rust/rocket/references/REFERENCE.md +13 -0
- package/rules/rust/rocket/references/handler-patterns.md +209 -0
- package/rules/rust/sea-orm/SKILL.md +230 -0
- package/rules/rust/sea-orm/references/REFERENCE.md +13 -0
- package/rules/rust/sea-orm/references/entity-patterns.md +221 -0
- package/rules/rust/serde-serialization/SKILL.md +150 -0
- package/rules/rust/serde-serialization/references/REFERENCE.md +13 -0
- package/rules/rust/serde-serialization/references/serialization-patterns.md +199 -0
- package/rules/rust/sqlx-database/SKILL.md +140 -0
- package/rules/rust/sqlx-database/references/REFERENCE.md +13 -0
- package/rules/rust/sqlx-database/references/query-patterns.md +210 -0
- package/rules/rust/tauri/SKILL.md +180 -0
- package/rules/rust/tauri/references/REFERENCE.md +13 -0
- package/rules/rust/tauri/references/command-patterns.md +209 -0
- package/rules/rust/tokio-runtime/SKILL.md +167 -0
- package/rules/rust/tokio-runtime/references/REFERENCE.md +14 -0
- package/rules/rust/tokio-runtime/references/async-patterns.md +137 -0
- package/rules/rust/tokio-runtime/references/synchronization.md +152 -0
- package/rules/rust/tonic/SKILL.md +231 -0
- package/rules/rust/tonic/references/REFERENCE.md +13 -0
- package/rules/rust/tonic/references/service-patterns.md +213 -0
- package/rules/rust/tracing/SKILL.md +214 -0
- package/rules/rust/tracing/references/REFERENCE.md +13 -0
- package/rules/rust/tracing/references/instrumentation.md +187 -0
- package/rules/typescript/best-practices/SKILL.md +108 -0
- package/rules/typescript/best-practices/references/REFERENCE.md +68 -0
- package/rules/typescript/language/SKILL.md +72 -0
- package/rules/typescript/language/references/REFERENCE.md +67 -0
- package/rules/typescript/patterns.rule.md +85 -0
- package/rules/typescript/security/SKILL.md +59 -0
- package/rules/typescript/security/references/REFERENCE.md +113 -0
- package/rules/typescript/tooling/SKILL.md +52 -0
- package/rules/typescript/tooling/references/REFERENCE.md +110 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Blazor
|
|
3
|
+
description: Blazor component patterns for interactive web UIs.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [blazor, components, wasm, server]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.razor', '**/*.razor.cs']
|
|
8
|
+
keywords: [Component, Parameter, CascadingParameter, EventCallback, StateHasChanged]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Blazor
|
|
12
|
+
|
|
13
|
+
## **Priority: P1 (OPERATIONAL)**
|
|
14
|
+
|
|
15
|
+
Blazor component patterns for interactive web UIs.
|
|
16
|
+
|
|
17
|
+
## Implementation Guidelines
|
|
18
|
+
|
|
19
|
+
- **Components**: Keep components focused. Split large components into smaller ones.
|
|
20
|
+
- **Parameters**: Use `[Parameter]` for one-way, `EventCallback` for two-way binding.
|
|
21
|
+
- **Cascading Values**: Use for app-wide state (theme, user context).
|
|
22
|
+
- **State Management**: Component state for local, Fluxor/custom service for global.
|
|
23
|
+
- **Forms**: `EditForm` with `DataAnnotationsValidator` or FluentValidation.
|
|
24
|
+
- **JS Interop**: Use `IJSRuntime` sparingly. Prefer Blazor bindings.
|
|
25
|
+
- **Render Modes**: Choose based on requirements (Server, WASM, Auto in .NET 8+).
|
|
26
|
+
- **Streaming**: Use `[StreamRendering]` for long-loading components.
|
|
27
|
+
|
|
28
|
+
## Anti-Patterns
|
|
29
|
+
|
|
30
|
+
- **No direct DOM manipulation**: Use Blazor bindings and refs.
|
|
31
|
+
- **No `StateHasChanged()` in lifecycle**: Called automatically after lifecycle methods.
|
|
32
|
+
- **No heavy computation in render**: Move to `OnInitialized` or background task.
|
|
33
|
+
- **No sync JS interop in Server mode**: Causes UI blocking.
|
|
34
|
+
|
|
35
|
+
## Code
|
|
36
|
+
|
|
37
|
+
```razor
|
|
38
|
+
@* UserList.razor *@
|
|
39
|
+
@page "/users"
|
|
40
|
+
@attribute [StreamRendering]
|
|
41
|
+
@inject IUserService UserService
|
|
42
|
+
|
|
43
|
+
<PageTitle>Users</PageTitle>
|
|
44
|
+
|
|
45
|
+
<h3>Users</h3>
|
|
46
|
+
|
|
47
|
+
@if (_users is null)
|
|
48
|
+
{
|
|
49
|
+
<p><em>Loading...</em></p>
|
|
50
|
+
}
|
|
51
|
+
else if (_users.Count == 0)
|
|
52
|
+
{
|
|
53
|
+
<p>No users found.</p>
|
|
54
|
+
}
|
|
55
|
+
else
|
|
56
|
+
{
|
|
57
|
+
<div class="user-grid">
|
|
58
|
+
@foreach (var user in _users)
|
|
59
|
+
{
|
|
60
|
+
<UserCard User="user" OnDelete="HandleDelete" />
|
|
61
|
+
}
|
|
62
|
+
</div>
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@code {
|
|
66
|
+
private List<User>? _users;
|
|
67
|
+
|
|
68
|
+
protected override async Task OnInitializedAsync()
|
|
69
|
+
{
|
|
70
|
+
_users = await UserService.GetAllAsync();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private async Task HandleDelete(int userId)
|
|
74
|
+
{
|
|
75
|
+
await UserService.DeleteAsync(userId);
|
|
76
|
+
_users = await UserService.GetAllAsync();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```razor
|
|
82
|
+
@* UserCard.razor - Reusable component *@
|
|
83
|
+
<div class="card">
|
|
84
|
+
<h5>@User.Name</h5>
|
|
85
|
+
<p>@User.Email</p>
|
|
86
|
+
<button @onclick="() => OnDelete.InvokeAsync(User.Id)">Delete</button>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
@code {
|
|
90
|
+
[Parameter, EditorRequired]
|
|
91
|
+
public User User { get; set; } = default!;
|
|
92
|
+
|
|
93
|
+
[Parameter]
|
|
94
|
+
public EventCallback<int> OnDelete { get; set; }
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```razor
|
|
99
|
+
@* EditForm with validation *@
|
|
100
|
+
<EditForm Model="@_model" OnValidSubmit="HandleSubmit" FormName="CreateUser">
|
|
101
|
+
<DataAnnotationsValidator />
|
|
102
|
+
<ValidationSummary class="text-danger" />
|
|
103
|
+
|
|
104
|
+
<div class="mb-3">
|
|
105
|
+
<label class="form-label">Name</label>
|
|
106
|
+
<InputText @bind-Value="_model.Name" class="form-control" />
|
|
107
|
+
<ValidationMessage For="@(() => _model.Name)" />
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div class="mb-3">
|
|
111
|
+
<label class="form-label">Email</label>
|
|
112
|
+
<InputText @bind-Value="_model.Email" class="form-control" type="email" />
|
|
113
|
+
<ValidationMessage For="@(() => _model.Email)" />
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<button type="submit" class="btn btn-primary" disabled="@_isSubmitting">
|
|
117
|
+
@if (_isSubmitting)
|
|
118
|
+
{
|
|
119
|
+
<span class="spinner-border spinner-border-sm"></span>
|
|
120
|
+
}
|
|
121
|
+
Submit
|
|
122
|
+
</button>
|
|
123
|
+
</EditForm>
|
|
124
|
+
|
|
125
|
+
@code {
|
|
126
|
+
private CreateUserModel _model = new();
|
|
127
|
+
private bool _isSubmitting;
|
|
128
|
+
|
|
129
|
+
private async Task HandleSubmit()
|
|
130
|
+
{
|
|
131
|
+
_isSubmitting = true;
|
|
132
|
+
await UserService.CreateAsync(_model);
|
|
133
|
+
_isSubmitting = false;
|
|
134
|
+
NavigationManager.NavigateTo("/users");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Reference & Examples
|
|
140
|
+
|
|
141
|
+
For lifecycle, state management, and JS interop:
|
|
142
|
+
See [references/REFERENCE.md](references/REFERENCE.md).
|
|
143
|
+
|
|
144
|
+
## Related Topics
|
|
145
|
+
|
|
146
|
+
aspnet-core | razor-pages | security
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# Blazor Reference
|
|
2
|
+
|
|
3
|
+
Component lifecycle, state management, and advanced patterns.
|
|
4
|
+
|
|
5
|
+
## References
|
|
6
|
+
|
|
7
|
+
- [**Lifecycle**](lifecycle.md) - Component lifecycle methods.
|
|
8
|
+
- [**State Management**](state-management.md) - Fluxor, cascading values.
|
|
9
|
+
- [**JS Interop**](js-interop.md) - JavaScript interoperability.
|
|
10
|
+
|
|
11
|
+
## Component Lifecycle
|
|
12
|
+
|
|
13
|
+
```csharp
|
|
14
|
+
@code {
|
|
15
|
+
// 1. Called when component is first initialized (before rendering)
|
|
16
|
+
protected override void OnInitialized()
|
|
17
|
+
{
|
|
18
|
+
// Sync initialization
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 1b. Async version (preferred for data loading)
|
|
22
|
+
protected override async Task OnInitializedAsync()
|
|
23
|
+
{
|
|
24
|
+
// Load initial data
|
|
25
|
+
_data = await DataService.GetAsync();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 2. Called when parameters are set/changed
|
|
29
|
+
protected override void OnParametersSet()
|
|
30
|
+
{
|
|
31
|
+
// React to parameter changes
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
protected override async Task OnParametersSetAsync()
|
|
35
|
+
{
|
|
36
|
+
// Async parameter processing
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 3. Called after component has rendered
|
|
40
|
+
protected override void OnAfterRender(bool firstRender)
|
|
41
|
+
{
|
|
42
|
+
if (firstRender)
|
|
43
|
+
{
|
|
44
|
+
// First render only - initialize JS libraries
|
|
45
|
+
}
|
|
46
|
+
// Every render - update DOM-dependent state
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
50
|
+
{
|
|
51
|
+
if (firstRender)
|
|
52
|
+
{
|
|
53
|
+
await JSRuntime.InvokeVoidAsync("initializeChart", _chartElement);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 4. Optimize re-rendering
|
|
58
|
+
protected override bool ShouldRender()
|
|
59
|
+
{
|
|
60
|
+
// Return false to prevent re-rendering
|
|
61
|
+
return _hasChanged;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 5. Cleanup when component is disposed
|
|
65
|
+
public void Dispose()
|
|
66
|
+
{
|
|
67
|
+
// Unsubscribe from events, dispose resources
|
|
68
|
+
_subscription?.Dispose();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Async dispose (IAsyncDisposable)
|
|
72
|
+
public async ValueTask DisposeAsync()
|
|
73
|
+
{
|
|
74
|
+
await JSRuntime.InvokeVoidAsync("cleanup");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## State Management Patterns
|
|
80
|
+
|
|
81
|
+
```csharp
|
|
82
|
+
// 1. Cascading Values - App-wide state
|
|
83
|
+
// App.razor or Routes.razor
|
|
84
|
+
<CascadingValue Value="@_themeState">
|
|
85
|
+
<CascadingValue Value="@_userState">
|
|
86
|
+
<Router AppAssembly="@typeof(App).Assembly">
|
|
87
|
+
...
|
|
88
|
+
</Router>
|
|
89
|
+
</CascadingValue>
|
|
90
|
+
</CascadingValue>
|
|
91
|
+
|
|
92
|
+
@code {
|
|
93
|
+
private ThemeState _themeState = new();
|
|
94
|
+
private UserState _userState = new();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Consuming component
|
|
98
|
+
@code {
|
|
99
|
+
[CascadingParameter]
|
|
100
|
+
public ThemeState Theme { get; set; } = default!;
|
|
101
|
+
|
|
102
|
+
[CascadingParameter]
|
|
103
|
+
public UserState User { get; set; } = default!;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```csharp
|
|
108
|
+
// 2. State Container Service
|
|
109
|
+
public class CartState
|
|
110
|
+
{
|
|
111
|
+
private readonly List<CartItem> _items = [];
|
|
112
|
+
|
|
113
|
+
public IReadOnlyList<CartItem> Items => _items.AsReadOnly();
|
|
114
|
+
public decimal Total => _items.Sum(i => i.Price * i.Quantity);
|
|
115
|
+
|
|
116
|
+
public event Action? OnChange;
|
|
117
|
+
|
|
118
|
+
public void AddItem(CartItem item)
|
|
119
|
+
{
|
|
120
|
+
_items.Add(item);
|
|
121
|
+
NotifyStateChanged();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public void RemoveItem(int productId)
|
|
125
|
+
{
|
|
126
|
+
_items.RemoveAll(i => i.ProductId == productId);
|
|
127
|
+
NotifyStateChanged();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private void NotifyStateChanged() => OnChange?.Invoke();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Registration
|
|
134
|
+
builder.Services.AddScoped<CartState>();
|
|
135
|
+
|
|
136
|
+
// Component usage
|
|
137
|
+
@inject CartState Cart
|
|
138
|
+
@implements IDisposable
|
|
139
|
+
|
|
140
|
+
<div>Total: @Cart.Total.ToString("C")</div>
|
|
141
|
+
|
|
142
|
+
@code {
|
|
143
|
+
protected override void OnInitialized()
|
|
144
|
+
{
|
|
145
|
+
Cart.OnChange += StateHasChanged;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public void Dispose()
|
|
149
|
+
{
|
|
150
|
+
Cart.OnChange -= StateHasChanged;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
```csharp
|
|
156
|
+
// 3. Fluxor (Redux pattern)
|
|
157
|
+
// State
|
|
158
|
+
public record CounterState(int Count);
|
|
159
|
+
|
|
160
|
+
public class CounterFeature : Feature<CounterState>
|
|
161
|
+
{
|
|
162
|
+
public override string GetName() => "Counter";
|
|
163
|
+
protected override CounterState GetInitialState() => new(0);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Actions
|
|
167
|
+
public record IncrementAction();
|
|
168
|
+
public record DecrementAction();
|
|
169
|
+
public record SetCountAction(int Count);
|
|
170
|
+
|
|
171
|
+
// Reducers
|
|
172
|
+
public static class CounterReducers
|
|
173
|
+
{
|
|
174
|
+
[ReducerMethod]
|
|
175
|
+
public static CounterState OnIncrement(CounterState state, IncrementAction _)
|
|
176
|
+
=> state with { Count = state.Count + 1 };
|
|
177
|
+
|
|
178
|
+
[ReducerMethod]
|
|
179
|
+
public static CounterState OnDecrement(CounterState state, DecrementAction _)
|
|
180
|
+
=> state with { Count = state.Count - 1 };
|
|
181
|
+
|
|
182
|
+
[ReducerMethod]
|
|
183
|
+
public static CounterState OnSetCount(CounterState state, SetCountAction action)
|
|
184
|
+
=> state with { Count = action.Count };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Component
|
|
188
|
+
@inject IState<CounterState> CounterState
|
|
189
|
+
@inject IDispatcher Dispatcher
|
|
190
|
+
|
|
191
|
+
<p>Count: @CounterState.Value.Count</p>
|
|
192
|
+
<button @onclick="Increment">+</button>
|
|
193
|
+
<button @onclick="Decrement">-</button>
|
|
194
|
+
|
|
195
|
+
@code {
|
|
196
|
+
private void Increment() => Dispatcher.Dispatch(new IncrementAction());
|
|
197
|
+
private void Decrement() => Dispatcher.Dispatch(new DecrementAction());
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## JS Interop
|
|
202
|
+
|
|
203
|
+
```csharp
|
|
204
|
+
// Calling JavaScript from C#
|
|
205
|
+
@inject IJSRuntime JS
|
|
206
|
+
|
|
207
|
+
@code {
|
|
208
|
+
private ElementReference _inputElement;
|
|
209
|
+
|
|
210
|
+
// Call JS function
|
|
211
|
+
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
212
|
+
{
|
|
213
|
+
if (firstRender)
|
|
214
|
+
{
|
|
215
|
+
await JS.InvokeVoidAsync("initializeComponent", _inputElement);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Call JS function with return value
|
|
220
|
+
private async Task<string> GetLocalStorage(string key)
|
|
221
|
+
{
|
|
222
|
+
return await JS.InvokeAsync<string>("localStorage.getItem", key);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Focus element
|
|
226
|
+
private async Task FocusInput()
|
|
227
|
+
{
|
|
228
|
+
await _inputElement.FocusAsync();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
// wwwroot/js/interop.js
|
|
235
|
+
window.initializeComponent = (element) => {
|
|
236
|
+
// Initialize third-party library
|
|
237
|
+
new SomeLibrary(element);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
window.blazorInterop = {
|
|
241
|
+
showAlert: (message) => alert(message),
|
|
242
|
+
getWindowSize: () => ({ width: window.innerWidth, height: window.innerHeight })
|
|
243
|
+
};
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
```csharp
|
|
247
|
+
// Calling C# from JavaScript
|
|
248
|
+
// In component
|
|
249
|
+
@inject IJSRuntime JS
|
|
250
|
+
|
|
251
|
+
@code {
|
|
252
|
+
private DotNetObjectReference<MyComponent>? _objRef;
|
|
253
|
+
|
|
254
|
+
protected override void OnInitialized()
|
|
255
|
+
{
|
|
256
|
+
_objRef = DotNetObjectReference.Create(this);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
260
|
+
{
|
|
261
|
+
if (firstRender)
|
|
262
|
+
{
|
|
263
|
+
await JS.InvokeVoidAsync("registerCallback", _objRef);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
[JSInvokable]
|
|
268
|
+
public void HandleCallback(string data)
|
|
269
|
+
{
|
|
270
|
+
// Called from JavaScript
|
|
271
|
+
Console.WriteLine($"Received: {data}");
|
|
272
|
+
StateHasChanged();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
public void Dispose()
|
|
276
|
+
{
|
|
277
|
+
_objRef?.Dispose();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
```javascript
|
|
283
|
+
// JavaScript calling C#
|
|
284
|
+
window.registerCallback = (dotNetRef) => {
|
|
285
|
+
window.myCallback = (data) => {
|
|
286
|
+
dotNetRef.invokeMethodAsync('HandleCallback', data);
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// Later...
|
|
291
|
+
myCallback('Some data from JS');
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Render Modes (.NET 8+)
|
|
295
|
+
|
|
296
|
+
```razor
|
|
297
|
+
@* Static Server Rendering (SSR) - Default *@
|
|
298
|
+
@rendermode InteractiveServer
|
|
299
|
+
@rendermode InteractiveWebAssembly
|
|
300
|
+
@rendermode InteractiveAuto
|
|
301
|
+
|
|
302
|
+
@* Per-component render mode *@
|
|
303
|
+
<Counter @rendermode="InteractiveServer" />
|
|
304
|
+
<Counter @rendermode="InteractiveWebAssembly" />
|
|
305
|
+
|
|
306
|
+
@* Streaming rendering for slow data *@
|
|
307
|
+
@attribute [StreamRendering]
|
|
308
|
+
|
|
309
|
+
<h1>Dashboard</h1>
|
|
310
|
+
|
|
311
|
+
@if (_data is null)
|
|
312
|
+
{
|
|
313
|
+
<p>Loading dashboard data...</p>
|
|
314
|
+
}
|
|
315
|
+
else
|
|
316
|
+
{
|
|
317
|
+
<DashboardContent Data="_data" />
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@code {
|
|
321
|
+
private DashboardData? _data;
|
|
322
|
+
|
|
323
|
+
protected override async Task OnInitializedAsync()
|
|
324
|
+
{
|
|
325
|
+
// This data streams to the client as it loads
|
|
326
|
+
_data = await SlowDataService.GetDashboardAsync();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Error Handling
|
|
332
|
+
|
|
333
|
+
```razor
|
|
334
|
+
@* ErrorBoundary for graceful error handling *@
|
|
335
|
+
<ErrorBoundary @ref="_errorBoundary">
|
|
336
|
+
<ChildContent>
|
|
337
|
+
<RiskyComponent />
|
|
338
|
+
</ChildContent>
|
|
339
|
+
<ErrorContent Context="exception">
|
|
340
|
+
<div class="alert alert-danger">
|
|
341
|
+
<h4>Something went wrong</h4>
|
|
342
|
+
<p>@exception.Message</p>
|
|
343
|
+
<button @onclick="Recover">Try Again</button>
|
|
344
|
+
</div>
|
|
345
|
+
</ErrorContent>
|
|
346
|
+
</ErrorBoundary>
|
|
347
|
+
|
|
348
|
+
@code {
|
|
349
|
+
private ErrorBoundary? _errorBoundary;
|
|
350
|
+
|
|
351
|
+
private void Recover()
|
|
352
|
+
{
|
|
353
|
+
_errorBoundary?.Recover();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Authentication in Blazor
|
|
359
|
+
|
|
360
|
+
```razor
|
|
361
|
+
@* Show content based on auth state *@
|
|
362
|
+
<AuthorizeView>
|
|
363
|
+
<Authorized>
|
|
364
|
+
<p>Hello, @context.User.Identity?.Name!</p>
|
|
365
|
+
<a href="account/logout">Logout</a>
|
|
366
|
+
</Authorized>
|
|
367
|
+
<NotAuthorized>
|
|
368
|
+
<a href="account/login">Login</a>
|
|
369
|
+
</NotAuthorized>
|
|
370
|
+
</AuthorizeView>
|
|
371
|
+
|
|
372
|
+
@* Role-based content *@
|
|
373
|
+
<AuthorizeView Roles="Admin,Manager">
|
|
374
|
+
<Authorized>
|
|
375
|
+
<AdminPanel />
|
|
376
|
+
</Authorized>
|
|
377
|
+
<NotAuthorized>
|
|
378
|
+
<p>Access denied</p>
|
|
379
|
+
</NotAuthorized>
|
|
380
|
+
</AuthorizeView>
|
|
381
|
+
|
|
382
|
+
@* Policy-based content *@
|
|
383
|
+
<AuthorizeView Policy="CanEditOrders">
|
|
384
|
+
<button @onclick="EditOrder">Edit</button>
|
|
385
|
+
</AuthorizeView>
|
|
386
|
+
|
|
387
|
+
@* Protect entire page *@
|
|
388
|
+
@page "/admin"
|
|
389
|
+
@attribute [Authorize(Roles = "Admin")]
|
|
390
|
+
|
|
391
|
+
<h1>Admin Dashboard</h1>
|
|
392
|
+
```
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: C# Language Patterns
|
|
3
|
+
description: Modern C# standards for type safety, performance, and maintainability.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [csharp, dotnet, language, types, async]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.cs', '**/*.csproj']
|
|
8
|
+
keywords: [class, record, interface, async, await, linq, nullable, span]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# C# Language Patterns
|
|
12
|
+
|
|
13
|
+
## **Priority: P0 (CRITICAL)**
|
|
14
|
+
|
|
15
|
+
Modern C# standards for type-safe, performant, maintainable code.
|
|
16
|
+
|
|
17
|
+
## Implementation Guidelines
|
|
18
|
+
|
|
19
|
+
- **Nullable Reference Types**: Enable `<Nullable>enable</Nullable>`. Use `?` for nullable, avoid `!` except when compiler can't infer.
|
|
20
|
+
- **Records**: `record` for immutable DTOs, `record struct` for stack-allocated value types.
|
|
21
|
+
- **Pattern Matching**: `is` patterns, `switch` expressions, property/positional patterns.
|
|
22
|
+
- **Async/Await**: Always use `CancellationToken`. `ValueTask` for hot paths. `ConfigureAwait(false)` in libraries.
|
|
23
|
+
- **LINQ**: Prefer method syntax. Avoid multiple enumerations (`ToList()` once). Use `AsNoTracking()` for read-only EF queries.
|
|
24
|
+
- **Generics**: Constraints (`where T : class, new()`), covariance (`out T`), contravariance (`in T`).
|
|
25
|
+
- **Spans**: `Span<T>`, `ReadOnlySpan<T>` for zero-allocation slicing.
|
|
26
|
+
- **Primary Constructors**: C# 12+ `class Foo(int x)` for concise DI.
|
|
27
|
+
- **Collection Expressions**: C# 12+ `[1, 2, 3]` syntax.
|
|
28
|
+
- **Raw String Literals**: `"""multi-line"""` for SQL, JSON templates.
|
|
29
|
+
|
|
30
|
+
## Anti-Patterns
|
|
31
|
+
|
|
32
|
+
- **No `async void`**: Use `async Task`. Exception: event handlers.
|
|
33
|
+
- **No `Task.Result`/`.Wait()`**: Deadlock risk. Always `await`.
|
|
34
|
+
- **No `DateTime.Now`**: Use `DateTimeOffset.UtcNow` for timezone safety.
|
|
35
|
+
- **No string concat in loops**: Use `StringBuilder` or `string.Join`.
|
|
36
|
+
- **No `!` abuse**: Prefer null checks or `??` over null-forgiving.
|
|
37
|
+
|
|
38
|
+
## Code
|
|
39
|
+
|
|
40
|
+
```csharp
|
|
41
|
+
// Record with primary constructor
|
|
42
|
+
public record UserDto(string Name, string Email);
|
|
43
|
+
|
|
44
|
+
// Pattern matching with switch expression
|
|
45
|
+
string GetStatus(Order order) => order switch
|
|
46
|
+
{
|
|
47
|
+
{ Status: OrderStatus.Pending } => "Waiting",
|
|
48
|
+
{ Status: OrderStatus.Shipped, TrackingNumber: not null } => "In Transit",
|
|
49
|
+
{ IsCancelled: true } => "Cancelled",
|
|
50
|
+
_ => "Unknown"
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Async with cancellation token
|
|
54
|
+
async Task<User?> GetUserAsync(int id, CancellationToken ct = default)
|
|
55
|
+
{
|
|
56
|
+
return await _db.Users
|
|
57
|
+
.AsNoTracking()
|
|
58
|
+
.FirstOrDefaultAsync(u => u.Id == id, ct);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Span for zero-allocation parsing
|
|
62
|
+
ReadOnlySpan<char> GetFirstWord(ReadOnlySpan<char> text)
|
|
63
|
+
{
|
|
64
|
+
int idx = text.IndexOf(' ');
|
|
65
|
+
return idx < 0 ? text : text[..idx];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Primary constructor (C# 12)
|
|
69
|
+
public class UserService(IUserRepository repo, ILogger<UserService> logger)
|
|
70
|
+
{
|
|
71
|
+
public async Task<User?> GetAsync(int id) => await repo.GetByIdAsync(id);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Reference & Examples
|
|
76
|
+
|
|
77
|
+
For advanced patterns, spans, and nullable annotations:
|
|
78
|
+
See [references/REFERENCE.md](references/REFERENCE.md).
|
|
79
|
+
|
|
80
|
+
## Related Topics
|
|
81
|
+
|
|
82
|
+
best-practices | security | tooling
|