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

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.

Written by Jonathan "JD" Danylko • Last Updated: • MVC •
Conference Sessions

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.

New Menu with Session Filter

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").

  • If we have an Id, determine the number and use that to pull the date from an array of calculated dates.
  • If we don't have an Id, we just display all of the sessions in the list.

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:

ASP.NET 8 Best Practices on Amazon

ASP.NET 8 Best Practices by Jonathan Danylko


Reviewed as a "comprehensive guide" and a "roadmap to excellence" with over 120 Best Practices for ASP.NET Core 8, Jonathan's first book by Packt Publishing explores proven techniques for every phase of the SDLC.

Learn industry-standard concepts to improve your coding, debugging, and deployment of ASP.NET Core websites.

Order now on Amazon.com button

Picture of Jonathan "JD" Danylko

Jonathan "JD" Danylko is an author, web architect, and entrepreneur who's been programming for over 30 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an Architect.

When asked what he likes to do in his spare time, he replies, "I like to write and I like to code. I also like to write about code."

comments powered by Disqus