Как создать общую форму в ASP.NET CORE Razor Pages?

Я должен создать форму многократного использования в заголовке моей страницы. Это должно отображаться на каждой странице. Простая кнопка ввода и отправки, которая отправит запрос POST.

Опции, о которых я знаю, являются частичными представлениями или компонентами представления. Я проверил документацию о компонентах представления, но нет никаких упоминаний, что это работает с формами. Только InvokeAsync метод доступен для инициализации представления.

При частичном просмотре может быть сложно определить модель страницы, и я не понимаю, куда поместить обработчик POST.

Я вижу еще один вариант, как разместить форму прямо на _Layout.cshtml, но, опять же, у него нет модели страницы (afaik),

Итак, как создать общую форму и где должен обрабатываться запрос POST?

2 ответа

Решение

Вы должны использовать компонент представления, поскольку это позволяет вам иметь несколько автономную модель и взаимодействие представления.

public class SharedFormViewComponent : ViewComponent
{
    public Task<IViewComponentResult> InvokeAsync() =>
        Task.FromResult(View(new SharedFormViewModel()));
}

Затем поместите HTML-код вашей формы в Views\Shared\Components\SharedForm\Default.cshtml, Для действия вашей формы вам нужно будет указать маршрут. Подробнее об этом в с. Затем, чтобы отобразить вашу форму:

@await Component.InvokeAsync("SharedForm")

Теперь, как вы уже заметили, компоненты представления нельзя публиковать. Это не проблема "не поддерживающих форм"; они буквально не являются частью конвейера запросов и поэтому не могут отвечать на запросы, такие как POST. Вам понадобится отдельное действие, которое будет обрабатывать POST на некотором контроллере. В теге формы вашего компонента, затем:

<form asp-action="SharedFormHandlerAction" asp-controller="Foo" asp-area="" method="post">

asp-area Атрибут должен быть предоставлен на тот случай, если он используется в контексте разных областей.

Вам также понадобится "обратный URL". Это будет URL-адрес текущей страницы, поэтому после того, как пользователь успешно отправит форму, он вернется на страницу, с которой отправил ее. Вы можете добиться этого, добавив скрытый ввод в форму:

<input type="hidden" name="returnUrl" value="@(Context.Request.Query["returnUrl"].FirstOrDefault() ?? (Context.Request.Path + Context.Request.QueryString))" />

Ваше действие обработчика должно принять такой параметр, как string returnUrl = null, и в случае успеха вы должны сделать:

return !string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl)
    ? Redirect(returnUrl)
    : RedirectToAction("SomeDefaultAction");

Что немного сложнее, так это обработка ошибок валидации. Так как вы публикуете другое действие, вы не можете вернуть предыдущее представление, в котором находился пользователь, чтобы показать ошибки проверки в элементе from в макете или что-либо еще. Вместо этого вам понадобится представление, специфичное для этого действия обработчика, которое будет просто вашей общей формой. Вы можете использовать представление для своего компонента представления здесь как частичное:

<partial name="~\Views\Shared\Components\SharedForm\Default.cshtml" />

Если вы хотите использовать PageModel, you could do so in a BasePageModel класс, который наследуется от PageModel and that all your pages inherit from. You can use a named handler ( https://www.learnrazorpages.com/razor-pages/handler-methods) in the BasePageModel class to process the form submission. Add the form directly to the Layout, which will need an @model directive for your BasePageModel type.

public class BasePageModel : PageModel
{
    [BindProperty]
    public string SearchString { get; set; }

    public void  OnPostBaseSearch()
    {
        // process the search
    }
}
Другие вопросы по тегам