/collect-user-input
Build forms, validate data, and react to user input in Blazor. USE FOR adding forms, search boxes, filter panels, inline editing, data-entry UI, file uploads, validation (annotations or custom), handling form submissions, and binding input controls. Covers EditForm, built-in
$ npx -y skills add managedcode/dotnet-skills --skill collect-user-input --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/collect-user-input
Context preview
The summary Claude sees to decide when to auto-load this skill.
Build forms, validate data, and react to user input in Blazor. USE FOR adding forms, search boxes, filter panels, inline editing, data-entry UI, file uploads, validation (annotations or custom), handling form submissions, and binding input controls. Covers EditForm, built-in
SKILL.md
collect-user-input.SKILL.mdlicense: MIT
name: collect-user-input
description: Build forms, validate data, and react to user input in Blazor. USE FOR adding forms, search boxes, filter panels, inline editing, data-entry UI, file uploads, validation (annotations or custom), handling form submissions, and binding input controls. Covers EditForm, built-in input components, DataAnnotationsValidator, custom validation, SSR form patterns (SupplyParameterFromForm, FormName, AntiforgeryToken, Enhance), and @bind for simple interactive controls. DO NOT USE for project scaffolding (see create-blazor-project) or prerendering issues (see support-prerendering).
Collect User Input
Step 1 — Read the Project's AGENTS.md
Check `AGENTS.md` for **Interactivity Mode** and **Interactivity Scope**. This determines which form patterns apply:
| Mode | Form mechanism | |------|---------------| | None (Static SSR) | `EditForm` with `FormName` + `[SupplyParameterFromForm]`. No `@bind`, no `@onchange`. | | Server | `EditForm` with `@bind-Value`. Full interactivity — real-time validation, dynamic UI. | | WebAssembly | Same as Server, but validators needing server data must call APIs. | | Auto | Same as WebAssembly — code must work in both browser and server. |
| Scope | Impact | |-------|--------| | Global | All forms are interactive. `FormName` only needed when explicitly opting a page to static SSR. | | Per-page | Forms in static pages use `FormName` + `[SupplyParameterFromForm]`. Forms in `@rendermode` pages use `@bind-Value`. |
EditForm Setup
`EditForm` requires **either** `Model` or `EditContext` — never both.
Model-based (default)
<EditForm Model="Employee" OnValidSubmit="HandleSubmit" FormName="employee">
<DataAnnotationsValidator />
<ValidationSummary />
<label>
Name: <InputText @bind-Value="Employee!.Name" />
<ValidationMessage For="() => Employee!.Name" />
</label>
<button type="submit">Save</button>
</EditForm>
@code {
[SupplyParameterFromForm]
private EmployeeModel? Employee { get; set; }
protected override void OnInitialized() => Employee ??= new();
private async Task HandleSubmit()
{
// Save Employee
}
}This single pattern works in **both** SSR and interactive modes:
- In SSR: `FormName` identifies the form, `[SupplyParameterFromForm]` binds POST data, `??=` initializes on GET.
- In interactive: `@bind-Value` provides two-way binding, `[SupplyParameterFromForm]` is ignored, `FormName` is harmless.
EditContext-based (advanced)
Use when you need programmatic field tracking, dynamic validation rules, or manual `EditContext.Validate()` calls:
private EditContext? editContext;
private EmployeeModel model = new();
protected override void OnInitialized()
{
editContext = new EditContext(model);
}<EditForm EditContext="editContext" OnValidSubmit="HandleSubmit" FormName="employee">
Submit Handlers
| Handler | Fires when | Use when | |---------|-----------|----------| | `OnValidSubmit` | Validation passes | Standard forms with `DataAnnotationsValidator` | | `OnInvalidSubmit` | Validation fails | Need custom handling for invalid state | | `OnSubmit` | Always — validation is manual | Using `EditContext.Validate()` yourself |
`OnSubmit` cannot combine with `OnValidSubmit`/`OnInvalidSubmit`.
Built-in Input Components
| Component | Binds to | Notes | |-----------|----------|-------| | `InputText` | `string` | Renders `<input type="text">` | | `InputTextArea` | `string` | Renders `<textarea>` | | `InputNumber<T>` | `int`, `double`, `decimal` | Renders `<input type="number">` | | `InputDate<T>` | `DateTime`, `DateOnly`, `DateTimeOffset` | Renders `<input type="date">` | | `InputCheckbox` | `bool` | Renders `<input type="checkbox">` | | `InputSelect<T>` | `string`, enums, numeric types | Renders `<select>` | | `InputRadioGroup<T>` | `string`, enums, numeric types | Wraps `InputRadio<T>` children | | `InputFile` | `IBrowserFile` | File upload — interactive modes only |
All input components use `@bind-Value` for binding. Always wrap text in a `<label>` or use `id`/`for` attributes for accessibility.
InputSelect with enum values
<InputSelect @bind-Value="Model!.Status">
<option value="">-- Select --</option>
@foreach (var value in Enum.GetValues<OrderStatus>())
{
<option value="@value">@value</option>
}
</InputSelect>InputRadioGroup
<InputRadioGroup @bind-Value="Model!.Priority">
@foreach (var p in Enum.GetValues<Priority>())
{
<label>
<InputRadio Value="p" /> @p
</label>
}
</InputRadioGroup>Validation
Data annotations
Define validation rules on the model:
public class EmployeeModel
{
[Required, StringLength(100)]
public string? Name { get; set; }
[Required, EmailAddress]
public string? Email { get; set; }
[Range(18, 99)]
public int Age { get; set; }
[Required]
public string? Department { get; set; }
}Add `<DataAnnotationsValidator />` inside `EditForm` — without it, annotation attributes are silently ignored.
Display errors with:
- `<ValidationSummary />` — all errors in a list
- `<ValidationMessage For="() => Model!.FieldName" />` — per-field inline errors
Custom validator component
For server-round-trip validation (uniqueness checks, business rules):
public class CustomValidator : ComponentBase
{
[CascadingParameter]
private EditContext? EditContext { get; set; }
private ValidationMessageStore? messageStore;
protected override void OnInitialized()
{
messageStore = new ValidationMessageStore(EditContext!);
EditContext!.OnValidationRequested += (s, e) => messageStore.Clear();
EditContext!.OnFieldChanged += (s, e) => messageStore.Clear(e.FieldIdentifier);
}
public void DisplayErrors(Dictionary<string, List<string>> errors)
{
foreach (varRead more
license: MIT name: collect-user-input description: Build forms, validate data, and react to user input in Blazor. USE FOR adding forms, search boxes, filter panels, inline editing, data-entry UI, file uploads, validation (annotations or custom), handling form submissions, and binding input controls. Covers EditForm, built-in input components, DataAnnotationsValidator, custom validation, SSR form patterns (SupplyParameterFromForm, FormName, AntiforgeryToken, Enhance), and @bind for simple interactive controls. DO NOT USE for project scaffolding (see create-blazor-project) or prerendering issues (see support-prerendering).
Collect User Input
Step 1 — Read the Project's AGENTS.md
Check `AGENTS.md` for **Interactivity Mode** and **Interactivity Scope**. This determines which form patterns apply:
| Mode | Form mechanism | |------|---------------| | None (Static SSR) | `EditForm` with `FormName` + `[SupplyParameterFromForm]`. No `@bind`, no `@onchange`. | | Server | `EditForm` with `@bind-Value`. Full interactivity — real-time validation, dynamic UI. | | WebAssembly | Same as Server, but validators needing server data must call APIs. | | Auto | Same as WebAssembly — code must work in both browser and server. |
| Scope | Impact | |-------|--------| | Global | All forms are interactive. `FormName` only needed when explicitly opting a page to static SSR. | | Per-page | Forms in static pages use `FormName` + `[SupplyParameterFromForm]`. Forms in `@rendermode` pages use `@bind-Value`. |
EditForm Setup
`EditForm` requires **either** `Model` or `EditContext` — never both.
Model-based (default)
<EditForm Model="Employee" OnValidSubmit="HandleSubmit" FormName="employee">
<DataAnnotationsValidator />
<ValidationSummary />
<label>
Name: <InputText @bind-Value="Employee!.Name" />
<ValidationMessage For="() => Employee!.Name" />
</label>
<button type="submit">Save</button>
</EditForm>
@code {
[SupplyParameterFromForm]
private EmployeeModel? Employee { get; set; }
protected override void OnInitialized() => Employee ??= new();
private async Task HandleSubmit()
{
// Save Employee
}
}This single pattern works in **both** SSR and interactive modes:
- In SSR: `FormName` identifies the form, `[SupplyParameterFromForm]` binds POST data, `??=` initializes on GET.
- In interactive: `@bind-Value` provides two-way binding, `[SupplyParameterFromForm]` is ignored, `FormName` is harmless.
EditContext-based (advanced)
Use when you need programmatic field tracking, dynamic validation rules, or manual `EditContext.Validate()` calls:
private EditContext? editContext;
private EmployeeModel model = new();
protected override void OnInitialized()
{
editContext = new EditContext(model);
}<EditForm EditContext="editContext" OnValidSubmit="HandleSubmit" FormName="employee">
Submit Handlers
| Handler | Fires when | Use when | |---------|-----------|----------| | `OnValidSubmit` | Validation passes | Standard forms with `DataAnnotationsValidator` | | `OnInvalidSubmit` | Validation fails | Need custom handling for invalid state | | `OnSubmit` | Always — validation is manual | Using `EditContext.Validate()` yourself |
`OnSubmit` cannot combine with `OnValidSubmit`/`OnInvalidSubmit`.
Built-in Input Components
| Component | Binds to | Notes | |-----------|----------|-------| | `InputText` | `string` | Renders `<input type="text">` | | `InputTextArea` | `string` | Renders `<textarea>` | | `InputNumber<T>` | `int`, `double`, `decimal` | Renders `<input type="number">` | | `InputDate<T>` | `DateTime`, `DateOnly`, `DateTimeOffset` | Renders `<input type="date">` | | `InputCheckbox` | `bool` | Renders `<input type="checkbox">` | | `InputSelect<T>` | `string`, enums, numeric types | Renders `<select>` | | `InputRadioGroup<T>` | `string`, enums, numeric types | Wraps `InputRadio<T>` children | | `InputFile` | `IBrowserFile` | File upload — interactive modes only |
All input components use `@bind-Value` for binding. Always wrap text in a `<label>` or use `id`/`for` attributes for accessibility.
InputSelect with enum values
<InputSelect @bind-Value="Model!.Status">
<option value="">-- Select --</option>
@foreach (var value in Enum.GetValues<OrderStatus>())
{
<option value="@value">@value</option>
}
</InputSelect>InputRadioGroup
<InputRadioGroup @bind-Value="Model!.Priority">
@foreach (var p in Enum.GetValues<Priority>())
{
<label>
<InputRadio Value="p" /> @p
</label>
}
</InputRadioGroup>Validation
Data annotations
Define validation rules on the model:
public class EmployeeModel
{
[Required, StringLength(100)]
public string? Name { get; set; }
[Required, EmailAddress]
public string? Email { get; set; }
[Range(18, 99)]
public int Age { get; set; }
[Required]
public string? Department { get; set; }
}Add `<DataAnnotationsValidator />` inside `EditForm` — without it, annotation attributes are silently ignored.
Display errors with:
- `<ValidationSummary />` — all errors in a list
- `<ValidationMessage For="() => Model!.FieldName" />` — per-field inline errors
Custom validator component
For server-round-trip validation (uniqueness checks, business rules):
public class CustomValidator : ComponentBase
{
[CascadingParameter]
private EditContext? EditContext { get; set; }
private ValidationMessageStore? messageStore;
protected override void OnInitialized()
{
messageStore = new ValidationMessageStore(EditContext!);
EditContext!.OnValidationRequested += (s, e) => messageStore.Clear();
EditContext!.OnFieldChanged += (s, e) => messageStore.Clear(e.FieldIdentifier);
}
public void DisplayErrors(Dictionary<string, List<string>> errors)
{
foreach (varStop explaining .NET to your AI. Start building. We've all been there: asking Claude to use Entity Framework, only to get EF6 patterns in a .NET 8 project. Explaining to Copilot that Blazor Server and Blazor WebAssembly aren't the same thing.
Repo: managedcode/dotnet-skills
Other skills on dotnet-skills.
- /aspnet-core
Build, debug, modernize, or review ASP.NET Core applications with correct hosting, middleware, security, configuration, logging, and deployment patterns on current .NET. USE FOR: working on ASP.NET Core apps, services, or middleware; changing auth, routing, configuration,
Open skill - /aspire
Build, upgrade, and operate Aspire 13.4.x C# or TypeScript application hosts with the current CLI, AppHost, ServiceDefaults, integrations, dashboard, testing, MCP, and deployment patterns for distributed apps. USE FOR: Aspire.AppHost.Sdk, Aspire.Hosting.*,
Open skill - /azure-functions
Build, review, or migrate Azure Functions in .NET with correct execution model, isolated worker setup, bindings, DI, and Durable Functions patterns. USE FOR: working on Azure Functions in .NET; migrating from the in-process model to the isolated worker model; adding Durable
Open skill - /blazor
Build and review Blazor applications across server, WebAssembly, web app, and hybrid scenarios with correct component design, state flow, rendering, and hosting choices. USE FOR: building interactive web UIs with C# instead of JavaScript; choosing between Server, WebAssembly, or
Open skill - /entity-framework6
Maintain or migrate EF6-based applications with realistic guidance on what to keep, what to modernize, and when EF Core is or is not the right next step. USE FOR: EF6 codebases; runtime versus ORM migration decisions; EDMX, code-first, ObjectContext, and legacy data-access
Open skill - /entity-framework-core
Design, tune, or review EF Core data access with proper modeling, migrations, query translation, performance, and lifetime management for modern .NET applications. USE FOR: DbContext, migrations, model configuration, EF queries, tracking, loading, performance, transactions, and
Open skill

