views:

287

answers:

2

Seems like a straitforward question but I can't quite figure it out myself...

I have an actionlink like so

Html.ActionLink( "Test", "test", new { q = "search+twitter" } )

This produces a url string as follows

http://myserver/test?q=search%2Btwitter

But i would like to preserve the plus sign (which i assume is being UrlPathEncoded) so that I get the following url

http://myserver/test?q=search+twitter

Is there an easy way to do this whilst still using Html.ActionLink ?

+1  A: 

The plus sign (after encoding) represents a space before encoding.

So search+twitter will become "search twitter" on post back, and to achieve that effect, you can simply use "search twitter" in the first place:

Html.ActionLink( "Test", "test", new { q = "search twitter" } )

which will generate following url

http://myserver/test?q=search%20twitter

Hope this helps.

Bill Yang
Thanks for the answer. However i actually want to have http://myserver/test?q=search+twitter as the url in my browser and I'm still stumped as to how you might achieve this.
Stuart
If that is your goal, one solution might be to create your own Extension Method for HtmlHelper to generate the url.
Bill Yang
+2  A: 

After some more googling, i reworded the question in this post. Using the answer from that question I was able to put together a suitable routing extension method which i include below.

public static class RouteCollectionExtensions
{
    public static void CustomMapRoute( this RouteCollection routes, string name, string url, object defaults )
    {
        routes.CustomMapRoute( name, url, defaults, null, null );
    }

    public static void CustomMapRoute( this RouteCollection routes, string name, string url, object defaults, string[] namespaces )
    {
        routes.CustomMapRoute( name, url, defaults, namespaces, null );
    }

    public static void CustomMapRoute( this RouteCollection routes, string name, string url, object defaults, string[] namespaces, object constraints )
    {
        if ( routes == null )
            throw new ArgumentNullException( "routes" );

        if ( url == null )
            throw new ArgumentNullException( "url" );

        var route = new CustomRoute( url, new MvcRouteHandler() )
        {
            Defaults = new RouteValueDictionary( defaults ),
            Constraints = new RouteValueDictionary( constraints ),
            DataTokens = new RouteValueDictionary()
        };

        if ( (namespaces != null) && (namespaces.Length > 0) )
        {
            route.DataTokens["Namespaces"] = namespaces;
        }

        if ( String.IsNullOrEmpty( name ) )
            routes.Add( route );
        else
            routes.Add( name, route );
    }
}

public class CustomRoute : Route
{
    public CustomRoute( string url, IRouteHandler routeHandler )
        : base( url, routeHandler ) { }

    public CustomRoute( string url, RouteValueDictionary defaults, IRouteHandler routeHandler )
        : base( url, defaults, routeHandler )
    { }

    public override VirtualPathData GetVirtualPath( RequestContext requestContext, RouteValueDictionary values )
    {
        var path = base.GetVirtualPath( requestContext, values );
        if ( path != null )
        {
            path.VirtualPath = path.VirtualPath.Replace( "%20", "+" );
        }
        return path;
    }
}

This extension is then called by the RegisterRoutes method in global.asax like so...

        routes.CustomMapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },  // Parameter defaults
            new string[] { "MyControllers" }
        );
Stuart