为什么在修改RouteValueDictionary时路由会中断?

时间:2013-11-28 20:59:50

标签: asp.net-mvc-4

我注册了几条路线:

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;
}

0 个答案:

没有答案