Should I be passing values through RedirectToActio

2020-04-11 11:47发布

问题:

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 });
}

回答1:

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.



回答2:

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
            );

        }