Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Urls not produced when you use a RouteAttribute instead of using routes.MapRoute() #459

Open
johnwc opened this issue Feb 22, 2017 · 5 comments

Comments

@johnwc
Copy link

johnwc commented Feb 22, 2017

If I decorate my controllers and actions with the Route attributes built into MVC, in place of manually building out the routes via routes.MapRoute(), the provider doesn't seem to find or use the routes. When using the Route attributes, the Url for each product we build with the dynamic node all have # as the value.

Dynamic Node

foreach(var prod in cat.Products)
{
    var prodNode = new DynamicNode();
    prodNode.Title = prod.Name;
    prodNode.ParentKey = catNode.Key;
    prodNode.Key = string.Format("Product_{0}", prod.Id);
    prodNode.Attributes.Add("visible", false);
    prodNode.Controller = "Product";
    prodNode.Action = "Index";
    prodNode.Route = "ProductInfo";
    prodNode.RouteValues.Add("id", prod.Id);
    prodNode.RouteValues.Add("producttitle", prod.Name);
}

Example not working:

public class RouteConfig
{
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapMvcAttributeRoutes();
            ...
        }
}

[RoutePrefix("product")]
public class ProductController : Controller
{
    // GET: product/123/pepsi
    [Route("{id}/{producttitle}", Name ="ProductInfo")]
    public ActionResult Index(int id)
    {
        ...
    }
}

Example working:

public class RouteConfig
{
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "ProductInfo",
                "product/{id}/{producttitle}",
                new { controller = "Product", action = "Index" }
                );
            ...
        }
}

public class ProductController : Controller
{
    // GET: product/123/pepsi
    public ActionResult Index(int id)
    {
        ...
    }
}
@NightOwl888
Copy link
Collaborator

What happens if you remove/comment the route name for the non-working example?

//prodNode.Route = "ProductInfo";

Attribute Routing support was added as a contribution to MvcSiteMapProvider after MVC 5 was released, and it is possible that some of the features of it aren't fully supported.

@johnwc
Copy link
Author

johnwc commented Feb 23, 2017

Has no affect, still doesn't work.

@johnwc
Copy link
Author

johnwc commented Mar 9, 2017

If I call the Url.RouteUrl like so, it works. Is the code on the backend not calling Url.RouteUrl?

var url = new System.Web.Mvc.UrlHelper(HttpContext.Current.Request.RequestContext, System.Web.Routing.RouteTable.Routes);

foreach(var prod in cat.Products)
{
    var prodNode = new DynamicNode();
    prodNode.Title = prod.Name;
    prodNode.ParentKey = catNode.Key;
    prodNode.Key = string.Format("Product_{0}", prod.Id);
    prodNode.Attributes.Add("visible", false);
    prodNode.Controller = "Product";
    prodNode.Action = "Index";
    prodNode.Route = "ProductInfo";
    prodNode.RouteValues.Add("id", prod.Id);
    prodNode.RouteValues.Add("producttitle", prod.Name);
    prodNode.Url = url.RouteUrl("ProductInfo", new { id = prod.Id, producttitle = prod.Name });
}

@johnwc
Copy link
Author

johnwc commented Mar 26, 2017

Any updates?

@johnwc
Copy link
Author

johnwc commented Mar 29, 2017

So the issue turns out to be that the CurrentNode is always null when viewing a action that is created via attributes. I think I have traced it down to the FindSiteMapNodeFromMvcRoute method in the SiteMap.cs file. It looks like GetMvcRouteData returns the underlining route when contained in a RouteCollectionRoute, and then that value is passed to the FindSiteMapNodeFromMvcRoute. In FindSiteMapNodeFromMvcRoute it runs through all the routes on the RouteTable.Routes and checks to see if each is equal to the passed in Route. Since the RouteTable.Routes doesn't have the sub route in it's root list, it always equals false. It might need to be changed up so that it doesn't do a straight object == object, and maybe check the route path or something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants