Обзор форм ASP.NET Core Blazor

Примечание.

Это не последняя версия этой статьи. Текущий выпуск можно найти в версии этой статьи о .NET 10.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Для получения дополнительной информации см. Политику поддержки .NET и .NET Core. Текущий выпуск можно найти в версии этой статьи о .NET 10.

В этой статье объясняется, как использовать формы в Blazor.

Входные компоненты и формы

Платформа Blazor поддерживает формы и предоставляет встроенные компоненты ввода:

Примечание.

Неподдерживаемые функции проверки ASP.NET Core рассматриваются в разделе Unsupported validation features.

Пространство имен Майкрософт.AspNetCore.Components.Forms предоставляет:

  • Классы для управления элементами формы, состоянием и проверкой.
  • Доступ к встроенным Input* компонентам.

Проект, созданный из Blazor шаблона проекта, включает пространство имен в файл приложения _Imports.razor , что делает пространство имен доступным для компонентов приложения Razor .

Поддерживаются стандартные ФОРМЫ HTML. Создайте форму с помощью обычного HTML-тега <form> и укажите @onsubmit обработчик для обработки отправленного запроса формы.

StarshipPlainForm.razor:

@page "/starship-plain-form"
@inject ILogger<StarshipPlainForm> Logger

<form method="post" @onsubmit="Submit" @formname="starship-plain-form">
    <AntiforgeryToken />
    <div>
        <label>
            Identifier: 
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</form>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        public string? Id { get; set; }
    }
}
@page "/starship-plain-form"
@inject ILogger<StarshipPlainForm> Logger

<form method="post" @onsubmit="Submit" @formname="starship-plain-form">
    <AntiforgeryToken />
    <div>
        <label>
            Identifier: 
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</form>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        public string? Id { get; set; }
    }
}

В предыдущем компоненте StarshipPlainForm:

  • Форма отображается в том месте, где появляется элемент <form>. Форма именуется с помощью атрибута @formname директивы, который однозначно идентифицирует форму на платформе Blazor.
  • Модель создается в блоке @code компонента и хранится в свойстве public (Model). Атрибут [SupplyParameterFromForm] указывает, что значение связанного свойства должно быть предоставлено из данных формы. Данные в запросе, который соответствует имени свойства, привязаны к свойству.
  • Компонент InputText является входным компонентом для редактирования строковых значений. Атрибут директивы @bind-Value привязывает свойство модели Model.Id к свойству InputText компонента Value.
  • Метод Submit зарегистрирован в качестве обработчика для обратного вызова @onsubmit. Обработчик вызывается, когда форма отправляется пользователем.

Внимание

Всегда используйте атрибут директивы @formname с уникальным именем формы.

Blazor улучшает навигацию по страницам и обработку форм путем перехвата запроса, чтобы применить ответ к существующей модели DOM, сохраняя столько отрисованной формы, сколько это возможно. Это улучшение позволяет избежать полной загрузки страницы и обеспечивает более плавный пользовательский опыт, аналогичный одностраничному приложению (SPA), несмотря на то, что компоненты отрисовываются на сервере. Дополнительные сведения см. в разделе ASP.NET Core Blazor навигации.

Потоковая отрисовка поддерживается для простых HTML-форм. Обратите внимание, что при POSTобработке формы транслируются только обновления DOM внутри обработчиков формы (например, @onsubmit). Обновления внутри OnInitializedAsync стримятся только для GET запросов. Дополнительные сведения см. в разделе "Разрешить потоковую передачу" этапа загрузки ответов POST (dotnet/aspnetcore #50994).

Примечание.

Ссылки на справочную документацию .NET обычно ведут на ветвь репозитория по умолчанию, которая представляет собой текущую разработку следующего релиза .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список ветвей switch или тегов . Дополнительные сведения см. в разделе Как выбрать тег версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Предыдущий пример включает поддержку защиты от подделки, включив компонент AntiforgeryToken в форму. Поддержка антиподделки объясняется далее в разделе поддержка антиподделки в этой статье.

Чтобы отправить форму на основе событий DOM другого элемента, например oninputonblur, используйте JavaScript для отправки формы (submit).

Вместо использования простых форм в Blazor приложениях форма обычно определяется с встроенной поддержкой форм от Blazor с помощью компонента фреймворка EditForm. Razor Следующий компонент демонстрирует типичные элементы, компоненты и Razor код для отрисовки EditForm веб-формы с помощью компонента.

Форма определяется с помощью компонента Blazor платформы EditForm. Razor Следующий компонент демонстрирует типичные элементы, компоненты и Razor код для рендеринга веб-формы с помощью компонента EditForm.

Starship1.razor:

@page "/starship-1"
@inject ILogger<Starship1> Logger

<EditForm Model="Model" OnSubmit="Submit" FormName="Starship1">
    <div>
        <label>
            Identifier:
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        public string? Id { get; set; }
    }
}
@page "/starship-1"
@inject ILogger<Starship1> Logger

