我注册了几条路线:
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") }
);
默认的一个:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", Id = UrlParameter.Optional }
);
siteTree是一个节点树,可以是内容页面,类别或产品(以及其他内容)。
在约束中,我向RouteValueDictionary添加一个新条目:
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 && node.Properties["type"] == _type)
{
values["node"] = node;
return true;
}
return false;
}
}
将“node”添加到RVD允许我定义类似这样的动作:
public class ContentPageController : Controller
{
public ActionResult Index(TreeNode node)
{
return View(node);
}
}
如果不修改RVD,则必须采取以下措施:
public ActionResult Index(string path) {}
...这将迫使我再次使用站点树来查找节点。我想避免这种情况。
这个新的帮助方法可以让我生成链接:
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);
}
AWSOME!但是当我执行“默认”路由时,路由会中断。以下创建一个带有空“href”属性的链接,而不是生成正确的链接:
Html.ActionLink("Register", "Register", "Account")
为了解决这个问题并且没有实际知道我到底在做什么,我将默认路由注册更改为:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", Id = UrlParameter.Optional },
constraints: new { id = new FakeConstraint() }
);
而且:
public class FakeConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
return true;
}
}
如果我知道为什么MVC会像这样,我会睡得好多了。我是以错误的方式解决这个问题吗?
编辑:如果我扔出那个糟糕的FakeConstraint而是这样做,它完全有效。如果我只知道原因,请叹气。
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 && 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;
}