代码之家  ›  专栏  ›  技术社区  ›  Muhammad Adeel Zahid

MVC2.NET路由中的环境值

  •  5
  • Muhammad Adeel Zahid  · 技术社区  · 15 年前

    我有两条路线在我的 global.asax 文件

    routes.MapRoute(
        "strict",
        "{controller}.mvc/{docid}/{action}/{id}",
        new { action = "Index", id = "", docid = "" },
        new { docid = @"\d+"}
    );
    routes.MapRoute(
        "default",
        "{controller}.mvc/{action}/{id}",
        new { action = "Index", id = "" },
        new { docConstraint = new DocumentConstraint() }
    );
    

    我的tabstrip中有一个静态的“dashboard”链接,还有一些其他的链接是用db中的值构建的,这里是代码

     <ul id="globalnav" class = "t-reset t-tabstrip-items">
         <li class="bar" id = "dashboard">
             <%=Html.ActionLink("dash.board", "Index", pck.Controller,  new{docid =string.Empty,id = pck.PkgID }, new { @class = "here" })%>
         </li>
         <%  
             foreach (var md in pck.sysModules)
             {
         %>
         <li class="<%=liClass%>">
             <%=Html.ActionLink(md.ModuleName, md.ActionName, pck.Controller, new { docid = md.DocumentID}, new { @class = cls })%>
         </li>
         <%
             }
         %>
     </ul>
    

    现在我的启动地址是 localhost/oa.mvc/index/11 与第二条路线明显匹配。但是当我访问任何映射到第一条路线然后返回到 dash.board 链接它显示我 localhost/oa.mvc/7/index/11 在哪里? 7 docid 从以前的URL中选择。

    我知道我的操作方法是在docid之后,更改它不会清除docid。

    我的问题是,我能把它移走吗? 多西德 在这种情况下,不改变路线?

    6 回复  |  直到 8 年前
        1
  •  4
  •   erlando    14 年前

    我有同样的“不清除”价值问题…

    我已经深入到源代码中,我不理解被注释为以下段的原因: //添加所有不在URL中的当前值

    @ System\Web\Routing\ParsedRoute.cs , public BoundUrl Bind(RouteValueDictionary currentValues, RouteValueDictionary values, RouteValueDictionary defaultValues, RouteValueDictionary constraints) 从第91行到第100行的方法

    在前面步骤的方法中正确处理清除过程的同时,此代码会将不需要的参数“reinject”到acceptedvalues字典中!?

        2
  •  4
  •   Robert Koritnik    14 年前

    我的路由定义如下:

    routes.MapRoute(
        "Planning",
        "Plans/{plan}/{controller}/{action}/{identifier}",
        new { controller = "General", action = "Planning", identifier = UrlParameter.Optional },
        new { plan = @"^\d+$" }
    );
    
    // default application route
    routes.MapRoute(
        "Default",
        "{controller}/{action}/{identifier}",
        new {
            controller = "General",
            action = "Summary",
            identifier = UrlParameter.Optional,
            plan = string.Empty // mind this default !!!
        }
    );
    

    这和你正在使用的非常相似。但请注意我定义默认值的默认路径。即使我的默认路线没有定义 plan 路由值我仍将其设置为 string.Empty . 所以每当我使用 Html.ActionLink() Url.Action() 我想要 计划 要从URL中删除,我通常称之为:

    Url.Action("Action", "Controller", new { plan = string.Empty });
    

    并且计划不再包含在URL查询字符串中。你自己试试看,它也可能管用。

        3
  •  2
  •   Mathias Kozlowski    15 年前

    穆罕默德,我建议这样做: (500万以前写的,未在生产中测试)

    public static class MyHtmlHelperExtensions {
    
        public static MvcHtmlString FixActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes) {
            var linkRvd = new RouteValueDictionary(routeValues);
            var contextRvd = htmlHelper.ViewContext.RouteData.Values;
            var contextRemovedRvd = new RouteValueDictionary();
    
            // remove clearing route values from current context
            foreach (var rv in linkRvd) {
                if (string.IsNullOrEmpty((string)rv.Value) && contextRvd.ContainsKey(rv.Key)) {
                    contextRemovedRvd.Add(rv.Key, contextRvd[rv.Key]);
                    contextRvd.Remove(rv.Key);
                }
            }
    
            // call ActionLink with modified context
            var htmlString = htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);
    
            // restore context
            foreach (var rv in contextRemovedRvd) {
                contextRvd.Add(rv.Key, rv.Value);
            }
    
            return htmlString;
        }
    }
    
        4
  •  2
  •   Khalid Abuhakmeh    14 年前

    这是一个令人沮丧的问题,我冒昧地说,它甚至是ASP.NET MVC中的一个bug。幸运的是,使用actionfilters很容易修复。如果您使用的是MVC3,那么我将把它作为一个全局属性来清除环境值。我将此属性设置为歧视性的,但您可以将其更改为清除所有属性。

    这里的假设是,在执行结果时(您的视图很可能),您已经显式地指定了所有的actionLinks和form操作。因此,这将在他们(链接)被评估之前执行,给你一个新的基础来生成它们。

    public class ClearAmbientRouteValuesAttribute : ActionFilterAttribute 
    {
        private readonly string[] _keys;
    
        public ClearAmbientRouteValuesAttribute(params string [] keys)
        {
            if (keys == null)
                _keys = new string[0];
    
            _keys = keys;
        }
    
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            foreach (var key in _keys) {
                // Why are you sticking around!!!
                filterContext.RequestContext.RouteData.Values.Remove(key);        
            }
        }
    }
    
    // Inside your Global.asax
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new ClearAmbientRouteValuesAttribute("format"));
    }
    

    希望这能帮助别人,因为它确实帮助了我。谢谢你问这个问题。

        5
  •  0
  •   Eilon    15 年前

    在这个特定的场景中,我有两个建议:

    1. 使用命名路由。的第一个参数 MapRoute 方法是一个名称。要生成链接,请使用 Html.RouteLink() (和其他类似的原料药)。这样你就可以选择 准确的 你想走的路线,不必想知道选择了什么。

    2. 如果你还想用 Html.ActionLink() 然后显式设置 docid="" 清除它的价值。

        6
  •  0
  •   Lucent Fox    13 年前

    以下是我解决问题的方法,可能需要稍作调整才能使其正常工作,但我觉得我可以得到我需要的东西,并或多或少地正常使用路由:

    摘自apress pro asp.net.mvc 3框架:

    • 必须为在URL模式中定义的每个段变量提供一个值。 要查找每个段变量的值,路由系统首先查看 我们提供的值(使用匿名类型的属性),然后 当前请求的变量值,最后是中定义的默认值 路线。(我们将在本章后面返回这些值的第二个来源。)

    • 我们为段变量提供的任何值都不能与 仅默认路由中定义的变量。 这些是默认的变量 已提供值,但这些值不会出现在URL模式中。为了 例如,在这个路由定义中,myvar是一个默认的唯一变量:

      routes.maproute(“myroute”,“控制器/操作”, 新建myvar=“true”);

      要使该路径匹配,我们必须注意不要为myvar提供值或 确保我们提供的值与默认值匹配。

    • 所有段变量的值必须满足路由约束。见 本章前面的“限制路线”部分提供了不同的示例 各种约束。

    基本上,我使用了一个关于路由不匹配的规则,如果它没有定义一个段,但是有一个默认变量,用来让我对路由是否被选为出站路由有更多的控制。

    这是我的固定路线,请注意我如何为永远无效的类别指定值,并且不为类别指定段。这意味着如果我有一个类别,路由将被跳过,但是如果我只有一个页面,路由将被使用:

    routes.MapRoute(null, "receptionists/faq/{page}", new { controller = "Receptionist", action = "Faq", page = 1, category = (Object)null }, new { page = @"^\d+$" });
    
    routes.MapRoute(null, "receptionists/faq/{category}/{page}", new { controller = "Receptionist", action = "Faq", page = 1 }, new { category = @"^\D+$", page = @"^\d+$" });
    

    对于类别链接

    @Html.ActionLink("All", "Faq", new { page = 1 })
    
    @foreach (var category in Model.Categories)
    {
    @Html.ActionLink(category.DisplayName, "faq", new { category = category.DisplayName.ToLower(), page = 1 })
    }
    

    用于页面链接

    @for (var p = 1; p <= Model.TotalPages; p++)
    {
    @Html.ActionLink(p.ToString(), "Faq", new { page = p, category = Model.CurrentCategory})
    }