7

I wanted to provide some URL separation for my public/anonymous controllers and views from the admin/authenticated controllers and views. So I ended up using entirely Attribute Routing in order to take more control of my URLs. I wanted my public URLs to start with "~/Admin/etc." while my public URLs would not have any such prefix.

Public Controller (one of several)

[RoutePrefix("Home")]
public class HomeController : Controller
{
    [Route("Index")]
    public ActionResult Index()
    { //etc. }
}

Admin Controller (one of several)

[RoutePrefix("Admin/People")]
public class PeopleController : Controller
{
    [Route("Index")]
    public ActionResult Index()
    { //etc. }
}

This allows me to have public URLs such as:

http://myapp/home/someaction

...and admin/authenticated URLs such as:

http://myapp/admin/people/someaction

But now I want to do some dynamic stuff in the views based on whether the user is in the Admin section or the Public section of the site. How can I access this programmatically, properly?

I know I could do something like

if (Request.Url.LocalPath.StartsWith("/Admin"))

...but it feels "hacky." I know I can access the controller and action names via

HttpContext.Current.Request.RequestContext.RouteData.Values

...but the "admin" piece isn't reflected in there, because it's just a route prefix, not an actual controller name.

So, the basic question is, how do I programmatically determine whether the currently loaded view is under the "admin" section or not?

Jiveman
  • 1,022
  • 1
  • 13
  • 30

1 Answers1

10

You just need to reflect the RoutePrefixAttribute from the Controller type, and then get its Prefix value. The Controller instance is available on the ViewContext.

This example creates a handy HTML helper that wraps all of the steps into a single call.

using System;
using System.Web.Mvc;

public static class RouteHtmlHelpers
{
    public static string GetRoutePrefix(this HtmlHelper helper)
    {
        // Get the controller type
        var controllerType = helper.ViewContext.Controller.GetType();

        // Get the RoutePrefix Attribute
        var routePrefixAttribute = (RoutePrefixAttribute)Attribute.GetCustomAttribute(
            controllerType, typeof(RoutePrefixAttribute));

        // Return the prefix that is defined
        return routePrefixAttribute.Prefix;
    }
}

Then in your view, you just need to call the extension method to get the value of the RoutePrefixAttribute.

@Html.GetRoutePrefix() // Returns "Admin/People"
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • Cool! I think that works well. I only tweaked the return from the extension method to account for situations where there is no prefix defined (like in my public controller). `return routePrefixAttribute != null ? routePrefixAttribute.Prefix : null;` – Jiveman Mar 14 '15 at 17:36
  • In AttributeRouting 3.5.6.0, the property is `Url` instead of `Prefix`. – Lars Gyrup Brink Nielsen Apr 28 '16 at 10:12
  • This worked. I didn't need the prefix from a view since I was making an API so I tweaked the extension method to take an ApiController instead so it could be used under the hood. Thanks! – starmandeluxe Sep 13 '16 at 06:32
  • 1
    one-liner: `helper.ViewContext.Controller.GetType().GetCustomAttribute.Prefix` – Andriy Tolstoy Jan 06 '17 at 14:22