2015-04-21 2 views
2

Я использую это расширение для создания RouteUrl с добавленной к нему текущей строкой запроса. Это отлично подходит для строк запросов, которые не имеют одного и того же ключа два или более.RouteUrl с querystring - с дублирующимися ключами

public static string CurrentQueryStringRouteUrl(this UrlHelper url, string routeName, RouteValueDictionary routeValues) 
{ 
    var context = url.RequestContext; 
    var combinedRouteValues = new RouteValueDictionary(); 
    var queryString = context.HttpContext.Request.QueryString; 

    foreach (var key in queryString.AllKeys.Where(key => key != null)) 
    { 
     combinedRouteValues[key] = queryString[key]; 
    } 

    if (routeValues != null) 
    { 
     foreach (var routeValue in routeValues) 
     { 
      combinedRouteValues[routeValue.Key] = routeValue.Value; 
     } 
    } 

    return url.RouteUrl(routeName, combinedRouteValues); 
} 

Когда есть клавиши строки запроса с таким же именем, например. ?id=1&id=2&id=3, он преобразуется в ?id=1,2,3 с использованием вышеописанного метода. Есть ли способ избежать этого? Я хочу сохранить исходную строку запроса, поскольку я привязываю эти значения в списке моделей.

Я знаю, что я могу создать настраиваемое связующее устройство для привязки строки, разделенной запятой, к string[] (или int[] в этом примере), но я хочу избежать этого, пока не будет консистенции.

ответ

0

Вы можете сделать это, но это грязный хак:

string _rawstring = context.HttpContext.Request.RawUrl; 
int _f; 
_f = _rawstring.IndexOf('?'); 
string _resultString = _rawstring.SubString(_f, _rawstring.Length); 

Здесь вы можете найти полезную информацию об этой проблеме: How to deal with more than one value per key in ASP.NET MVC 3?

+0

Я просто не понимаю, почему формы POST и GET значения не объединяются в виде разделенных запятыми строк. Если у меня есть элемент 'select', с множеством' multiple', форма submit result в '? Id = 1 & id = 2 & id = 3' – janhartmann

+0

Попробуйте следующее: QueryString.AllKeys.InvalidateCachedArrays() – SpookyBookie

+0

У вас есть дополнительная информация о том, что это будет делать? – janhartmann

0

я взял несколько иной подход, потому что я действительно нужен отдельный дублированные ключи в моей строке запроса. Я изменяю ключ, используя счетчик, а затем после рендеринга строки url восстанавливаю исходные имена параметров. Мне это нужно для запросов grid_filter от GridMvc, но вы можете адаптировать их для своей цели.

/// <summary> 
/// Allows you to create or extend a collection of route values to use in a url action 
/// </summary> 
public class RouteValueBuilder 
{ 
    readonly RouteValueDictionary routeValues; 
    private int gridFilterCounter = 0; 

    public RouteValueBuilder(object existingRouteValues = null) 
    { 
     routeValues = existingRouteValues as RouteValueDictionary ?? new RouteValueDictionary(existingRouteValues); 
    } 

    public void Add(string field, object value) 
    { 
     if (field == "grid_filter" && routeValues.ContainsKey(field)) 
     { 
      // Because we can't add duplicate keys and GridMvc doesn't support joined comma format for query strings, 
      // we briefly rename each new filter, and then the Finalise method must be called after the url 
      // string is rendered to restore the grid_filter names back to normal. 
      gridFilterCounter++; 
      routeValues.Add(field + gridFilterCounter, value); 
     } 
     else if (routeValues.ContainsKey(field)) 
     { 
      // Since duplicate key names are not supported, the concatenated comma approach can be used 
      routeValues[field] += "," + value; 
     } 
     else 
     { 
      routeValues.Add(field, value); 
     } 
    } 

    public RouteValueDictionary Get() 
    { 
     return routeValues; 
    } 

    /// <summary> 
    /// Cleans up the final string url, fixing workarounds done during the building process. 
    /// This must be called after the final url string is rendered. 
    /// </summary> 
    public static string Finalise(string url) 
    { 
     // Restores grid_filter parameters to their correct naming. See comments on Add method. 
     for (var i = 0; i < 100; i++) 
     { 
      url = url.Replace("grid_filter" + i, "grid_filter"); 
     } 

     return url; 
    } 
} 

Использование:

var builder = new RouteValueBuilder(); 
builder.Add("grid_filter", "value1"); 
builder.Add("grid_filter", "value2"); 
string url = Html.Action("Index", "Home", builder.Get()); 
url = RouteValueBuilder.Finalise(url); 

Edit: Обратите внимание, что запятая конкатенация подход фактически не работает в классе, потому что он будет закодирован, но поддержка для дублирования является основным берущей из этого примера.

Смежные вопросы