3

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 });
}
Community
  • 1
  • 1
dotnetN00b
  • 5,021
  • 13
  • 62
  • 95
  • Define the kind of data you need to share (and how), and we can suggest a better alternative than `TempData`, which is unreliable as a good data transport mechanism. – Tejs Apr 17 '12 at 15:03
  • The Index loads a calendar with its events. The Previous and Next buttons needs to send the month and year (ex: 4 and 2012) to the Previous and Next actionmethods. They in turn calculate the needed month and year and pass that to the Index actionmethod. – dotnetN00b Apr 17 '12 at 15:40
  • 1
    Please look at this, it might help you, http://stackoverflow.com/questions/7993263/viewbag-viewdata-and-tempdata – Hari Gillala Apr 17 '12 at 15:47

2 Answers2

2

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.

Tejs
  • 40,736
  • 10
  • 68
  • 86
0

I came up with this. Is this bad, good, should be improved upon?

RAZOR/HTML:

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

Controller/Action Methods:

public ActionResult Index(int? year = 2012 , int? month = 2)
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            Calendar monthEventsCal = new Calendar();

            HTMLMVCCalendar.Models.MonthModel allMonthEvents = monthEventsCal.monthEvents(year.Value, month.Value);
            return View("Index", allMonthEvents);
        }

        [HttpPost]
        public ActionResult Previous(int? year = 2012, int? month = 2)
        {
            Calendar monthEventsCal = new Calendar();

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

            int currMonth = newMonth.Item2;
            int currYear = newMonth.Item1;

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

        [HttpPost]
        public ActionResult Next(int? year = 2012, int? month = 2)
        {
            Calendar monthEventsCal = new Calendar();

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

            int currMonth = newMonth.Item2;
            int currYear = newMonth.Item1;

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

Global.asax.cs:

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{month}/{year}", // URL with parameters
                new { controller = "Home", action = "Index", month = UrlParameter.Optional, year = UrlParameter.Optional } // Parameter defaults
                //"{controller}/{action}/{id}", // URL with parameters
                //new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }
dotnetN00b
  • 5,021
  • 13
  • 62
  • 95