noo*_*oox 28 c# asp.net-core-mvc asp.net-core
我需要多个提交按钮来在控制器中执行不同的操作.
我在这里看到了一个优雅的解决方案:如何在ASP.NET MVC Framework中处理多个提交按钮? 使用此解决方案,可以使用自定义属性修饰操作方法.处理路径时,此自定义属性的方法检查属性的属性是否与单击的提交按钮的名称匹配.
但是在MVC Core(RC2 nightly build)中我还没有找到ActionNameSelectorAttribute(我还搜索了Github存储库).我发现了一个类似的解决方案ActionMethodSelectorAttribute(http://www.dotnetcurry.com/aspnet-mvc/724/handle-multiple-submit-buttons-aspnet-mvc-action-methods).
ActionMethodSelectorAttribute可用,但该方法IsValidForRequest具有不同的签名.有一个类型的参数RouteContext.但我找不到那里的帖子数据.所以我没有什么可以与我的自定义属性属性进行比较.
MVC Core中是否有与之前MVC版本类似的优雅解决方案?
Wil*_*Ray 52
您可以使用HTML5 formaction属性,而不是在服务器端路由它.
<form action="" method="post">
<input type="submit" value="Option 1" formaction="DoWorkOne" />
<input type="submit" value="Option 2" formaction="DoWorkTwo"/>
</form>
Run Code Online (Sandbox Code Playgroud)
然后只需要像这样的控制器动作:
[HttpPost]
public IActionResult DoWorkOne(TheModel model) { ... }
[HttpPost]
public IActionResult DoWorkTwo(TheModel model) { ... }
Run Code Online (Sandbox Code Playgroud)
可以在此处找到适用于旧版浏览器的优质填充.
ModelState在发布的操作上发生错误(或其他),则需要将用户发送回正确的视图.(但是,如果您通过AJAX发布,这不是问题.)Sha*_*tin 32
ASP.NET Core 1.1.0具有FormActionTagHelper创建formaction属性的功能.
<form>
<button asp-action="Login" asp-controller="Account">log in</button>
<button asp-action="Register" asp-controller="Account">sign up</button>
</form>
Run Code Online (Sandbox Code Playgroud)
这样呈现:
<button formaction="/Account/Login">log in</button>
<button formaction="/Account/Register">sign up</button>
Run Code Online (Sandbox Code Playgroud)
它也适用于或的input标签.type="image"type="submit"
我之前已经这样做过,并且在过去我会将表单发布到不同的控制器操作。问题是,在服务器端验证错误中,您要么陷入困境:
\n\nreturn View(vm)将后操作名称留在 url\xe2\x80\xa6 中。return Redirect(...)需要使用TempData来保存ModelState. 还恶心。这就是我选择做的事情。
\n\nname按钮的 绑定到 POST 上的变量。value是一个枚举,用于区分提交操作。Enum 是类型安全的,并且在 switch 语句中效果更好。;)return View(viewModel)请按照正确的 PGR 模式重建视图模型和 。使用此技术,无需使用TempData!
在我的用例中,我有一个用户/详细信息页面,其中包含“添加角色”和“删除角色”操作。
\n\n这是按钮。它们可以是按钮而不是输入标签...;)
\n\n<button type="submit" class="btn btn-primary" name="SubmitAction" value="@UserDetailsSubmitAction.RemoveRole">Remove Role</button>\n<button type="submit" class="btn btn-primary" name="SubmitAction" value="@UserDetailsSubmitAction.AddRole">Add Users to Role</button>\nRun Code Online (Sandbox Code Playgroud)\n\n这是控制器操作。我将 switch 代码块重构为它们自己的函数,以使它们更易于阅读。我必须发布到 2 个不同的视图模型,因此不会填充其中一个,但模型绑定器并不关心!
\n\n[HttpPost]\n[ValidateAntiForgeryToken]\npublic async Task<IActionResult> Details(\n SelectedUserRoleViewModel removeRoleViewModel, \n SelectedRoleViewModel addRoleViewModel,\n UserDetailsSubmitAction submitAction)\n{\n switch (submitAction)\n {\n case UserDetailsSubmitAction.AddRole:\n {\n return await AddRole(addRoleViewModel);\n }\n case UserDetailsSubmitAction.RemoveRole:\n {\n return await RemoveRole(removeRoleViewModel);\n }\n default:\n throw new ArgumentOutOfRangeException(nameof(submitAction), submitAction, null);\n }\n}\n\nprivate async Task<IActionResult> RemoveRole(SelectedUserRoleViewModel removeRoleViewModel)\n{\n if (!ModelState.IsValid)\n {\n var viewModel = await _userService.GetDetailsViewModel(removeRoleViewModel.UserId);\n return View(viewModel);\n }\n\n await _userRoleService.Remove(removeRoleViewModel.SelectedUserRoleId);\n\n return Redirect(Request.Headers["Referer"].ToString());\n}\n\nprivate async Task<IActionResult> AddRole(SelectedRoleViewModel addRoleViewModel)\n{\n if (!ModelState.IsValid)\n {\n var viewModel = await _userService.GetDetailsViewModel(addRoleViewModel.UserId);\n return View(viewModel);\n }\n\n await _userRoleService.Add(addRoleViewModel);\n\n return Redirect(Request.Headers["Referer"].ToString());\n}\nRun Code Online (Sandbox Code Playgroud)\n\n作为替代方案,您可以使用 AJAX 发布表单。
\n| 归档时间: |
|
| 查看次数: |
26896 次 |
| 最近记录: |