C# ASP.NET MVC Core/6:多个提交按钮
我需要多个提交按钮来执行控制器中的不同操作 我在这里看到了一个优雅的解决方案: 使用此解决方案,可以使用自定义属性修饰操作方法。处理路由时,此自定义属性的方法将检查属性的属性是否与单击的提交按钮的名称匹配 但是在MVC核心(RC2夜间构建)中,我没有找到C# ASP.NET MVC Core/6:多个提交按钮,c#,asp.net-core,asp.net-core-mvc,C#,Asp.net Core,Asp.net Core Mvc,我需要多个提交按钮来执行控制器中的不同操作 我在这里看到了一个优雅的解决方案: 使用此解决方案,可以使用自定义属性修饰操作方法。处理路由时,此自定义属性的方法将检查属性的属性是否与单击的提交按钮的名称匹配 但是在MVC核心(RC2夜间构建)中,我没有找到ActionNameSelectorAttribute(我还搜索了Github存储库)。我发现了一个类似的解决方案,它使用ActionMethodSelectorAttribute() ActionMethodSelectorAttribute可
ActionNameSelectorAttribute
(我还搜索了Github存储库)。我发现了一个类似的解决方案,它使用ActionMethodSelectorAttribute
()
ActionMethodSelectorAttribute
可用,但方法IsValidForRequest
具有不同的签名。有一个类型为RouteContext
的参数。但是我在那里找不到post数据。因此,我没有任何东西可以与我的自定义属性进行比较
MVC Core中是否有类似于以前MVC版本的优雅解决方案?您可以使用HTML5
属性,而不是将其路由到服务器端
<form action="" method="post">
<input type="submit" value="Option 1" formaction="DoWorkOne" />
<input type="submit" value="Option 2" formaction="DoWorkTwo"/>
</form>
对于较旧的浏览器,一个好的多边形填充可以是
记住。。。
ModelState
或其他错误,则需要将用户发送回正确的视图。(不过,如果您是通过AJAX发布,这不是问题。)ASP.NET Core 1.1.0具有创建
formaction
属性的
<form>
<button asp-action="Login" asp-controller="Account">log in</button>
<button asp-action="Register" asp-controller="Account">sign up</button>
</form>
登录
注册
呈现如下:
<button formaction="/Account/Login">log in</button>
<button formaction="/Account/Register">sign up</button>
登录
注册
它还适用于
input
标记,这些标记是type=“image”
或type=“submit”
我以前做过,过去我会将表单发布到不同的控制器操作中。问题是,在服务器端验证错误中,您可能会遇到以下问题:
返回视图(vm)
在url中保留操作后的名称…糟糕返回重定向(…)
要求使用TempData
保存ModelState
。也很恶心名称
绑定到POST上的变量值
是一个用于区分提交操作的枚举。Enum是类型安全的,在switch语句中工作得更好。;)李>
TempData
在我的用例中,我有一个带有“添加角色”和“删除角色”操作的用户/详细信息页面
这是按钮。它们可以是按钮而不是输入标记…;)
删除角色
将用户添加到角色
这是控制器的动作。我将开关代码块重构为它们自己的函数,使它们更易于阅读。我必须张贴到2个不同的视图模型,所以其中一个将不会被填充,但模型绑定器不关心
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Details(
SelectedUserRoleViewModel removeRoleViewModel,
SelectedRoleViewModel addRoleViewModel,
UserDetailsSubmitAction submitAction)
{
switch (submitAction)
{
case UserDetailsSubmitAction.AddRole:
{
return await AddRole(addRoleViewModel);
}
case UserDetailsSubmitAction.RemoveRole:
{
return await RemoveRole(removeRoleViewModel);
}
default:
throw new ArgumentOutOfRangeException(nameof(submitAction), submitAction, null);
}
}
private async Task<IActionResult> RemoveRole(SelectedUserRoleViewModel removeRoleViewModel)
{
if (!ModelState.IsValid)
{
var viewModel = await _userService.GetDetailsViewModel(removeRoleViewModel.UserId);
return View(viewModel);
}
await _userRoleService.Remove(removeRoleViewModel.SelectedUserRoleId);
return Redirect(Request.Headers["Referer"].ToString());
}
private async Task<IActionResult> AddRole(SelectedRoleViewModel addRoleViewModel)
{
if (!ModelState.IsValid)
{
var viewModel = await _userService.GetDetailsViewModel(addRoleViewModel.UserId);
return View(viewModel);
}
await _userRoleService.Add(addRoleViewModel);
return Redirect(Request.Headers["Referer"].ToString());
}
[HttpPost]
[ValidateAntiForgeryToken]
公共异步任务详细信息(
选择EdUserRoleViewModel RemoveOleViewModel,
已选择的RoleView模型AddRoleView模型,
用户详细信息提交(提交提交)
{
开关(submitAction)
{
案例UserDetailsSubmitAction.AddRole:
{
返回等待添加角色(addRoleViewModel);
}
案例用户详细信息SubmitAction.RemoveOLE:
{
返回等待移除ole(移除oleviewmodel);
}
违约:
抛出新ArgumentOutOfRangeException(nameof(submitAction),submitAction,null);
}
}
专用异步任务删除OLE(SelectedUserRoleViewModel删除oleViewModel)
{
如果(!ModelState.IsValid)
{
var viewModel=await\u userService.GetDetailsViewModel(removoleviewmodel.UserId);
返回视图(viewModel);
}
等待_userRoleService.Remove(RemoveOleViewModel.SelectedUserRoleId);
返回重定向(Request.Headers[“Referer”].ToString());
}
专用异步任务AddRole(SelectedRoleViewModelAddRoleViewModel)
{
如果(!ModelState.IsValid)
{
var viewModel=await_userService.GetDetailsViewModel(addRoleViewModel.UserId);
返回视图(viewModel);
}
wait_userRoleService.Add(addRoleViewModel);
返回重定向(Request.Headers[“Referer”].ToString());
}
作为一种选择,你可以。一个更好的答案是使用并忘记所有的混乱
根据您喜欢与否,可以使用客户端(aka:JQuery)更改元素的实际URL。在单击偶数时,确定单击了哪个按钮,更改了元素的[action]属性并提交()了.Perfect!似乎我必须更详细地研究HTML5。奇怪的是:我有关于索引的动作。所以:
/AreaName/ControllerName
。单击按钮后,我得到:/AreaName/ButtonFormActionName
。控制器部分丢失了。当我从/AreaName/ControllerName/ActionName
开始时,它很有效。啊,好主意!在这种情况下,您将需要使用Url.Action(actionName,controllerName)
helper方法为formaction
属性生成正确的目标。完美的解决方案,但有一个陷阱,如果我们使用您的方式,第一个操作是/post/add,第二个是/post/addcontinue。如果用户单击addcontinue按钮,并且页面已显示va
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Details(
SelectedUserRoleViewModel removeRoleViewModel,
SelectedRoleViewModel addRoleViewModel,
UserDetailsSubmitAction submitAction)
{
switch (submitAction)
{
case UserDetailsSubmitAction.AddRole:
{
return await AddRole(addRoleViewModel);
}
case UserDetailsSubmitAction.RemoveRole:
{
return await RemoveRole(removeRoleViewModel);
}
default:
throw new ArgumentOutOfRangeException(nameof(submitAction), submitAction, null);
}
}
private async Task<IActionResult> RemoveRole(SelectedUserRoleViewModel removeRoleViewModel)
{
if (!ModelState.IsValid)
{
var viewModel = await _userService.GetDetailsViewModel(removeRoleViewModel.UserId);
return View(viewModel);
}
await _userRoleService.Remove(removeRoleViewModel.SelectedUserRoleId);
return Redirect(Request.Headers["Referer"].ToString());
}
private async Task<IActionResult> AddRole(SelectedRoleViewModel addRoleViewModel)
{
if (!ModelState.IsValid)
{
var viewModel = await _userService.GetDetailsViewModel(addRoleViewModel.UserId);
return View(viewModel);
}
await _userRoleService.Add(addRoleViewModel);
return Redirect(Request.Headers["Referer"].ToString());
}