Skip to content
Development
Skill

/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

From plugin
dotnet-skills
5.1k96 skills16 agents
Install
$ npx -y skills add dotnet/skills --skill collect-user-input --agent claude-code

How 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.md
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 (var
Read more
Ships withdotnet-skills

This repository contains the .NET team's curated set of core skills and custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io. 📊 Dashboard - Accuracy and efficiency scoring trends for contained plugins (

Get the whole plugin

Other skills on dotnet-skills.