如何在 ASP.NET CORE Razor Pages 中创建共享表单?

Posted

技术标签:

【中文标题】如何在 ASP.NET CORE Razor Pages 中创建共享表单?【英文标题】:How to create shared form in ASP.NET CORE Razor Pages? 【发布时间】:2019-04-05 20:58:59 【问题描述】:

我必须在我的页眉中创建一个可重复使用的表单。它应该显示在每一页上。将发送 POST 请求的简单输入和提交按钮。

我知道的选项是部分视图或视图组件。 我检查了有关视图组件的文档,但没有提到它适用于表单。只有InvokeAsync 方法可用于初始化视图。

使用局部视图,可能很难定义其页面模型,我不明白将其 POST 处理程序放在哪里。

我看到的另一个选项,以某种方式直接在_Layout.cshtml 上放置一个表单,但同样,它没有它的页面模型(afaik),

那么什么是创建共享表单的方法,以及应该在哪里处理 POST 请求?

【问题讨论】:

【参考方案1】:

您应该使用视图组件,因为这允许您拥有某种程度独立的模型和视图交互。

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" />

【讨论】:

我在局部视图中使用了这种方法,因为我不需要重用该表单,但是使用asp-controller 的方法效果很好,这就是我一直缺少的 您可以从请求标头中获取引用而不是隐藏的表单输入,例如Redirect(Request.Headers["Referer"].ToString())? 没有。 1) 不保证此标头存在。它由客户端添加,可以更改或省略。 2)无论如何,它并不总是你需要的。例如,在第一个帖子上,它可能与returnUrl 相同,但如果用户返回该页面以修复错误,那么引荐来源现在就是该页面,而不是用户最初来自的地方。而returnUrl 将在多个帖子中保持一致。【参考方案2】:

如果您想使用PageModel,您可以在继承自PageModelBasePageModel 类中执行此操作,并且您的所有页面都继承自该类。您可以在 BasePageModel 类中使用命名处理程序 (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
    

【讨论】:

这个答案对我来说效果很好。如果您收到错误“表达式树可能不包含动态操作”,则意味着您忘记将其放在 _Layout.chtml 的顶部:@model BasePageModel。

以上是关于如何在 ASP.NET CORE Razor Pages 中创建共享表单?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.NET Core 的自定义 TagHelper 中呈现 Razor 模板?

如何在 asp.net core razor 页面中拒绝匿名用户?

如何多次提交表单(asp.net core razor)

如何ASP.NET Core Razor中处理Ajax请求

如何在 ASP.NET Core 2.0 Razor 页面中填充下拉列表

如何使用 ASP.NET Core Razor 页面预选下拉列表中的项目