如何在 ASP.NET CORE Razor Pages 中创建共享表单?
How to create shared form in ASP.NET CORE Razor Pages?
我必须在页眉中创建一个可重复使用的表单。它应该显示在每个页面上。将发送 POST 请求的简单输入和提交按钮。
我知道的选项是部分视图或视图组件。
我检查了有关视图组件的文档,但没有提及它适用于表单。只有 InvokeAsync
方法可用于初始化视图。
使用局部视图,可能很难定义其页面模型,而且我不知道将其 POST 处理程序放在哪里。
我看到的另一个选项,以某种方式直接在 _Layout.cshtml
上放置一个表单,但是,同样,它没有它的页面模型 (afaik),
那么创建共享表单的方法是什么,应该在哪里处理 POST 请求?
如果你想使用 PageModel
,你可以在 BasePageModel
class 中使用它,它继承自 PageModel
并且你的所有页面都继承自。您可以在 BasePageModel
class 中使用命名处理程序 (https://www.learnrazorpages.com/razor-pages/handler-methods#named-handler-methods) 来处理表单提交。将表单直接添加到布局中,这将需要针对您的 BasePageModel 类型的 @model
指令。
public class BasePageModel : PageModel
{
[BindProperty]
public string SearchString { get; set; }
public void OnPostBaseSearch()
{
// process the search
}
}
您应该使用视图组件,因为这允许您拥有某种程度上独立的模型和视图交互。
public class SharedFormViewComponent : ViewComponent
{
public Task<IViewComponentResult> InvokeAsync() =>
Task.FromResult(View(new SharedFormViewModel()));
}
然后,将您的表单 HTML 代码放入 Views\Shared\Components\SharedForm\Default.cshtml
。对于表单的操作,您需要指定一条路线。稍后会详细介绍。然后,显示您的表单:
@await Component.InvokeAsync("SharedForm")
现在,正如您已经看出的那样,无法发布视图组件。这不是 "not supporting forms" 的问题;它们实际上不是请求管道的一部分,因此无法响应 POST 之类的请求。您需要一个独特的操作来处理某些控制器上的 POST。在您的组件的表单标签上,然后:
<form asp-action="SharedFormHandlerAction" asp-controller="Foo" asp-area="" method="post">
应提供 asp-area
属性,以防在不同区域的上下文中使用。
您还需要 "return 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");
事情变得有点棘手的地方在于处理验证错误。由于您要发布到不同的操作,因此您不能 return 用户之前查看的视图在布局或其他内容中的 from 中显示验证错误。相反,您需要一个特定于此处理程序操作的视图,它只是您的共享表单。您可以在此处将视图组件用作部分视图:
<partial name="~\Views\Shared\Components\SharedForm\Default.cshtml" />
我必须在页眉中创建一个可重复使用的表单。它应该显示在每个页面上。将发送 POST 请求的简单输入和提交按钮。
我知道的选项是部分视图或视图组件。
我检查了有关视图组件的文档,但没有提及它适用于表单。只有 InvokeAsync
方法可用于初始化视图。
使用局部视图,可能很难定义其页面模型,而且我不知道将其 POST 处理程序放在哪里。
我看到的另一个选项,以某种方式直接在 _Layout.cshtml
上放置一个表单,但是,同样,它没有它的页面模型 (afaik),
那么创建共享表单的方法是什么,应该在哪里处理 POST 请求?
如果你想使用 PageModel
,你可以在 BasePageModel
class 中使用它,它继承自 PageModel
并且你的所有页面都继承自。您可以在 BasePageModel
class 中使用命名处理程序 (https://www.learnrazorpages.com/razor-pages/handler-methods#named-handler-methods) 来处理表单提交。将表单直接添加到布局中,这将需要针对您的 BasePageModel 类型的 @model
指令。
public class BasePageModel : PageModel
{
[BindProperty]
public string SearchString { get; set; }
public void OnPostBaseSearch()
{
// process the search
}
}
您应该使用视图组件,因为这允许您拥有某种程度上独立的模型和视图交互。
public class SharedFormViewComponent : ViewComponent
{
public Task<IViewComponentResult> InvokeAsync() =>
Task.FromResult(View(new SharedFormViewModel()));
}
然后,将您的表单 HTML 代码放入 Views\Shared\Components\SharedForm\Default.cshtml
。对于表单的操作,您需要指定一条路线。稍后会详细介绍。然后,显示您的表单:
@await Component.InvokeAsync("SharedForm")
现在,正如您已经看出的那样,无法发布视图组件。这不是 "not supporting forms" 的问题;它们实际上不是请求管道的一部分,因此无法响应 POST 之类的请求。您需要一个独特的操作来处理某些控制器上的 POST。在您的组件的表单标签上,然后:
<form asp-action="SharedFormHandlerAction" asp-controller="Foo" asp-area="" method="post">
应提供 asp-area
属性,以防在不同区域的上下文中使用。
您还需要 "return 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");
事情变得有点棘手的地方在于处理验证错误。由于您要发布到不同的操作,因此您不能 return 用户之前查看的视图在布局或其他内容中的 from 中显示验证错误。相反,您需要一个特定于此处理程序操作的视图,它只是您的共享表单。您可以在此处将视图组件用作部分视图:
<partial name="~\Views\Shared\Components\SharedForm\Default.cshtml" />