<EditForm Model="Model" OnSubmit="Submit" FormName="Starship1">
    <div>
        <label>
            Identifier:
            <InputText @bind-Value="Model!.Id" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        public string? Id { get; set; }
    }
}

В предыдущем компоненте Starship1:

  • Компонент EditForm отображается там, где находится элемент <EditForm>. Форма называется свойством FormName, которое однозначно идентифицирует форму для платформы Blazor.
  • Модель создается в блоке @code компонента и хранится в свойстве public (Model). Свойство назначается параметру EditForm.Model . Атрибут [SupplyParameterFromForm] указывает, что значение связанного свойства должно быть предоставлено из данных формы. Данные в запросе, который соответствует имени свойства, привязаны к свойству.
  • Компонент InputText является входным компонентомдля редактирования строковых значений. Атрибут директивы @bind-Value привязывает свойство модели Model.Id к свойству InputText компонента Value.
  • Метод Submit регистрируется в качестве обработчика для обратного OnSubmit вызова. Обработчик вызывается, когда форма отправляется пользователем.

Внимание

Всегда используйте свойство FormName с уникальным именем формы.

Blazor улучшает навигацию по страницам и обработку форм для EditForm компонентов. Дополнительные сведения см. в разделе ASP.NET Core Blazor навигации.

Потоковая отрисовка поддерживается для EditForm. Обратите внимание, что при POSTобработке формы транслируются только обновления DOM внутри обработчиков формы (например, OnValidSubmit). Обновления внутри OnInitializedAsync стримятся только для GET запросов. Дополнительные сведения см. в разделе "Разрешить потоковую передачу" этапа загрузки ответов POST (dotnet/aspnetcore #50994).

Примечание.

Ссылки на справочную документацию платформы .NET обычно загружают ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список ветвей switch или тегов . Дополнительные сведения см. в разделе Как выбрать версию тега исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

@page "/starship-1"
@inject ILogger<Starship1> Logger

<EditForm Model="Model" OnSubmit="Submit">
    <InputText @bind-Value="Model!.Id" />
    <button type="submit">Submit</button>
</EditForm>

@code {
    public Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit()
    {
        Logger.LogInformation("Model.Id = {Id}", Model?.Id);
    }

    public class Starship
    {
        public string? Id { get; set; }
    }
}

В предыдущем компоненте Starship1:

  • Компонент EditForm отображается там, где находится элемент <EditForm>.
  • Модель создается в блоке @code компонента и хранится в частном поле (model). Поле назначается параметру EditForm.Model .
  • Компонент InputText является входным компонентом для редактирования строковых значений. @bind-Value Атрибут директивы привязывает Model.Id свойство модели к InputText свойству компонентаValue†.
  • Метод Submit регистрируется в качестве обработчика для колбэка OnSubmit. Обработчик вызывается, когда форма отправляется пользователем.

Для получения дополнительной информации о привязке свойств см. привязку данных в ASP.NET CoreBlazor.

В следующем примере предыдущий компонент изменяется, чтобы создать форму в компоненте Starship2 :

  • OnSubmit заменяется на OnValidSubmit, который выполняет назначенный обработчик событий, если форма действительна при отправке.
  • Компонент ValidationSummary добавляется для отображения сообщений проверки, когда форма недопустима при отправке формы.
  • Валидатор аннотаций данных (DataAnnotationsValidator компонент†) подключает поддержку проверки с использованием аннотаций данных.
    • <input> Если поле формы остается пустым при выборе Submit кнопки, ошибка отображается в сводке проверки (ValidationSummary компонент) ("The Id field is required."), и Submitне вызывается.
    • <input> Если поле формы содержит более десяти символов при Submit выборе кнопки, в сводке проверки отображается ошибка ("Id is too long."). Submit не вызывается.
    • Если при нажатии кнопки <input> поле формы Submit содержит допустимое значение, Submit вызывается.

Компонент DataAnnotationsValidator рассматривается в разделе компонента Validator. ValidationSummary Компонент рассматривается в разделе "Сводка проверки" и "Компоненты сообщения проверки".

Starship2.razor:

@page "/starship-2"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship2> Logger

<EditForm Model="Model" OnValidSubmit="Submit" FormName="Starship2">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <label>
        Identifier: 
        <InputText @bind-Value="Model!.Id" />
    </label>
    <button type="submit">Submit</button>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        [Required]
        [StringLength(10, ErrorMessage = "Id is too long.")]
        public string? Id { get; set; }
    }
}
@page "/starship-2"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship2> Logger

