views:

110

answers:

3

Hello Everyone,

i have following two routes registered in my global.asax file

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

and i have a static "dashboard" link in my tabstrip and some other links that are constructed from values in db here is the code

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

Now my launching address is localhost/oa.mvc/index/11 clearly matching the 2nd route. but when i visit any page that has mapped to first route and then come back to dash.board link it shows me localhost/oa.mvc/7/index/11 where 7 is docid and picked from previous Url. now i understand that my action method is after docid and changing it would not clear the docid. my question here is that can i remove docid in this scenario without changing the route. regards
adeel

A: 

In this particular scenario I have two recommendations:

  1. Use named routes. The first parameter to the MapRoute method is a name. To generate links use Html.RouteLink() (and other similar APIs). This way you'll always choose the exact route that you want and never have to wonder what gets chosen.

  2. If you still want to use Html.ActionLink() then explicitly set docid="" to clear out its value.

Eilon
@Elion yes i want to use html.actionlink() and i m setting docid = "" but this is not clearing out its value. it rather appends docid into query string. i m using .NET 4 mvc2 RTMthanks
Muhammad Adeel Zahid
+1  A: 

I have the same "not clearing out" value problem...

I've stepped into source code and I don't understand the reason for being of segment commented as : // Add all current values that aren't in the URL at all

@ System\Web\Routing\ParsedRoute.cs, public BoundUrl Bind(RouteValueDictionary currentValues, RouteValueDictionary values, RouteValueDictionary defaultValues, RouteValueDictionary constraints) method from line 91 to line 100

While the clearing process is correctly handled in method preceding steps, this code "reinjects" the undesired parameter into acceptedValues dictionary!?

Thx, Mat.

Mathias Kozlowski
@Mathias Kozlowski thanks it was a great insight. how would u suggest clearing these values
Muhammad Adeel Zahid
A: 

Muhammad, I suggest something like this : (written 5 mn ago, not tested in production)

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