ASP.NET 部分视图/视图组件中的核心 MVC 提交表单



我有一个菜单和一个内容区域,它根据菜单中的选定项目显示内容。由于允许用户更改主菜单的结构,我决定所有内容都将在页面/home/index上,并将为需要显示的内容分配一个guid。我最初的想法是引入部分视图,但意识到 ASP.NET Core不再有RenderAction,并被ViewComponents取代。 所以我使用了ViewComponents,一切正常,除了我偶然发现了需要将组件作为提交表单的情况。

在示例中:一个菜单项是显示用户列表的组件。另一个菜单项是创建新用户的组件。在创建用户组件时,我将有一个需要填写的表单,并且在成功提交后,我想将用户重定向到显示用户列表的组件。在提交失败、错误、输入错误的情况下,我当然不希望将用户重定向到用户列表。

由于 ViewComponents 的工作是显示视图,我应该如何处理这个问题?我正在寻找正确方向的指针。 我在这个领域几乎没有经验,所以任何帮助将不胜感激。

更新

Index.cshtml中:

<tbody>
@foreach (string item in Model.Components)
{
<tr>
<td>
<div class="col-md-3">
@await Component.InvokeAsync(@item)
</div>
</td>
</tr>
}
</tbody>

这是在内容区域内。组件是我想在内容区域中显示的组件的字符串名称(当前一个接一个地列出(。

当我单击菜单项以显示表单时,将调用我的视图组件:

public class TestFormViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync()
{
return View("_TestForm", new TestModelPost());
}
}

我的_TestForm.cshtml组件:

@model TestModelPost
<form asp-controller="Home" asp-action="TestPost" method="post">
<label asp-for="Name"></label>
<input asp-for="Name" /><br />
<label asp-for="Surname"></label>
<input asp-for="Surname" /><br />
<button type="submit">Go</button>
</form>

而《测试邮报》的行动称之为:

[HttpPost]
public IActionResult TestPost(TestModelPost model)
{
// Save model data, etc
// !ModelState.IsValid -> go back to form
// Success -> go to specific id
return RedirectToAction("Index", new { id = 1 });
}

我应该如何处理这个问题?或者更确切地说,我什至走在正确的轨道上吗?我不确定如何"返回"我在_TestForm组件中创建的视图,以防输入不正确。

查看组件,就像 MVC 中它们之前的子操作 ASP.NET 不支持 POST。您需要一个完整的操作来处理表单帖子,这将需要返回完整视图。从本质上讲,您只需要更抽象地考虑它。

视图组件最终只是将一些 HTML 转储到最终响应中的一种手段。当完整响应返回到客户端时,没有视图组件、部分视图等概念。它只是一个 HTML 文档。该 HTML 文档的一部分是您的表单。该窗体将具有一个操作,该操作最终应是由控制器操作之一处理的路由。传统的表单帖子会导致整个浏览器视图发生更改,因此此操作的响应应该是完整视图或重定向到返回完整视图的操作。重定向是遵循 PRG 模式的更合适的路径。然后,最终返回该视图的责任来确定如何构造内容,根据需要使用视图组件、部件等。

长话短,这真的与您的视图组件完全无关。它所做的只是将表单代码放在页面上。

对于作为布局一部分的此类表单,通常最好在表单中包含包含"返回 URL"的隐藏输入。处理表单的操作可以在执行需要执行的操作后重定向回此 URL,以便看起来用户已停留在同一位置。

请参考以下链接:

https://andrewlock.net/an-introduction-to-viewcomponents-a-login-status-view-component/

可能会有所帮助

public class LoginStatusViewComponent : ViewComponent
{
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly UserManager<ApplicationUser> _userManager;
public LoginStatusViewComponent(SignInManager<ApplicationUser> signInManager, UserManager<ApplicationUser> userManager)
{
_signInManager = signInManager;
_userManager = userManager;
}
public async Task<IViewComponentResult> InvokeAsync()
{
if (_signInManager.IsSignedIn(HttpContext.User))
{
var user = await _userManager.GetUserAsync(HttpContext.User);
return View("LoggedIn", user);
}
else
{
return View();
}
}
}

我们的 InvokeAsync 方法非常不言自明。我们正在检查当前用户是否使用 SignInManager<> 登录,如果他们是,我们将从 UserManager<> 获取关联的 ApplicationUser。最后,我们调用帮助程序 View 方法,传入要呈现的模板和模型用户。如果用户未登录,我们将调用不带模板参数的帮助程序 View。

根据您的代码段,您可以尝试按如下方式修改它:

public class TestFormViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync()
{
if (_signInManager.IsSignedIn(HttpContext.User))
{
//user list display
return View("_TestForm", new TestModelPost());
}
else
{
return View();
}
}
}

相关内容

最新更新