<EditForm Model="Model" OnValidSubmit="Submit" FormName="Starship2">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <label>
        Identifier: 
        <InputText @bind-Value="Model!.Id" />
    </label>
    <button type="submit">Submit</button>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() => Logger.LogInformation("Id = {Id}", Model?.Id);

    public class Starship
    {
        [Required]
        [StringLength(10, ErrorMessage = "Id is too long.")]
        public string? Id { get; set; }
    }
}
@page "/starship-2"
@using System.ComponentModel.DataAnnotations
@inject ILogger<Starship2> Logger

<EditForm Model="Model" OnValidSubmit="Submit">
    <DataAnnotationsValidator />
    <ValidationSummary />
    <InputText @bind-Value="Model!.Id" />
    <button type="submit">Submit</button>
</EditForm>

@code {
    public Starship? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit()
    {
        Logger.LogInformation("Id = {Id}", Model?.Id);
    }

    public class Starship
    {
        [Required]
        [StringLength(10, ErrorMessage = "Id is too long.")]
        public string? Id { get; set; }
    }
}

Обработка отправки формы

EditForm предоставляет следующие обратные вызовы для обработки отправки формы:

  • Используйте OnValidSubmit, чтобы обработчик событий запускался при отправке формы с допустимыми полями.
  • Используйте OnInvalidSubmit, чтобы обработчик событий запускался при отправке формы с недопустимыми полями.
  • Используйте OnSubmit, чтобы обработчик событий запускался независимо от состояния проверки полей формы. Форма проверяется путем вызова EditContext.Validate в методе обработчика событий. Если Validate возвращает true, форма является допустимой.

Очистка формы или поля

Сброс формы путем очистки модели обратно в состояние по умолчанию, которое можно выполнить внутри или вне EditFormразметки:

<button @onclick="ClearForm">Clear form</button>

...

private void ClearForm() => Model = new();

Кроме того, используйте явное Razor выражение:

<button @onclick="@(() => Model = new())">Clear form</button>

Сброс поля путем очистки модельного значения до его состояния по умолчанию.

<button @onclick="ResetId">Reset Identifier</button>

...

private void ResetId() => Model!.Id = string.Empty;

Кроме того, используйте явное Razor выражение:

<button @onclick="@(() => Model!.Id = string.Empty)">Reset Identifier</button>

В предыдущих примерах нет необходимости вызывать StateHasChanged, так как StateHasChanged фреймворк автоматически вызывает компонент Blazor после вызова обработчика событий. Если обработчик событий не используется для вызова методов, которые очищают форму или поле, то код разработчика должен вызывать StateHasChanged, чтобы повторно отобразить компонент.

Поддержка защиты от подделки

Службы антифальсификации автоматически добавляются в Blazor приложения при вызове AddRazorComponents в файле Program.

