How to determine Route Prefix programmatically in asp.net mvc?

Jiveman picture Jiveman · Mar 14, 2015 · Viewed 7.1k times · Source

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?

Answer

NightOwl888 picture NightOwl888 · Mar 14, 2015

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"