ASP.NET MVC Optimization Series: Part 5 - Filtering Sessions By Day

July 22nd, 2015

While we've built up a pretty nice web application that simulates a native app, we still need to fix the user interface. Today, we cover some enhancements to our sessions list to make it more user-friendly.

Our web application is coming along quite nicely. We've built up a simple Web Service repository, cached the data as much as possible, create simple ListView screens, and displayed detailed information about speakers and sessions that were presented at Codemash.

Today, we focus on making the web app a little more usable with some enhancements.

Such enhancements will include filtering out the days of the week so users can find sessions on particular days.

First, let's look at making the filtering a little easier to contend with on the main menu.

"But I just want one day!"

I can hear the users now. "I don't want to see every single session in one list. I want it broken out by day."

Ok, then we seem to have a problem.

We need a way to display a list of sessions for each day. In this particular situation, we really don't need JavaScript. We can do all of this with ASP.NET MVC.

No JavaScript will be harmed in the making of this application. ;-)

First, we need our View to include a couple of days. So in our _Layout.cshtml, we'll add 4 new menu items.

<nav id="codemashMenu" class="navmenu navmenu-default navmenu-fixed-left offcanvas" role="navigation">
    <span class="navmenu-brand">Menu</span>
    <ul class="nav navmenu-nav">
        <li><a href="@Url.AllSessionsUrl()"><i class="fa fa-2x fa-users fa-fw"></i> All Sessions</a></li>
        <li><a href="@Url.AllSpeakersUrl()"><i class="fa fa-2x fa-bullhorn fa-fw"></i> All Speakers</a></li>
        <li><a href="@Url.SessionsByDayUrl("Day1")"><i class="fa fa-2x fa-calendar fa-fw"></i> Pre-Compiler (Tuesday)</a></li>
        <li><a href="@Url.SessionsByDayUrl("Day2")"><i class="fa fa-2x fa-calendar fa-fw"></i> Pre-Compiler (Wednesday)</a></li>
        <li><a href="@Url.SessionsByDayUrl("Day3")"><i class="fa fa-2x fa-calendar fa-fw"></i> Conference (Thursday)</a></li>
        <li><a href="@Url.SessionsByDayUrl("Day4")"><i class="fa fa-2x fa-calendar fa-fw"></i> Conference (Friday)</a></li>
    </ul>
</nav>

Now our menu looks a little friendlier.

Since we have a new UrlHelper, we'll add the new Url to our UrlHelpers.cs file.

public static string SessionsByDayUrl(this UrlHelper helper, string id)
{
    return helper.RouteUrl("Default",
        new { @controller = "Codemash", @action = "Sessions", id });
}

This may look a little funky. You may be asking, "Why are we passing in a string of DayX?"

First off, it makes our url look more readable. A sample Url will look like this: /Sessions/Day3.

We also need to know what days the user is interested in when selecting their sessions. Since we know the dates of the conference, we can use the number in the Url to determine the particular date requested.

I stored the dates in the web.config under <appsettings>.

    <add key="Dates" value="1/6/2015-1/9/2015" />

Next, for our CodemashSessionViewModelBuilder, we modify the builder to populate the data by the id passed into the builder ("Day1").

Once we extract the dates from the web.config, we use that number to calculate the date.

ViewModelBuilder/CodemashSessionViewModelBuilder.cs

public CodemashSessionViewModel Build(CodemashController controller, 
    CodemashSessionViewModel viewModel, string day)
{
    viewModel.MetaKeywords = "Codemash v2.0.1.5 Sessions";
 
    var codemashUnitOfWork = new CodemashUnitOfWork();
    var records = codemashUnitOfWork.SessionRepository.GetAll();
 
    if (String.IsNullOrEmpty(day))
    {
        viewModel.SessionItems = records
            .Where(e => e.SessionType != "CodeMash Schedule Item");
        viewModel.ScheduleItems = records
            .Where(e => e.SessionType == "CodeMash Schedule Item");
        
        viewModel.Title = "Sessions";
    }
    else
    {
        // day variable should read "Day1" or "Day2", etc.
        var removeDay = day.ToLower().Replace("day"String.Empty);
        var dayNumber = Int32.Parse(removeDay);
 
        var dates = CodemashConfiguration.ConferenceDates.Split('-');
        DateTime startDate;
        DateTime stopDate;
        if (!DateTime.TryParse(dates[0], out startDate))
        {
            throw new Exception("StartDate is not valid.");
        }
        if (!DateTime.TryParse(dates[1], out stopDate))
        {
            throw new Exception("StopDate is not valid.");
        }
        var dateList = GetAllDates(startDate, stopDate);
        var date = dateList.ToList()[dayNumber - 1];
 
        viewModel.Title = String.Format("Sessions on Day {0} - {1}", 
            dayNumber, date.ToShortDateString());
 
        viewModel.SessionItems = records
            .Where(e =>
                e.SessionType != "CodeMash Schedule Item" &&
                e.SessionStartTime.Date.ToShortDateString() == date.ToShortDateString());
        viewModel.ScheduleItems = records
            .Where(e =>
                e.SessionType == "CodeMash Schedule Item" &&
                e.SessionStartTime.Date.ToShortDateString() == date.ToShortDateString());
 
        viewModel.Sessions = codemashUnitOfWork.SessionRepository
            .GetAll()
            .Where(e => e.SessionStartTime.Date.ToShortDateString() == date.ToShortDateString());
    }
 
    return viewModel;
}
 
public IEnumerable<DateTime> GetAllDates(DateTime start, DateTime end)
{
    var list = new List<DateTime>();
    var currLoopDate = start;
    while (currLoopDate <= end)
    {
        list.Add(currLoopDate);
        currLoopDate = currLoopDate.AddDays(1);
    }
    return list;
}

Here's the great news.

That's it! That's all we need to do to filter out the Sessions and display them in a list based on a specific day.

Conclusion

With everything we've done so far in this series, we're still not done yet. Like I said, I always like a challenge.

In the next post, we'll enhance the web application even more by showing how to select specific sessions to create an agenda.

Did you enjoy the post? Post your comments below.

ASP.NET MVC Optimization Series: