Frage

So far:

  • I have a page with multiple submits on it, where each submit depends on the previous one.

  • The same page is rendered each time a submit is clicked.

  • I found myself writing spaghetti code in the controller method (branching based on the ViewModel), and wanted to factor out the behaviour for each submit into a separate method.

  • I implemented the solution found here - specifically the solution posted by mkozicki based on the article by Maartin Balliauw.

  • This worked well for forking to different controller methods. But I encountered two problems:

    1. Returning to the same view each time.
    2. Hard-wiring the action method names in the View.cshtml

Here's the code:

Controller:

public class PlayerStatController : Controller
{

    public class PlayerStatViewModel . . . //quite complex ViewModel


    // HTTP GET
    public ActionResult SelectPlayer() 
    {
        List<string> idx_list = getSeasonIndex();
        return View(new PlayerStatViewModel(idx_list));
    }


    // One of three forked action methods
    [HttpPost]
    [MultipleButton(Name = "action", Argument = "ChosenSeason")]
    public ActionResult ChosenSeason(PlayerStatViewModel viewModel) 
    {

        List<string> team_idx = getTeamNameIndex(viewModel.selected_seasonIndex);


        return View("SelectPlayer",new PlayerStatViewModel(new List<string>(), team_idx, new List<string>(), 0));

    }

Here an excerpt from the view (SelectPlayer.cshtml)

<form action="/PlayerStat/ChosenSeason" method="post">
  <fieldset>
    <legend>Select Season</legend>
    <div class="editor-field">
      @Html.LabelFor(m => m.selected_seasonIndex)
      @Html.DropDownListFor(m => m.selected_seasonIndex, Model.seasonIndex_select_list)
      @Html.ValidationMessageFor(m => m.selected_seasonIndex)
    </div>
    <p>
      <input type="submit" value="Choose Season" name="action:ChosenSeason" />
    </p>
  </fieldset>
</form>

Hence:

  1. Is returning from the forked action method with return View("SelectPlayer",new PlayerStatViewModel(...); the best solution to forcing the same view (SelectPlayer.cshtml) to be rendered every time?
  2. Is there a way to avoid hard-coding the action method name in the View (i.e., <form action="/PlayerStat/ChosenSeason" method="post">) I would like to keep using @using (Html.BeginForm()) if possible.
War es hilfreich?

Lösung

  1. Specifying the view name in the return statement is the best and most practical way to return a view that is named something different than the current action method being executed. I believe this is by design in order to decouple action methods from a single view.

  2. Again, for the view if you want the form to post to an action other than the one specified in the current URL you have to specify it explicitly. Using an empty BeginForm() will cause the form to post to the same URL that was returned on the previous request.

I believe what you have is the best way to tackle the problem and is the way I have my MVC application implemented as well. There is nothing wrong with being explicit, especially when it comes to views and view logic because they are by their very nature explicit. Separating the different submit buttons into different action methods is a solid approach and one that will inherently require you to specify which action to target for each submit button. You can think of this approach as analogous to Web Forms Server Side Event Handlers for button clicks (minus all the nasty page life cycle). This approach is elegant and clean, only the server side code corresponding to the submit is executed.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top