Search code examples
asp.net-mvc-4parametersactionmethod

Paramete value is null in one action method and non-null in another


I have controller called Documents with three action methods:

 public ActionResult Save(string returnUrl){
      TempData["returnUrl"]=returnUrl;
      return View(viewName: "Save");
 }


 [HttpPost]
 public ActionResult Save(string returnUrl){     
      return Redirect(returnUrl); 
 }

and

 [HttpPost]
 public ActionResult Cancel(string returnUrl){     
      return Redirect(returnUrl);
 }

And here's the content of the Save.cshtml view:

 @Html.Hidden(TempData["returnUrl"].ToString())
 @using (Html.BeginForm){
    <!--Some html here-->
    <input type="submit" value="Save"/>
 }

 @using (Html.BeginForm(actionName:"Cancel",controllerName:"Documents")){
     <input type="submit" value="Cancel"/>
 }

Of course, the above code does not reflect what I need to do in real world but one problem made me strip my code down to this simplest stage. The problem is that the returnUrl argument is null when I call the Cancel action method. Why is that?


Solution

  • In order to post back to FormCollection, inputs associated with the form need to be located inside the <form> tag (except if using the form attribute). In your case where you have 2 forms and need to post back the value of returnUrl, you would need 2 inputs. This will create elements with duplicate id's if using html helpers. A better approach would be to include the value in the form element, for example

    Controller

    [HttpGet]
    public ActionResult Save(string returnUrl)
    {
      ViewBag.ReturnUrl = returnUrl;
      return View("Save");
    }
    
    [HttpPost]
    public ActionResult Save(string returnUrl, MyModel, model)
    {
      ....
    }
    
    [HttpPost]
    public ActionResult Cancel(string returnUrl, MyModel, model)
    {
      ....
    }
    

    View

    @using (Html.BeginForm("Save", "Documents", new { ReturnUrl = ViewBag.ReturnUrl })) {
      ....
    
    @using (Html.BeginForm("Cancel", "Documents", new { ReturnUrl = ViewBag.ReturnUrl })) {
      ....