I have done this before and in the past I would have posted the form to different controller actions.  The problem is, on a server side validation error you are either stuck with:
- return View(vm)leaves the post action name in the url… yuck.
- return Redirect(...)requires using- TempDatato save the- ModelState.  Also yuck.
Here is what I chose to do.
- Use the nameof the button to bind to a variable on POST.
- The button valueis an enum to distinguish the submit actions. Enum is type safe and works better in a switch statement.  ;)
- POST to the same action name as the GET.  That way you don't get the POST action name in your URL on a server side validation error.
- If there is a validation error, rebuild your view model and return View(viewModel), following the proper PGR pattern.
Using this technique, there is no need to use TempData!
In my use case, I have a User/Details page with an "Add Role" and "Remove Role" action.
Here are the buttons.  They can be button instead of input tags... ;)
<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>
Here is the controller action.  I refactored out the switch code blocks to their own functions to make them easier to read.  I have to post to 2 different view models, so one will not be populated, but the model binder does not care!
[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());
}
As an alternative, you could post the form using AJAX.