Как добавить параметр к текущему URL в представлении?

У меня есть веб-приложение на основе ASP.NET MVC4, в котором я использую макет, который содержит три языковых флага (изображения). Эти флаги видны по всему сайту. Теперь я хочу использовать эти изображения для выбора языка. Чтобы показать какую-либо страницу на определенном языке, мне просто нужно добавить параметр к текущему URL и загрузить его, мои контроллеры затем оценивают его и устанавливают правильный язык в модели (или устанавливают запасной язык по умолчанию, когда есть язык не указан в запросе).

Вот пример (hxxp = http):

Язык не указан:

hxxp://mysite.com?StationId=12

Указанный язык:

hxxp://mysite.com?StationId=12&lang=1033

У меня вопрос: как я могу сформировать ссылку в моем макете, которая окружает изображение языкового флага и всегда указывает на загруженный в данный момент URL со всеми параметрами ПЛЮС новый параметр&lang=1033 соответственно ?lang=1033 если есть только параметр языка?

Другими словами: как создать ссылку на ту же страницу со всеми параметрами и просто добавить значение маршрута в URL?

Обновление: вот подробный пример

В моем _Layout.cshtml Я имею:

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

Теперь, когда я запускаю сайт, ссылки на стартовой странице работают нормально, они указывают на текущую страницу и добавляют параметр lang=xy в соответствующий URL.

Но когда я перехожу на другую страницу, которая использует тот же самый файл макета и также использует параметр, ссылки не будут собраны правильно: предположим, я перехожу на подстраницу, определенную этим URL:

http://localhost:1234/Stations?position=up

Сама страница отображается правильно. Но когда я парю или перехожу по языковым ссылкам, они указывают на:

http://localhost:1234/Stations?lang=1031 вместо

http://localhost:1234/Stations?position=up&lang=1031

Как видите, любые существующие параметры опущены.

1 ответ

Решение

Вы можете использовать текущую коллекцию значений маршрута, добавить к ней новое значение, а затем создать URL с помощью помощника URL. RouteUrl, Чтобы собрать параметры строки запроса, переданные на страницу, вы можете выполнить итерацию HttpContext.Request.QueryString толковый словарь:

@{
    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"); 
}

Тогда используйте это так:

@Url.RouteUrl(currentRouteValues)

Я немного расширил ответ @Andrei и создал вспомогательные методы для сборки Urlв поле зрения.

Это вспомогательные методы:

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

        }

Тогда, по моему мнению, я использую это так:

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

Результат для 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>

Надеюсь, это поможет людям.

Другие вопросы по тегам