NoviceMe
NoviceMe

Reputation: 3256

How to pass back actionlink values - mvc3

I have following code in HomeController; it gets latest date and shows songs according to that date.

public ActionResult Index()
{           
   var topsong = db.TopSongs;
   var topDate = db.TopDates;
   var latestDate = topDate.OrderByDescending(d => d.Date).FirstOrDefault();
   int dateId = topDate.OrderByDescending(d => d.DateId).FirstOrDefault().DateId;
   var topTitles = topsong.Where(s => s.DateId == latestDate.DateId).ToList();

   ViewBag.Message = "Top Songs";                                    
   ViewBag.latestDate = latestDate.Date.ToShortDateString();            

   return View(topTitles);
}

This goes into database and picks latest date -- let's say 08/25/2012 -- and shows all songs corresponding to this date. This part is working fine; now I want to add a feature where the user can select previous dates or next dates from the database, and display songs according to that.

What I am trying to do is add previous and next date buttons in the View. Like this:

<h2>Songs Updated On: @ViewBag.latestDate</h2>
@Html.ActionLink("Previous Week's Songs", "Index", new { });
@Html.ActionLink("Next Week's Songs", "Index", new { });

As I am new to MVC3, can someone please tell me how can I get previous and next dates to show up? If I calculate them in the View, how can I pass them back to controller to show songs for those dates?

Here is the example dates table: DateId Date 1 08/25/2012 2 08/20/2012 3 09/21/2012

Updated Code:

Here is code for HomeController:

 public ActionResult Index(DateTime? date = null)
        {            
            var topsong = db.TopSongs;
            var topDate = db.TopDates;

            var latestDate = (date.HasValue) ? date.Value : topDate.OrderByDescending(d => d.Date).FirstOrDefault();           


            //var latestDate = topDate.OrderByDescending(d => d.Date).FirstOrDefault();

            int dateId = topDate.OrderByDescending(d => d.DateId).FirstOrDefault().DateId;           
            var topTitles = topsong.Where(s => s.DateId == latestDate.DateId).ToList();

            /////
            ViewBag.NextDate = topDate.Where(d => d.Date > latestDate).OrderBy(d => d.Date).FirstOrDefault();
            ViewBag.PreviousDate = topDate.Where(d => d.Date < latestDate).OrderByDescending(d => d.Date).FirstOrDefault();
            ////////

            ViewBag.Dates = topDate.Select(d => d.Date).Distinct();
            ViewBag.latestDate = latestDate.Date.ToShortDateString();            

            return View(topTitles);
        }

Code for Index.cshtml

@model IEnumerable<App.Models.TopSong>
@{
    ViewBag.Title = "Top Songs";
    var songs = ViewBag.songs;
}            
<h1>@ViewBag.Message</h1>

<h2>Song's Updated On: @ViewBag.latestDate</h2>
@Html.ActionLink("Previous Week's Songs", "Index", new { [email protected] });
@Html.ActionLink("Next Week's Songs", "Index", new { [email protected] });

Basically i just want to be able to go to previous or next date using action links. I tried above code but it is not working.

Upvotes: 1

Views: 2528

Answers (2)

NiK
NiK

Reputation: 1857

One way of doing this is as follows:

First, create an action method

Public ActionResult Songs(string val)
{
   if (val == "Previous")
   {
    // code to get and return previous week songs
   }

   if (val == "Next")
   {
    // code to get and return next week songs
   }

    // By default return either previous/next/current week's songs...
}

Second, modify your action links to match as below

@Html.ActionLink("Previous Week's songs", "Songs", new { val = "Previous"})

@Html.ActionLink("Next Week's Songs", "Songs", new { val = "Next"})

Another Approach:

Another approach is to create an action method for each, that means you can have an action method to just return Previous Week's Songs and another action method to return Next Week's songs. This means you will not need to pass any arguments and your actionlink code will look as simple as below

   @Html.ActionLink("Previous Week's songs", "PreviousWeekSongs")

   @Html.ActionLink("Next Week's Songs", "NextWeekSongs")

UPDATE:

Hey it seems like you do not have any code specific to binding your model data back to the View...so try updating your View code as below

    @model IEnumerable<App.Models.TopSong>
@{
    ViewBag.Title = "Top Songs";
    var songs = ViewBag.songs;
}            
<h1>@ViewBag.Message</h1>
// Code to Display Songs
@foreach(var song in model)
{
  <div> 
   <span>@song.Property1</span>
   <span>@song.Property2</span>
   <span>@song.Property3</span>          
  </div>

}

<h2>Song's Updated On: @ViewBag.latestDate</h2>
@Html.ActionLink("Previous Week's Songs", "Index", new { [email protected] });
@Html.ActionLink("Next Week's Songs", "Index", new { [email protected] });

I hope this may help you...

Upvotes: 1

McGarnagle
McGarnagle

Reputation: 102753

For the first question, the answer is to create a View Model. The idea here is to provide all the data needed by your view. For example:

public class ViewModel
{
    public string CurrentDate { get; set; }
    public DateTime NextDate { get; set; }
    public DateTime PreviousDate { get; set; }
    public List<Song> Songs { get; set; }
}

So, you'll populate this as needed, eg

var topDate = db.TopDates;
var model = new ViewModel();
model.Songs = ...
model.CurrentDate = latestDate.Date.ToShortDateString();
model.NextDate = topDate.Where(d => d.Date > latestDate).OrderBy(d => d.Date).FirstOrDefault(d => d.Date);
model.PreviousDate = topDate.Where(d => d.Date < latestDate).OrderByDescending(d => d.Date).FirstOrDefault(d => d.Date);

Now you can create the links in the Razor view using values from the model:

@Html.ActionLink("Previous Week's Songs", "Index", new { date=Model.PreviousDate });
@Html.ActionLink("Next Week's Songs", "Index", new { date=Model.NextDate });

Finally, to handle the links in the postback, add a parameter to the Action method that matches the route value specified above (date).

public ActionResult Index(int? date = null)
{
    var latestDate = (date.HasValue) ? date.Value : db.TopDates.OrderByDescending(d => d.Date).FirstOrDefault(d => d.Date);
    // same logic
}

Upvotes: 1

Related Questions