Question

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.

Était-ce utile?

La solution

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)

Autres conseils

I've extended @Andrei's answer a little and created helper methods to build Urls 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&param1=value'>Add item to query string.</a>
<a href='http://localhost:5000/?param1=value' >Remove item from query string.</a>

Hope it helps folks.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top