Skip to main content

aspnetcore-blazor10

Provides up-to-date information about ASP.NET Core 10 and Blazor .NET 10 new features. Use when the user asks about Blazor .NET 10 capabilities, ASP.NET Core 10 features, OpenAPI, Minimal APIs, SignalR, or needs guidance on ASP.NET Core/Blazor .NET 10 specific features.

소스 정보

저장소
runceel/ai-dev-template
최근 소스 활동
2026년 4월 24일 02:50
감지된 SKILL.md 언어
영어
스타
11
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
aspnetcore-blazor10
description
Provides up-to-date information about ASP.NET Core 10 and Blazor .NET 10 new features. Use when the user asks about Blazor .NET 10 capabilities, ASP.NET Core 10 features, OpenAPI, Minimal APIs, SignalR, or needs guidance on ASP.NET Core/Blazor .NET 10 specific features.
# ASP.NET Core 10 / Blazor .NET 10 New Features Reference Source: https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-10.0 --- ## Blazor ### Blazor Component Coding Conventions 以下のルールに従ってコンポーネントを実装すること。 #### コードビハインド分離(`@code` ブロック禁止) `.razor` ファイルに `@code {}` ブロックを記述せず、C# コードは `.razor.cs` ファイルに分離する。コードビハインドクラスは `partial class` として定義する。 ```razor @* Counter.razor — マークアップのみ *@ @page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button @onclick="IncrementCount">Click me</button> ``` ```csharp // Counter.razor.cs public partial class Counter { private int currentCount; private void IncrementCount() { currentCount++; } } ``` #### DI はコンストラクターインジェクションを使用 `@inject` ディレクティブや `[Inject]` 属性ではなく、コンストラクターインジェクションを使用する。.NET 10 の Blazor コンポーネントではコンストラクターインジェクションがサポートされている。 ```csharp // MyComponent.razor.cs public partial class MyComponent(IMyService myService, NavigationManager navigationManager) { protected override async Task OnInitializedAsync() { var data = await myService.GetDataAsync(); } } ``` #### コンポーネント固有の CSS は `.razor.css` に分離 コンポーネントに固有のスタイルはコンポーネントと同名の `.razor.css` ファイルに定義する(CSS isolation)。 ```css /* Counter.razor.css */ h1 { color: #333; } button { background-color: #0078d4; color: white; } ``` --- ### QuickGrid Enhancements **`RowClass` parameter** — Apply a CSS class to a row based on row item: ```razor <QuickGrid Items="movies" RowClass="GetRowCssClass"> <PropertyColumn Property="@(m => m.Title)" /> </QuickGrid> @code { private string? GetRowCssClass(Movie item) => item.IsArchived ? "row-archived" : null; } ``` **`HideColumnOptionsAsync`** — Close column options UI programmatically: ```razor <QuickGrid @ref="grid" Items="items"> <PropertyColumn Property="@(m => m.Title)"> <ColumnOptions> <input @bind="filter" @bind:after="@(() => grid.HideColumnOptionsAsync())" /> </ColumnOptions> </PropertyColumn> </QuickGrid> ``` --- ### `[PersistentState]` — Declarative Prerendering State Persistence Before (.NET 9): ```razor @implements IDisposable @inject PersistentComponentState ApplicationState @code { public List<Movie>? MoviesList { get; set; } private PersistingComponentStateSubscription? sub; protected override async Task OnInitializedAsync() { if (!ApplicationState.TryTakeFromJson<List<Movie>>(nameof(MoviesList), out var movies)) MoviesList = await MovieService.GetMoviesAsync(); else MoviesList = movies; sub = ApplicationState.RegisterOnPersisting(() => { ApplicationState.PersistAsJson(nameof(MoviesList), MoviesList); return Task.CompletedTask; }); } public void Dispose() => sub?.Dispose(); } ``` After (.NET 10): ```razor @code { [PersistentState] public List<Movie>? MoviesList { get; set; } protected override async Task OnInitializedAsync() { MoviesList ??= await MovieService.GetMoviesAsync(); } } ``` **`AllowUpdates`** — opt-in to update state during enhanced navigation: ```csharp [PersistentState(AllowUpdates = true)] public WeatherForecast[]? Forecasts { get; set; } ``` **`RestoreBehavior`** options: ```csharp [PersistentState(RestoreBehavior = RestoreBehavior.SkipInitialValue)] public string NoPrerenderedData { get; set; } [PersistentState(RestoreBehavior = RestoreBehavior.SkipLastSnapshot)] public int CounterNotRestoredOnReconnect { get; set; } ``` **Custom serializer for persistent state:** ```csharp // Program.cs builder.Services.AddSingleton<PersistentComponentStateSerializer<TUser>, CustomUserSerializer>(); ``` --- ### Improved Form Validation Validates nested objects and collection items. Uses source generator (AOT-compatible) instead of reflection. **Setup:** ```csharp // Program.cs builder.Services.AddValidation(); ``` **Model** (must be a `.cs` file, not inline in `.razor`): ```csharp [ValidatableType] // required on root type only public class Order { public Customer Customer { get; set; } = new(); public List<OrderItem> OrderItems { get; set; } = []; } public class Customer { [Required(ErrorMessage = "Name is required.")] public string? FullName { get; set; } [Required(ErrorMessage = "Email is required.")] [EmailAddress] public string? Email { get; set; } } ``` **Component** — uses `DataAnnotationsValidator` as before: ```razor <EditForm Model="Model"> <DataAnnotationsValidator /> <InputText @bind-Value="Model!.Customer.FullName" /> <ValidationMessage For="@(() => Model!.Customer.FullName)" /> </EditForm> ``` **Validation rules** (all applied in order; short-circuits on first error): 1. Member property attributes (including nested objects) 2. Type-level attributes 3. `IValidatableObject.Validate` `[SkipValidation]` to exclude specific properties or types from validation. --- ### New JavaScript Interop APIs **Create a JS object instance:** ```csharp // Async var objRef = await JSRuntime.InvokeConstructorAsync("MyLib.MyClass", arg1, arg2); var value = await objRef.GetValueAsync<string>("propertyName"); await objRef.SetValueAsync("propertyName", newValue); // Sync (in-process) var inProc = (IJSInProcessRuntime)JSRuntime; var objRef = inProc.InvokeConstructor("MyLib.MyClass", arg1); var value = objRef.GetValue<string>("propertyName"); inProc.SetValue("propertyName", newValue); ``` **Read/write JS object properties:** ```csharp // Read var num = await JSRuntime.GetValueAsync<int>("myLib.config.retryCount"); // Write await JSRuntime.SetValueAsync("myLib.config.retryCount", 5); ``` --- ### Not Found Handling **`Router.NotFoundPage` parameter** — specify a page for 404: ```razor <Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)"> <Found Context="routeData"> <RouteView RouteData="@routeData" /> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> <!-- <NotFound> is ignored when NotFoundPage is defined --> </Router> ``` **`NavigationManager.NotFound()`** — trigger Not Found programmatically: ```csharp @inject NavigationManager Nav protected override async Task OnInitializedAsync() { var item = await Service.GetItemAsync(Id); if (item is null) Nav.NotFound(); } ``` Behavior: - Static SSR: sets HTTP 404 - Interactive rendering: renders the `NotFoundPage` - Streaming rendering: renders `NotFoundPage` via enhanced navigation Subscribe to notifications: `NavigationManager.OnNotFound`. --- ### Passkey (WebAuthn/FIDO2) Support for ASP.NET Core Identity Password-less login using biometrics or security keys. Built into the Blazor Web App project template. ```csharp // Program.cs — already included in the new project template builder.Services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); ``` See: https://learn.microsoft.com/aspnet/core/security/authentication/passkeys --- ### Circuit State Persistence Server-side Blazor (SignalR) sessions survive connection loss without losing unsaved work: - Browser tab throttling - Mobile app switching - Network interruptions - Proactive pausing of inactive circuits - Enhanced navigation See: https://learn.microsoft.com/aspnet/core/blazor/state-management/server --- ### Hot Reload for Blazor WebAssembly ```xml <!-- Enabled by default for Debug configuration --> <WasmEnableHotReload>true</WasmEnableHotReload> ``` --- ### Navigation Changes - **`NavigateTo` same-page**: No longer scrolls to top (viewport preserved on query string / fragment changes) - **`NavLink` with `NavLinkMatch.All`**: Ignores query string and fragment — link stays `active` on path match Revert: set `AppContext` switch `Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragment` to `true` Override matching: ```csharp public class CustomNavLink : NavLink { protected override bool ShouldMatch(string currentUriAbsolute) { ... } } ``` --- ### Disable `NavigationException` during Static SSR ```xml <!-- Program.cs template sets this to true by default in .NET 10 --> <BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException> ``` With this set, `NavigationManager.NavigateTo` during static SSR no longer throws `NavigationException`. Code after `NavigateTo` executes before the redirect occurs. --- ### Reconnection UI (`ReconnectModal`) Template now includes a `ReconnectModal` component with collocated CSS/JS. CSP-compliant (no inline styles). New event: `components-reconnect-state-changed` New state: `"retrying"` (in addition to existing states) --- ### `OwningComponentBase` implements `IAsyncDisposable` ```csharp // DisposeAsync and DisposeAsyncCore now available public class MyComponent : OwningComponentBase { // async cleanup supported } ``` --- ### New `InputHidden` Component ```razor <EditForm Model="Parameter" OnValidSubmit="Submit" FormName="Example"> <InputHidden id="hidden" @bind-Value="Parameter" /> <button type="submit">Submit</button> </EditForm> @code { [SupplyParameterFromForm] public string Parameter { get; set; } = "stranger"; private void Submit() { } } ``` --- ### Client-Side Fingerprinting (Standalone Blazor WebAssembly) ```xml <!-- .csproj --> <OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders> ``` ```html <!-- wwwroot/index.html --> <head> <script type="importmap"></script> </head> <body> <script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script> </body> ``` Fingerprint JS modules: ```html <script type="module" src="js/scripts#[.{fingerprint}].js"></script> ``` ```xml <ItemGroup> <StaticWebAssetFingerprintPattern Include="JSModule" Pattern="*.js" Expression="#[.{fingerprint}]!" /> </ItemGroup> ``` --- ### WebAssembly Environment Configuration ```xml <!-- No longer uses launchSettings.json --> <WasmApplicationEnvironmentName>Staging</WasmApplicationEnvironmentName> ``` Defaults: `Development` (build), `Production` (publish). --- ### `HttpClient` Response Streaming Enabled by Default `response.Content.ReadAsStreamAsync()` now returns `BrowserHttpReadStream` (not `MemoryStream`). Synchronous `Stream.Read` is not supported. Opt out globally: ```xml <WasmEnableStreamingResponse>false</WasmEnableStreamingResponse> ``` Opt out per request: ```csharp requestMessage.SetBrowserResponseStreamingEnabled(false); ``` --- ### Static Asset Preloading **Blazor Web Apps** — use `<ResourcePreloader />` component: ```razor <!-- App.razor --> <head> <base href="/" /> <ResourcePreloader /> </head> ``` **Standalone Blazor WebAssembly** — add `<link rel="preload" id="webassembly" />` in `wwwroot/index.html` (requires `OverrideHtmlAssetPlaceholders`). --- ### Blazor Script as Static Web Asset
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기