Banner

Using HandleUnknownAction in MVC Widgets

Nov 5, 2017
Sitefinity's MVC widgets are fantastic. They allow untold amounts of customization and enable you to create an MVC framework as complex or as simple as you need. There is a caveat to using them, however: Because the controllers are typical ASP.NET MVC controllers, going to particular pages on your site might make them disappear! There is a simple workaround for this problem, and with this information you can ensure that your Sitefinity MVC widgets consistently display no matter what current state your web site is in.

The Problem

Say you have a simple custom MVC widget that has a single "Index" action. Its job is to always render the same "Default" view, regardless of what else is going on on the currently-viewed Sitefinity page. A common example of a widget like this would be for a custom navigation widget. Regardless of what the user is doing, they should always see the site's navigation. A simple example would look something like this:

using System.Collections.Generic;
using System.Web.Mvc;
using Telerik.Sitefinity.Mvc;
 
namespace SitefinityWebApp.Mvc.Controllers
{
    [ControllerToolboxItem(Name = "SimpleNavWidget", Title = "Simple Nav Widget", SectionName = "MvcWidgets")]
    public class SimpleNavWidgetController : Controller
    {
        public ActionResult Index()
        {
            var navItems = new List<string> {"One", "Two", "Three"};
 
            return View("Default", navItems);
        }
    }
}


I created a bare-bones site and put this widget on a page, along with a stock Sitefinity News widget:
00master
So far, so good. But watch what happens when we click to read a particular news story:
01detailnonav
Our custom widget vanished! And worse: There is no indication that anything went wrong. There are no logged errors or warnings or traces, and the page itself shows no signs that anything has gone awry. Our widget is simply gone.

The Cause

What's happening here is default MVC behavior: Our MVC widget sees the page we're on, and sees that there is additional data in the URL. Most Sitefinity content is accessed using friendly-looking URLs (such as our news story details URL of /news/2016/07/11/example-news-title). The problem is that our widget is reading the rest of this URL, and is misinterpreting what the Action should be for our controller.

The Fix

Luckily, the fix to this problem for these kinds of widgets is simple. All actions that aren't "Index" in our controller are considered unknown, as they have no defined methods to call. So we're going to manipulate how our controller handles unknown actions, telling the controller to always call our Index action regardless of what action is given.

[ControllerToolboxItem(Name = "SimpleNavWidget", Title = "Simple Nav Widget", SectionName = "MvcWidgets")]
public class SimpleNavWidgetController : Controller
{
    public ActionResult Index()
    {
        var navItems = new List<string> {"One", "Two", "Three"};
 
        return View("Default", navItems);
    }
 
    protected override void HandleUnknownAction(string actionName)
    {
        if (!ActionInvoker.InvokeAction(ControllerContext, "Index"))
        {
            base.HandleUnknownAction(actionName);
        }
    }
}


The method in question, "HandleUnknownAction", is actually defined on the base Controller class and can be overridden. In this instance, we are simply instructing our controller to say "always invoke the Index action of our controller. If this invoke fails, handle the unknown action like you normally would." This way, no matter what URL Sitefinity throws at our pages, our custom widget will always render what it's supposed to render. If we step into the debugger we can see exactly what action name our controller is receiving when loading the news details page:
02debug
Since our controller doesn't have an action to handle the given URL, or the "2016" action, the "HandleUnknownAction" method is invoked. But now we're handling this scenario, and are manually invoking the "Index" action. Now when the page loads, it correctly renders our widget alongside the details of the news story:
03navshown
Our widget now functions completely as expected. With the "HandleUnknownAction" utility, you can also define other special cases for your Sitefinity widgets and pages, instead of just always rendering the Index action. This method gives you a lot more control over how your Sitefinity MVC widgets react and render when put into specific scenarios, and you can use this to control them without resorting to hacks or other manual means of achieving your goals.
Load more comments
comment-avatar

Copyright © 2017 Alain "Lino" Tadros