Приложение использует Antiforgery Middleware, вызывая его в конвейере обработки запросов в файле Program. UseAntiforgery вызывается после вызова UseRouting. Если есть вызовы UseRouting и UseEndpoints, то вызов UseAntiforgery должен осуществляться между ними. Вызов UseAntiforgery следует разместить после вызовов UseAuthentication и UseAuthorization.

Компонент AntiforgeryToken отображает маркер антифоргерии в виде скрытого поля, а [RequireAntiforgeryToken] атрибут обеспечивает защиту от антифоргерии. Если проверка защиты от подделки завершается неудачно, создается ответ 400 - Bad Request, и форма не обрабатывается.

Формы, основанные на EditForm, автоматически получают компонент AntiforgeryToken и атрибут [RequireAntiforgeryToken], чтобы обеспечить защиту от подделки.

Для форм на основе HTML-элемента <form> вручную добавьте AntiforgeryToken компонент в форму:

<form method="post" @onsubmit="Submit" @formname="starshipForm">
    <AntiforgeryToken />
    <input id="send" type="submit" value="Send" />
</form>

@if (submitted)
{
    <p>Form submitted!</p>
}

@code{
    private bool submitted = false;

    private void Submit() => submitted = true;
}

Предупреждение

Для форм, основанных либо на EditForm, либо на элементе HTML <form>, защиту от подделки можно отключить, передав required: false атрибуту [RequireAntiforgeryToken]. Следующий пример отключает защиту от подделки и не рекомендуется для публичных приложений.

@using Microsoft.AspNetCore.Antiforgery
@attribute [RequireAntiforgeryToken(required: false)]

Дополнительные сведения см. в разделе ASP.NET Core Blazor аутентификации и авторизации.

Снижение риска атак переполнения данных

Статически отрисованные серверные формы, такие как те, которые обычно используются в компонентах для работы с записями в базе данных через модель формы, могут быть подвержены атаке избыточного присвоения, также называемой атакой массового назначения. Атака переполнения происходит, когда злоумышленник отправляет HTML-форму POST на сервер, который обрабатывает данные для свойств, не принадлежащих к отображаемой форме, и которые разработчик не разрешает изменять пользователям. Термин "overposting" означает, что вредоносный пользователь чрезмерно использовал метод POST при работе с формой.

Перепоступение не является проблемой, если модель не включает ограниченные свойства для операций создания и обновления. Однако, при работе со статическими формами на основе Blazor SSR, которые вы поддерживаете, важно учитывать избыточную отправку данных.

Чтобы избежать избыточной передачи данных, рекомендуется использовать отдельную модель представления или объект передачи данных (DTO) для формы и базы данных при выполнении операций создания (вставки) и обновления. При отправке формы для изменения базы данных используются только свойства модели представления или DTO компонента и кода C#. Все дополнительные данные, включенные вредоносным пользователем, удаляются, поэтому злоумышленник не может вести атаку на переположение.

Улучшенная обработка форм

Улучшите навигацию для POST-запросов с помощью параметра Enhance для форм EditForm или атрибута data-enhance для форм HTML (<form>):

<EditForm ... Enhance ...>
    ...
</EditForm>
<form ... data-enhance ...>
    ...
</form>

Неподдерживаемо: Нельзя задать расширенную навигацию для элемента-родителя формы для обеспечения улучшенной работы с формами.

<div ... data-enhance ...>
    <form ...>
        <!-- NOT enhanced -->
    </form>
</div>

Расширенные записи форм работают только с Blazor конечными точками. Отправка расширенной формы на не-конечнуюBlazor точку приводит к ошибке.

Чтобы отключить расширенную обработку форм, выполните приведенные действия.

  • EditFormУдалите параметр Enhance из элемента формы (или задайте ему значение false: Enhance="false").
  • Для HTML <form>удалите data-enhance атрибут из элемента формы (или задайте для него falseзначение : data-enhance="false").

BlazorУлучшенная навигация и обработка форм могут отменить динамические изменения в DOM, если обновленное содержимое не является частью рендеринга на сервере. Чтобы сохранить содержимое элемента, используйте data-permanent атрибут.

