4

I'm trying to get the current Route into my navigation controller so I can run comparisons as the navigation menu data is populated.

My Links object is like this:

public class StreamNavLinks
{
    public string Text { get; set; }
    public RouteValueDictionary RouteValues { get; set; }
    public bool IsSelected { get; set; }
}

In the master page, I'm trying to pass the current route to the nav controller like this:

<% Html.RenderAction(
    "MenuOfStreamEntries", // action
    "Nav", // controller
    new { // parameters for action
        currentStreamUrl = "Blog", 
        currentRoute = ViewContext.RouteData } // get route data to compare in controller
); %>

The problem that I'm running into is that I can't figure out how to get any of the data out of currentRoute. What is the best technique for getting the values out or currentRoute?

I've tried syntax like this:

 currentRoute.Values.routevaluename

and

 currentRoute.Values[0]

But I can't seem to get it to work.

Edit

I have also tried placing this code into the action of the navigation controller:

var current = RouteData["streamUrl"];

and

var current = this.RouteData["streamUrl"];

Both versions give me this error:

Error 1 Cannot apply indexing with [] to an expression of >type 'System.Web.Routing.RouteData' C:\pathtocontroller\NavController.cs 25 27

Edit 2

It also might be helpful to know the route values that I'm trying to match against:

        routes.MapRoute(null, "", // Only matches the empty URL (i.e. ~/)
                        new
                        {
                            controller = "Stream",
                            action = "Entry",
                            streamUrl = "Pages",
                            entryUrl = "HomePage"
                        }
        );

        routes.MapRoute(null, "{streamUrl}/{entryUrl}", // matches ~/Pages/HomePage
                        new { controller = "Stream", action = "Entry" }
        );

So, ultimately mydomain.com/blog/blogentry1 would map to the same controller/action as mydomain.com/pages/welcome. I'm not looking for the controller value or the action value, rather I'm looking for streamUrl value and EntryUrl value.

3 Answers 3

15

You don't need to pass route data to a controller because the controller already has knowledge of it via the RouteData property:

public ActionResult Index() {
    // You could use this.RouteData here
    ...
}

Now if you want to pass some simple arguments like current action that was used to render the view you could do this:

<%= Html.RenderAction(
    "MenuOfStreamEntries",
    "Nav",
    new {
        currentStreamUrl = "Blog", 
        currentAction = ViewContext.RouteData.Values["action"],
        currentController = ViewContext.RouteData.Values["controller"]
    }
); %>

And in your controller:

public ActionResult Nav(string currentAction, string currentController) 
{
    ...
}
Sign up to request clarification or add additional context in comments.

5 Comments

Am I doning this right in the controller? var current = this.RouteData["streamUrl"]; doesn't compile.
Should be RouteData.Values["streamUrl"]
@Darin - I got the same error with that syntax. Please see edited question above.
In your Edit you are trying RouteData["streamUrl"]; while I suggested you RouteData.Values["streamUrl"]. See my previous comment.
@Darin - the devil's in the details. lol I'm playing with it again now.
5

Taken from this good article.

Create a custom extension method:

public static class HtmlExtensions
{
    public static MvcHtmlString ActionMenuItem(this HtmlHelper htmlHelper, String linkText,
        String actionName, String controllerName)
    {
        var tag = new TagBuilder("li");

        if ( htmlHelper.ViewContext.RequestContext
            .IsCurrentRoute(null, controllerName, actionName) )
        {
            tag.AddCssClass("selected");
        }

        tag.InnerHtml = htmlHelper.ActionLink(linkText, actionName, controllerName).ToString();

        return MvcHtmlString.Create(tag.ToString());
    }
}

Your HTML markup:

<div id="menucontainer">

    <ul id="menu">
        <%= Html.ActionMenuItem("Home", "Index", "Home") %>
        <%= Html.ActionMenuItem("About", "About", "Home") %>
    </ul>

</div>

Produces the following output:

<div id="menucontainer">

    <ul id="menu">
        <li class="selected"><a href="/">Home</a></li>
        <li><a href="/Home/About">About</a></li>
    </ul>

</div>

Comments

1

Here's a sample method we wrote for doing something similar.

public static bool IsCurrentAction(this HtmlHelper helper, string actionName, string controllerName)
{
  string currentControllerName = (string)helper.ViewContext.RouteData.Values["controller"];
  string currentActionName = (string)helper.ViewContext.RouteData.Values["action"];

  return currentControllerName.Equals(controllerName, StringComparison.CurrentCultureIgnoreCase) && currentActionName.Equals(actionName, StringComparison.CurrentCultureIgnoreCase));
}

2 Comments

This is cool. I might switch my navigation code to do something more like this.
did not show how to use IsCurrentAction() function. provide the usage too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.