Day 21: Cleaning Up Filtering, the Layout & the Menu

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

In software development we often talk about concepts like the Single Responsibility Principle. Web pages are often doing lots of things, so it’s hard to say that it should always apply when we’re building our views. But, in the spirit of Martin Fowler’s take on it, I would argue that our _Layout.cshtml is starting to get a lot of reasons as to why it might change, and for that reason, we’re going to split out the menu.

Extracting the Menu

In your Views\Shared folder add another partial called _MenuPartial.cshtml and paste in the following code.

@using SimpleSite.Models
<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Home", "Index", "Home")</li>
    <li>@Html.ActionLink("About", "About", "Home")</li>
    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
    <li>@Html.ActionLink("My Peeps", "Index", "Simple")</li>

    @if (ViewBag.Notifications != null)
    {
        foreach (NotificationViewModel notification in ViewBag.Notifications)
        {
            <li>
                <a href="#">
                    @notification.NotificationType
                    <span class="badge badge-@notification.BadgeClass">
                        @notification.Count
                    </span>
                </a>
            </li>
        }
    }
</ul>
If you flip back to our _Layout view, you’ll see that this is very close to what we had there. I’ve made two important changes: 1. I’ve added a link to our SimpleController in the menu. 2. I’m checking to make sure there is data in the ViewBag before accessing the dynamic property. This will prevent errors should there be no notifications for the users. If you do #1 without #2 above, you will most definitely get errors because the only place that has notifications injected is in the Index action on the Home controller. With those bits in place, be sure to pop back into your _Layout, and update the navbar where we had previously added the code for notifications. It should now only include a call to render our _MenuPartial and the _LoginPartial.
<div class="navbar-collapse collapse">
    @Html.Partial("_MenuPartial")
    @Html.Partial("_LoginPartial")
</div>

If you run the site at this point you won’t get any errors, but you’ll only see the notifications on the home page. Let’s address that.

Globally Registering an Action Filter

We’re now going to set it up so that our NotificationFilter is executed on every request. I just ask that you remember that this is a demo, and that there are a few caveats you should be aware of.

During application startup (checkout your global.asax in the root of the site) you’ll notice a call to FilterConfig.RegisterGlobalFilters. There is no magic here. There’s a static method on a class located in your App_Start folder that helps to keep that global.asax nice and tidy. A GlobalFilterCollection is passed in and we can then add to it.

In previous versions of the MVC template, this wasn’t around, so most folks ended up either dropping in a ton of lifting into Application_Start or otherwise coming up with a comparable solution to the above. Now, the class that does the FilterConfig does the FilterConfig. Kinda like that whole Single Responsibility Principle again, eh?

Update FilterConfig (which has the global error handling baked in already) to also include the registration of our filter:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new NotificationFilter());
}


Now, return to the Home Controller and remove the NotificationFilter attribute from the Index action.  It won’t really matter if you don’t (the Framework is smart enough to see that it’s already in play) but you might confuse the future version of yourself when you disable the global registration down the road and the filter keeps getting executed.

You’re all set!

Next Steps

One final step that you might want to consider in the clean up is to move your notification model to a separate DLL, but I’ll leave that as an exercise to the reader as it’s more of a “code” thing and less of an “MVC or Bootstrap” thing.

Next up, we’ll tackle user registration and membership.