Search code examples
c#asp.net-mvcasp.net-mvc-3redirecttoactiontempdata

Should I be passing values through RedirectToAction or TempData?


I've seen some articles (even MSDN) suggest TempData for passing data between ActionMethods. But I've seen others here say that TempData should be avoided. What's the best practices way to approach this?

Here's some code to show my situation. Note: I'm 100% sure, I'm doing this wrong. Which is why I'm here. :) Also, I've been doing Webforms up until recently.

Note2: This is related, but not the same.

View:

<div>
    @using (Html.BeginForm("Previous", "Home", new {month = @month}, FormMethod.Post)) 
    {
        <input id="previous" type="submit" value="Previous" />
    }

    // This fails but that's another situation
    @using (Html.BeginForm("Next", "Home", new {month = @month, year = @year}, FormMethod.Post))
    {
        <input id="next" type="submit" value="Next" />
    }
</div>

Controller methods:

[HttpPost]
public ActionResult Previous(HTMLMVCCalendar.Models.MonthModel prevMonth)
{
    Calendar monthEventsCal = new Calendar();

    int month = prevMonth.Month;
    int year = prevMonth.Year;

    var newMonth = monthEventsCal.previousMonth(year, month);

    month = newMonth.Item2;
    year = newMonth.Item1;

    return RedirectToAction("Index", "Home", new { month = month });
}

[HttpPost]
public ActionResult Next(HTMLMVCCalendar.Models.MonthModel nextMonth)
{
    Calendar monthEventsCal = new Calendar();

    int month = nextMonth.Month;
    int year = nextMonth.Year;

    var newMonth = monthEventsCal.nextMonth(year, month);

    month = newMonth.Item2;
    year = newMonth.Item1;

    return RedirectToAction("Index", "Home", new { year = year, month = month });
}

Solution

  • It sounds like you are coupling your action methods to your end result too tightly.

    I would refactor a little bit; you would have your Index Method like so:

     public ActionResult Index()
     {
          HTMLMVCCalendar.Models.MonthModel someModel = new HTMLMVCCalendar.Models.MonthModel();
    
          someModel.DateTime = DateTime.Now; // whatever
    
          return View(someModel);
     }
    

    Then, when you need to recalculate your calendar, you simply post to the same URL which returns the same view with new view model data.

     [HttpPost]
     public ActionResult Index(HTMLMVCCalendar.Models.MonthModel previousModel, bool? goForward)
     {
          if(goForward.HasValue && goForward.Value)
                previousModel.DateTime = previousModel.DateTime.AddMonths(1);
          else
                previousModel.DateTime = previousModel.DateTime.AddMonths(-1);
    
          return View(previousModel);
     }
    

    You stay on the same URL and present the same view, but with the changes that you need. You dont need a specific endpoint for each action.