2015-04-21 122 views
2

我使用此擴展名創建RouteUrl,並附加當前查詢字符串。這適用於沒有相同密鑰兩次或更多的查詢字符串。帶查詢字符串的RouteUrl - 帶有重複鍵

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'設置,表單提交結果在'?id = 1&id = 2&id = 3' – janhartmann

+0

試試這個:QueryString.AllKeys.InvalidateCachedArrays() – SpookyBookie

+0

你有更多的信息做? – janhartmann

0

我參加了一個稍微不同的方法,因爲我真的需要分開在我的查詢字符串中重複鍵。我使用計數器更改密鑰,然後在呈現url字符串之後,恢復原始參數名稱。我需要這個GridMvc的grid_filter查詢,但你可以根據你的目的進行調整。

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

編輯:注意逗號的級聯方法其實並不在類中,因爲它被編碼的工作,但複製的支持,從這個例子的主要接受者。