David Ruttka

I make computers do things

Forcing MVC3 Into an Area

I had a bit of an issue today with an area in my MVC3 application. I added it with the standard tooling, but when I tried to navigate to it, I got some 404s and some 500s that the View couldn’t be found. It was looking for the View in the main application’s Views, not in my Area!

Well, there isn’t anything new under the sun and I found an answer on StackOverflow. I wasn’t quite satisfied with throwing that snippet in all of my actions, so I thought, “Why not an ActionFilter!?”

And so a new Github repository of ASP.NET MVC3 goodies was born! I am sure I’ll throw a lot more goodies in here, but for now, I give you AreaAttribute.cs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/// <summary>
/// Signals that a Controller or Action belongs in the given Area when the MVC Framework
/// might miss it despite area registration
/// </summary>
/// <remarks>Based on http://stackoverflow.com/questions/5128009/mvc-3-area-route-not-working</remarks>
/// <example>
/// <![CDATA[
///     [Area("MyArea")]
///     public class MyAreaController : Controller
///     {
///         // ...
///     }
/// ]]>
/// </example>
public class AreaAttribute : ActionFilterAttribute
{
  private readonly string _areaName;
  private const string DataTokenKey = "area";

  /// <summary>
  /// Constructs a new AreaAttribute with the given areaName
  /// </summary>
  /// <param name="areaName">The target area</param>
  public AreaAttribute(string areaName)
  {
      _areaName = areaName;
  }

  /// <summary>
  /// Forces us into the target area if MVC Framework hasn't already figured it out
  /// </summary>
  /// <param name="filterContext">The executing context</param>
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
      base.OnActionExecuting(filterContext);

      var controllerContext = filterContext.Controller.ControllerContext;
      if (!controllerContext.RouteData.DataTokens.ContainsKey(DataTokenKey))
      {
          controllerContext.RouteData.DataTokens.Add(DataTokenKey, _areaName);
      }
  }
}

This post originally appeared on The DevStop.