Reputation: 11798
I have a web application based an ASP.NET MVC4 in which I use a layout that contains three language flags (images). These flags are visible throughout the whole site. Now I want to use these images for language selection. In order to show any of the pages in a specific language, I just need to add a parameter to the current URL and load it, my controllers then evaluate it and set the correct language in the model (or set a default fallback language when there's no language specified in the request).
Here's an example:
No language specified:
http://example.com?StationId=12
Language specified:
http://example.com?StationId=12&lang=1033
My question is: how can I form a link in my layout that surrounds a language flag image and always points to the currently loaded URL with all the parameters PLUS a new parameter &lang=1033
respectively ?lang=1033
in case there's only the language parameter?
In other words: how to create a link to the very same page with all parameters and simply add a route value to the URL?
Update: Here's a detailed example
In my _Layout.cshtml
I have:
@{
var u_eng = new RouteValueDictionary(Url.RequestContext.RouteData.Values);
var u_deu = new RouteValueDictionary(Url.RequestContext.RouteData.Values);
var u_por = new RouteValueDictionary(Url.RequestContext.RouteData.Values);
u_eng.Add("lang", "1033");
u_deu.Add("lang", "1031");
u_por.Add("lang", "1046");
}
.
.
.
<li>
<a href="@Url.RouteUrl(u_por)" class="Flag BR">BR</a>
</li>
<li>
<a href="@Url.RouteUrl(u_eng)" class="Flag US">US</a>
</li>
<li>
<a href="@Url.RouteUrl(u_deu)" class="Flag DE">DE</a>
</li>
Now, when I run the site, the links on the start page work just fine, they point towards the current page and add the lang=xy parameter to the corresponding URL.
But when I go to another page that uses the very same layout file and also uses a parameter, the links don't get build correctly: suppose I go to a subpage that is defined by this URL:
http://localhost:1234/Stations?position=up
The page itself gets displayed correctly. But when I hover or follow the language links, they point to:
http://localhost:1234/Stations?lang=1031
instead of
http://localhost:1234/Stations?position=up&lang=1031
As you can see, any existing parameters are omitted.
Upvotes: 3
Views: 9711
Reputation: 98
I've extended @Andrei's answer a little and created helper methods to build Url
s in the view.
These are helper methods:
private static RouteValueDictionary GetKeyValuePairs(this UrlHelper urlHelper)
{
var routeValueDictionary = new RouteValueDictionary(urlHelper.RequestContext.RouteData.Values);
var queryString = HttpContext.Current.Request.QueryString;
foreach (var key in queryString.AllKeys) routeValueDictionary.Add(key, queryString[key]);
return routeValueDictionary;
}
public static string BuildUrl(this UrlHelper urlHelper)
{
var routeValueDictionary = GetKeyValuePairs(urlHelper);
return urlHelper.RouteUrl(routeValueDictionary);
}
public static string BuildUrl(this UrlHelper urlHelper, string key)
{
var routeValueDictionary = GetKeyValuePairs(urlHelper);
if (routeValueDictionary.Keys.Contains(key)) routeValueDictionary.Remove(key);
return urlHelper.RouteUrl(routeValueDictionary);
}
public static string BuildUrl(this UrlHelper urlHelper, string key, object value)
{
var routeValueDictionary = GetKeyValuePairs(urlHelper);
if (routeValueDictionary.ContainsKey(key)) routeValueDictionary[key] = value;
else routeValueDictionary.Add(key, value);
return urlHelper.RouteUrl(routeValueDictionary);
}
Then in my views, I use it like this:
<a href='@Url.BuilUrl()' >Preserve current query string.</a>
<a href='@Url.BuilUrl("param2", "value")' >Add item to query string.</a>
<a href='@Url.BuilUrl("param1")' >Remove item from query string.</a>
Result for http://localhost:5000/?param2=value2 :
<a href='http://localhost:5000/?param2=value2'>Preserve current query string.</a>
<a href='http://localhost:5000/?param2=value2¶m1=value'>Add item to query string.</a>
<a href='http://localhost:5000/?param1=value' >Remove item from query string.</a>
Hope it helps folks.
Upvotes: 1
Reputation: 56716
You can use current route values collection, add new value to it, and then produce the url with url helper RouteUrl
. To collect query string parameters passed to the page you can iterate throught the HttpContext.Request.QueryString
dictionary:
@{
var currentRouteValues = new RouteValueDictionary(Url.RequestContext.RouteData.Values);
var queryString = Request.QueryString;
foreach (var key in queryString.AllKeys)
{
currentRouteValues.Add(key, queryString[key]);
}
currentRouteValues.Add("lang", "1033");
}
Then use it like this:
@Url.RouteUrl(currentRouteValues)
Upvotes: 8