В следующем примере содержимое <div> элемента динамически обновляется скриптом при загрузке страницы:

<div data-permanent>
    ...
</div>

Чтобы отключить расширенную навигацию и обработку форм глобально, см. раздел ASP.NET Core Blazor настройки запуска.

Инструкции по использованию события enhancedload для прослушивания расширенных обновлений страниц см. в разделе ASP.NET Core Blazor навигации.

Примеры

Примеры не применяют расширенную обработку форм для запросов POST формы, но все примеры можно обновить для внедрения расширенных функций, следуя инструкциям в разделе "Улучшенная обработка форм ".

Примеры используют оператор с указанием типа new, который появился с C# 9 и .NET 5. В следующем примере тип для оператора new не указан явно:

public ShipDescription ShipDescription { get; set; } = new();

При использовании C# 8 или более ранней версии (ASP.NET Core 3.1) измените пример кода, чтобы указать тип оператору new:

public ShipDescription ShipDescription { get; set; } = new ShipDescription();

Компоненты используют ссылочные типы, допускающие значение NULL (NRT), а компилятор .NET выполняет статический анализ состояния NULL, оба из которых поддерживаются в .NET 6 или более поздней версии. Для получения дополнительных сведений см. Миграция с ASP.NET Core в .NET 5 на .NET 6.

При использовании C# 9 или более ранней версии (.NET 5 или более ранних версий) удалите NRT из примеров. Как правило, это просто включает удаление вопросительных знаков () и восклицательных точек (?!) из типов в примере кода.

Пакет SDK .NET применяет неявные глобальные директивы using для проектов при выборе .NET 6 или более поздней версии. В примерах используется логгер для записи сведений об обработке форм, но в примерах компонентов не требуется указывать директиву @using для пространства имен Майкрософт.Extensions.Logging. Дополнительные сведения см. в разделе SDK проектов .NET: неявные директивы использования.

При использовании C# 9 или более ранней версии (.NET 5 или более ранних версий) добавьте директивы @using в верхнюю часть компонента после директивы @page для любого API, необходимого в примере. Найдите пространства имен API через Visual Studio (щелкните объект правой кнопкой мыши и выберите Peek Definition) или браузер API .NET.

Чтобы продемонстрировать, как формы работают с проверкой заметок данных , примеры компонентов используют System.ComponentModel.DataAnnotations API. Если вы хотите избежать дополнительной строки кода в компонентах, использующих аннотации данных, сделайте пространство имен доступным во всех компонентах приложения с помощью файла импорта (_Imports.razor):

@using System.ComponentModel.DataAnnotations

Примеры форм ссылались на аспекты вселенной Star Trek . Star Trek является авторским правом ©1966-2023 CBS Studio и Paramount.

Для проверки на стороне клиента требуется канал

Для Blazor Web Appпроверки на стороне клиента требуется активный BlazorSignalR канал. Проверка на стороне клиента недоступна для форм в компонентах, использующих статический рендеринг на стороне сервера. Формы, использующие статический SSR, проверяются на сервере после отправки формы.

Неподдерживаемые функции проверки

Все встроенные валидаторы аннотации данных поддерживаются Blazor за исключением атрибута валидации[Remote].

Проверка jQuery не поддерживается в Razor компонентах. Мы рекомендуем использовать любой из следующих подходов:

  • Следуйте инструкциям в ASP.NET Core Blazor проверки форм для одного из вариантов:
    • Проверка на стороне сервера в Blazor Web App режиме интерактивной отрисовки.
    • Проверка на стороне клиента в автономном приложении Blazor WebAssembly.
  • Используйте собственные атрибуты проверки HTML (см. проверку на стороне клиента).
  • Внедрение сторонней библиотеки JavaScript для проверки.

Для статически отрисованных форм на сервере рассматривается новый механизм проверки на стороне клиента. Дополнительные сведения см. в статье "Создание серверных форм с проверкой на стороне клиента, используя Blazor, без использования канала (dotnet/aspnetcore #51040)".

Дополнительные ресурсы