In ASP.NET MVC 2 - How do I get Route Values into my navigation controller so I can highlight the current link?
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 = "Strea开发者_如何学编程m", 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.
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)
{
...
}
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>
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));
}
精彩评论