Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy does routing break down when I modify RouteValueDictionary?
    primarykey
    data
    text
    <p>I register several routes as such:</p> <pre><code>routes.MapRoute( name: "contentPage", url: "{*path}", defaults: new { controller = "ContentPage", action = "Index", path = "start" }, constraints: new { path = new NodeTypeConstraint(siteTree, "contentPage") } ); routes.MapRoute( name: "category", url: "{*path}", defaults: new { controller = "Category", action = "Index" }, constraints: new { path = new NodeTypeConstraint(siteTree, "category") } ); </code></pre> <p>And a default one:</p> <pre><code>routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", Id = UrlParameter.Optional } ); </code></pre> <p>The siteTree is a tree of nodes that can be content pages, categories or products (among other things).</p> <p>In the constraint I add a new entry to the RouteValueDictionary:</p> <pre><code>public class NodeTypeConstraint : IRouteConstraint { private readonly TreeNode _siteTree; private readonly string _type; public NodeTypeConstraint(TreeNode siteTree, string type) { _siteTree = siteTree; _type = type; } public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { var path = values[parameterName].ToString(); var node = _siteTree.Find(path); if (node != null &amp;&amp; node.Properties["type"] == _type) { values["node"] = node; return true; } return false; } } </code></pre> <p>Adding "node" to RVD lets me define actions like this one:</p> <pre><code>public class ContentPageController : Controller { public ActionResult Index(TreeNode node) { return View(node); } } </code></pre> <p>Without modifying the RVD the action would have to be:</p> <pre><code> public ActionResult Index(string path) {} </code></pre> <p>...which would force me to once again use the site tree to look up the node. I want to avoid that.</p> <p>This new helper method lets me generate links:</p> <pre><code> public static IHtmlString ActionLink(this HtmlHelper html, TreeNode node) { return html.ActionLink( node.Properties["title"] ?? node.Name, "Index", node.Properties["type"], new {path = node}, null); } </code></pre> <p>Awsome! But routing breaks down when I do "default" routing. Instead of producing a correct link the following creates a link with an empty "href" attribute:</p> <pre><code>Html.ActionLink("Register", "Register", "Account") </code></pre> <p>To fix this and without acctually knowing what the hell I'm doing, I changed the default route registration to this:</p> <pre><code> routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", Id = UrlParameter.Optional }, constraints: new { id = new FakeConstraint() } ); </code></pre> <p>And this:</p> <pre><code>public class FakeConstraint : IRouteConstraint { public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { return true; } } </code></pre> <p>I'd sleep much better if I know why MVC behaves like this. Did I go about this the wrong way?</p> <p>EDIT: If I throw out that awful FakeConstraint and instead do this, it totally works. If I only knew why, sigh.</p> <pre><code>public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { var path = values[parameterName].ToString(); var node = _siteTree.Find(path); if (node != null &amp;&amp; node.Properties["type"] == _type) { values["node"] = node; // These two lines make FakeConstraint redundant: values["controller"] = route.Defaults["controller"]; values["action"] = route.Defaults["action"]; return true; } return false; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload