3

I have a single View, which has tabs with various different sections. Each tab I have implemented as a partial view.

There is one ViewModel which has various sub classes to populate the view and partial views within the tabs.

FormCaptureViewModel
  - FormDetailViewModel
  - FormBrandingViewModel
  - etc


[HttpGet]
public IActionResult FormCapture()
{
    return View(new FormCaptureViewModel());
}

<div class="tab-pane" id="tab2">
    @Html.Partial("_FormBrandingPartial", Model.FormBranding)
</div>
<div class="tab-pane" id="tab3">
    @Html.Partial("_FormDesignerPartial", Model.FormDesigner)
</div>
<div class="tab-pane" id="tab4">
    @Html.Partial("_FormAnalyticsPartial", Model.FormAnalytics)
</div>

Then I want each form to do a post back to FormCapture like so:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult FormCapture(FormBrandingViewModel brandingModel)
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult FormCapture(FormDetailViewModel detailModel, SaveAction action)
{
    return View();
}

Each partial view will have a form tag that looks like this:

<form role="form" method="post" asp-action="FormCapture" enctype="multipart/form-data">

However I get an AmbiguousActionException: Multiple actions matched. This makes sense because asp will not know which method to use. How do I go about fixing this?

I am trying to keep away from using ajax because using scripts in partial views is not great.

Any ideas how to implement something like this? Surely this is a normal use case for complicated views (with tabs, etc.)?

I cannot just submit the entire FormCaptureViewModel on each partial view as other tabs may have issues or be non-existent depending on the view's state.

My aim:

  • Utilize ModelState validations specific to the sub viewmodel.
  • The URL must not change on post back.
Dylan
  • 1,919
  • 3
  • 27
  • 51
  • You could maybe use the Post/Redirect/Get pattern. If you are unfamiliar the post action processes the form (saving data or whatever else) and then redirects back to `FormCapture` via a redirect/get request. This would mean that your other actions could have different names since you would never really see them. Depending on what you are actually doing with the post actions though this may not be possible but its a nice pattern to be familiar with. – Chris Mar 07 '17 at 09:12
  • Hi Chris. The problem with this is that you lose any ModelState validations when you RedirectToAction. – Dylan Mar 07 '17 at 09:13
  • Also if ModelState is not valid and you return the View(model), the partial view causes complications with the URL. – Dylan Mar 07 '17 at 09:16
  • Yeah, as I said, not always possible which is partly why I just commented. – Chris Mar 07 '17 at 09:16
  • 1
    One option would be to pass a `HtmlFieldPrefix` to the partials (refer [this answer](http://stackoverflow.com/questions/29808573/getting-the-values-from-a-nested-complex-object-that-is-passed-to-a-partial-view/29809907#29809907)) and then have one single method - `public IActionResult FormCapture(FormCaptureViewModel model)` - only the property related to the form would bound and the others `null` so its easy enough to test which form was submitted –  Mar 07 '17 at 09:21

0 Answers0