コントローラーで異なるアクションを実行するには、複数の送信ボタンが必要です。
私はここでエレガントなソリューションを見ました: ASP.NET MVCフレームワークで複数の送信ボタンをどのように処理しますか? このソリューションでは、アクションメソッドをカスタム属性で装飾できます。ルートが処理されると、このカスタム属性のメソッドは、属性のプロパティがクリックされた送信ボタンの名前と一致するかどうかをチェックします。
しかし、MVCコア(RC2ナイトリービルド)では、ActionNameSelectorAttribute
が見つかりません(Githubリポジトリも検索しました)。 ActionMethodSelectorAttribute
を使用する同様のソリューションを見つけました( http://www.dotnetcurry.com/aspnet-mvc/724/handle-multiple-submit-buttons-aspnet-mvc-action-methods )。
ActionMethodSelectorAttribute
は使用できますが、メソッドIsValidForRequest
の署名は異なります。タイプRouteContext
のパラメーターがあります。しかし、投稿データが見つかりませんでした。したがって、カスタム属性プロパティと比較するものは何もありません。
以前のMVCバージョンのソリューションと同様に、MVCコアで利用できる同様のエレガントなソリューションはありますか?
私はこれを以前に行いましたが、以前は、フォームをさまざまなコントローラーアクションに投稿していました。問題は、サーバー側の検証エラーで次のいずれかで行き詰まっていることです。
return View(vm)
は、投稿アクション名をURLに残します…残念です。return Redirect(...)
は、TempData
を保存するためにModelState
を使用する必要があります。また残念。これが私が選択したことです。
name
を使用して、POSTで変数にバインドします。value
は、送信アクションを区別するための列挙型です。 Enumはタイプセーフであり、switchステートメントでより適切に機能します。 ;)return View(viewModel)
を再構築します。この手法を使用すると、TempData
!を使用する必要はありません。
私の使用例では、「ロールの追加」および「ロールの削除」アクションを含む「ユーザー/詳細」ページがあります。
ここにボタンがあります。入力タグの代わりにボタンにすることもできます...;)
<button type="submit" class="btn btn-primary" name="SubmitAction" value="@UserDetailsSubmitAction.RemoveRole">Remove Role</button>
<button type="submit" class="btn btn-primary" name="SubmitAction" value="@UserDetailsSubmitAction.AddRole">Add Users to Role</button>
これがコントローラーのアクションです。読みやすくするために、switchコードブロックを独自の関数にリファクタリングしました。 2つの異なるビューモデルに投稿する必要があるため、1つは入力されませんが、モデルバインダーは気にしません!
[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());
}
別の方法として、 AJAXを使用してフォームを投稿 することもできます。