您应该使用视图组件,因为这样可以实现相对自包含的模型和视图交互。
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");
在处理验证错误时,情况会变得有点棘手。由于您正在发布到不同的操作,因此无法返回用户之前所在的视图以显示布局中表单内的验证错误或其他内容。相反,您需要为此处理程序操作创建一个特定的视图,该视图将仅是共享表单。您可以使用此处的视图组件作为部分视图:
<partial name="~\Views\Shared\Components\SharedForm\Default.cshtml" />
asp-controller
的方法非常好,这正是我一直缺少的。 - Roma KostelnyyRedirect(Request.Headers["Referer"].ToString())
。 - Steven B.returnUrl
相同,但如果用户返回到页面以修复错误,则引用者现在是该页面,而不是用户最初来自的位置。而returnUrl
将在多个帖子之间保持一致。