Shawn Eary
Shawn Eary

Reputation: 750

How To Render Correct View when Calling Post Action of Another Controller

A Login Action on my AccountController uses the technique mentioned by Ε Г И І И О in Redirect to Post Method/Action to post a "Login Successful" message to a Success Action of my StatusController:

/// <returns>
/// If login is successful, returns a view stating such.  If the
/// login is not successful, the main Login view will be 
/// redisplayed 
/// </returns>
[HttpPost]
public ActionResult Login(logIn loginAttempt)
{
    logIn theLoginModel = new logIn();

    string username = loginAttempt.Username; 
    string password = loginAttempt.Password; 
    if (Membership.ValidateUser(username, password)) {     
       ...

       /* The login was successful.  Redirect to the LoginSucess
        * Action success */
       status theStatus = new status();
       theStatus.Message = Constants.StatusMsgs.LoginSuccess;
       StatusController SC = new StatusController();
       return SC.Success(theStatus);            
    } else {
       ...
       return View(theLoginModel);
    }                  
}          

I can use the VS2010 debugger to verify that my Success Action gets the correct message in code fragment:

namespace usedCarLotWebApp.Controllers
{
   public class StatusController : Controller
   {
      /// <summary>
      /// Outputs a Success status message to the user
      /// </summary>
      /// <returns>
      /// A trivial view to display a Success status message to the 
      /// user
      /// </returns>
      [HttpPost]
      public ActionResult Success(status theMessage)
      {
         return View(viewName: "Success", model: theMessage);
      }
   }
}

but when the Success Action of my Status Controller tries to render the view, it attempts to render a view from my AccountController Directory instead of my StatusController Directory as I would expect.

Is there some way I can modify the Success Action of my StatusController so that it always tries to find a Success View in my StatusController Directory?

Upvotes: 1

Views: 1222

Answers (2)

Ufuk Hacıoğulları
Ufuk Hacıoğulları

Reputation: 38508

You should return a redirection as a response instead of trying to call the method on a controller instance.

return RedirectToAction("Success", "Status")

or

return RedirectToAction("Success", "Status", new { theMessage = Constants.StatusMsgs.LoginSuccess})

Also you can send the parameter in Success action.

//[HttpPost] You don't need this
public ActionResult Success()
{
   return View("Success",Constants.StatusMsgs.LoginSuccess);
}

Upvotes: 2

LukLed
LukLed

Reputation: 31882

TempData is the way to go. TempData is a collection, that stores values until next request. When you redirect, you go directly to next request, where you retrieve values from TempData. I do it all the time to pass status messages.

I would do it like that:

[HttpPost]
public ActionResult Login(logIn loginAttempt)
{
    logIn theLoginModel = new logIn();

    string username = loginAttempt.Username; 
    string password = loginAttempt.Password; 
    if (Membership.ValidateUser(username, password)) {     
       TempData["Message"] = theMessage;
       return RedirectToAction("Success", "Status");      
    } else {
       ...
       return View(theLoginModel);
    }                  
}

Status controller (please notice status theMessage disappears from action header, because it is passed in TempData). Success also becomes GET message:

namespace usedCarLotWebApp.Controllers
{
   public class StatusController : Controller
   {
      [HttpGet]
      public ActionResult Success()
      {
         var theMessage = (theMessageType) TempData["Message"];
         return View(viewName: "Success", model: theMessage);
      }
   }
}

Upvotes: 2

Related Questions