views:

268

answers:

3

I have to sort a namevaluecollection(Items usually 5 to 15) Against an enum(having items more than 60). Right now I am using this extension function, Anyone have better idea to write this code....

    public static NameValueCollection Sort(this NameValueCollection queryString, Type orderByEnumType, bool excludeZeroValues)
    {
        NameValueCollection _processedQueryString = HttpUtility.ParseQueryString("");
        if (queryString.HasKeys())
        {
            SortedList<int, KeyValuePair<string, string>> querySortedList = new SortedList<int, KeyValuePair<string, string>>();
            string[] enumKeys = Enum.GetNames(orderByEnumType);
            int counter = 1000;
            foreach (string key in queryString)
            {
                string value = queryString[key];
                if (enumKeys.Contains(key, StringComparer.CurrentCultureIgnoreCase))
                {
                    int order = (int)Enum.Parse(orderByEnumType, key, true);
                    querySortedList.Add(order, new KeyValuePair<string, string>(key, value));
                }
                else
                {
                    querySortedList.Add(counter, new KeyValuePair<string, string>(key, value));
                    counter++;
                }
            }
            foreach (KeyValuePair<int, KeyValuePair<string, string>> kvp in querySortedList)
            {
                if (!kvp.Value.Value.IsNullOrEmpty() && !kvp.Value.Key.IsNullOrEmpty())
                {
                    if (!excludeZeroValues || kvp.Value.Value != "0")
                    {
                        _processedQueryString.Add(kvp.Value.Key, System.Web.HttpUtility.UrlEncode(kvp.Value.Value));
                    }
                }
            }
        }
        return _processedQueryString;
    }

This works like this

    public enum OrderEnum
    {
        key1=1,
        key2=20,
        key3=3,
        //note
        key4=100,
        key5=2,
        key6=6,
        key7,
        key8,
        key9 
    }
    public void Test()
    {
        NameValueCollection col1 = new NameValueCollection();
        col1.Add("key1", "value1");
        col1.Add("key9", "value1");
        col1.Add("key3", "value1");
        col1.Add("key5", "value1");
        Response.Write(col1.Sort(typeof(OrderEnum)).ToString());
        //out put: key1=value1&key5=value1&key3=value1&key9=value1
    }

This is should also work

public void Test2()
    {
        NameValueCollection col1 = new NameValueCollection();
        col1.Add("key1", "value1");
        col1.Add("key-x", "value1");
        col1.Add("key-y", "value1");
        col1.Add("key9", "value1");
        col1.Add("key3", "value1");
        col1.Add("key5", "value1");
        col1.Add("key-z", "value1");
        Response.Write(col1.Sort(typeof(OrderEnum)).ToString());
        //out put: key1=value1&key5=value1&key3=value1&key9=value1&key-x=value1&key-y=value1&key-z=value1
    }
+1  A: 

I think its better to convert your namevaluecollection into List of keyvaluepairs and apply a simple LINQ order by operation, thats quick and simple.

Add a new extension method to convert your namevaluecoll into list of keyvaluepairs

    public static List<KeyValuePair<string, string>> ToPairs(this System.Collections.Specialized.NameValueCollection collection)
    {
        if (collection == null)
        {
            throw new ArgumentNullException("collection");
        }

        return collection.Cast<string>().Select(key => new KeyValuePair<string, string>(key, collection[key])).ToList();
    } 

And just apply the linq order by over this object, something like this

        System.Collections.Specialized.NameValueCollection col1= new System.Collections.Specialized.NameValueCollection();
        col1.Add("key1", "value1");
        col1.Add("key-x", "value2");
        col1.Add("key-y", "value3");
        col1.Add("key9", "value4");
        col1.Add("key3", "value5");
        col1.Add("key5", "value6");
        col1.Add("key-z", "value7"); 

        var nvc = col1.ToPairs();

        // To order the items based on key in descending order
        var orderedbykey=nvc.OrderByDescending(x => x.Key).ToList();  

       // To order the items based on value in descending order           
       var orderedbyval=nvc.OrderByDescending(x => x.Value).ToList();

       //or order by ur custom enum key
        var orderbyEnumKeys = colc.OrderBy(x =>
        {
            int en;
            try
            {
                 en = (int)Enum.Parse(typeof(OrderEnum), x.Key);
            }
            catch (Exception ex)
            {
                return int.MaxValue;
            }
            return en;
        }).ToList();

Hope this helps..

Cheers

Ramesh Vel
Can you describe how to use an Enum in sorting. Please use the exact scenario I have used.
Mukesh
@Mukesh, i have updated my source code to meet ur requirements, check out is that ok?
Ramesh Vel
OKie I got my Solution Thx
Mukesh
A: 

You could do something like that :

public static NameValueCollection SortByEnum<TEnum>(this NameValueCollection source) where TEnum : struct
{
    var orderedKeys = source.Keys.Cast<string>().OrderBy(k => Enum.IsDefined(typeof(TEnum), k) ? Convert.ToInt32(Enum.Parse(typeof(TEnum), k)) : int.MaxValue);
    var ordered = new NameValueCollection();
    foreach(var key in orderedKeys) ordered.Add(key, source[key]);
    return ordered;
}
Thomas Levesque
This gives error when Key is not defined in the enum. IN this case the undfined keys should be placed at the end of collecion
Mukesh
I edited my code to handle that case
Thomas Levesque
A: 

I finally Came to conclusion with this solution

public static NameValueCollection SortByEnum<TEnum>(this NameValueCollection source) where TEnum : struct
{
    var orderedKeys = source.Keys.Cast<string>().OrderBy(k => ((Enum.IsDefined(typeof(TEnum), k)) ? ((int)Enum.Parse(typeof(TEnum), k)) : int.MaxValue));
    var ordered = HttpUtility.ParseQueryString("");
    foreach (var key in orderedKeys)
    {
        ordered.Add(key, source[key]);
    }
    return ordered;
}

This will resolve all my issues Thanks @thomas @ramesh

Mukesh