Как создать общую форму в 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
}
}