Get all values of a NameValueCollection to a string
Asked Answered
M

7

37

I have the following code:

string Keys = string.Join(",",FormValues.AllKeys);

I was trying to play around with the get:

string Values = string.Join(",", FormValues.AllKeys.GetValue());

But of course that doesn't work.

I need something similar to get all the values, but I don't seem to find the appropriate code to do the same.

P.S: I do not want to use a foreach loop since that beats the purpose of the first line of code.

Mellie answered 6/8, 2011 at 13:38 Comment(0)
S
43
var col = new NameValueCollection() { { "a", "b" }, { "1", "2" } }; // collection initializer

var values = col.Cast<string>().Select(e => col[e]); // b, 2

var str = String.Join(",", values );  // "b,2"

Also you can create an extension method:

public static string Join(this NameValueCollection collection, Func<string,string> selector, string separator)
{
    return String.Join(separator, collection.Cast<string>().Select(e => selector(e)));
}

Usage:

var s = c.Join(e => String.Format("\"{0}\"", c[e]), ",");

Also you can easily convert NameValueCollection to more handy Dictionary<string,string> so:

public static IDictionary<string,string> ToDictionary(this NameValueCollection col)
{
    return col.AllKeys.ToDictionary(x => x, x => col[x]);
}

Gives:

var d = c.ToDictionary();

As I found using Reflector, NameValueCollection.AllKeys internally performs a loop to gather all te keys, so it seems that c.Cast<string>() is more preferable.

Stepp answered 6/8, 2011 at 13:44 Comment(4)
just a little addition, can quotes be added to each value ?Mellie
@Dementic: Sure. Just use c.Select(e => String.Format("\"{0}\"", c[e]));Stepp
I think that one line needs to be: var values = col.Cast<string>().Select(e => col[e]);Kennel
This was a perfect solution for my problem of formatting a NameValueCollection as a query string: string queryString = string.Join("&", queryParams.Cast<string>().Select(e => e + "=" + queryParams[e]));Tortile
K
29
string values = string.Join(",", collection.AllKeys.Select(key => collection[key]));
Klockau answered 6/8, 2011 at 13:45 Comment(1)
This is how I did it. Simplest solution, but maybe not the most readable in all instances. This can also be accomplished using a foreach loop and just concatenating the key:value pairs.Tortile
G
10

Following creates a string from URL parameter list.

string.Join(", ", 
            Request.QueryString
                   .AllKeys
                   .Select(key => key + ": " + Request.QueryString[key])
      .ToArray())

i.e

page.aspx?id=75&page=3&size=7&user=mamaci

would be

id: 75, page: 3, size: 7, user: mamaci
Gluck answered 8/5, 2013 at 9:34 Comment(0)
A
9
string values = 
    string.Join(",", FormValues.AllKeys.SelectMany(key => FormValues.GetValues(key)));

Edit: The other answers may or may not be what you want. They appear simpler, but the results might not be what you are looking for in all circumstances, but then again, they might be (your mileage may vary).

Note that a NameValueCollection is not a 1:1 mapping like a dictionary. You can add multiple values for the same key, which is why a function like .GetValues(key) returns an array, not a single string.

If you have a collection where you have added

 collection.Add("Alpha", "1");
 collection.Add("Alpha", "2");
 collection.Add("Beta", "3");

Retrieving collection["Alpha"] yields "1,2". Retrieving collection.GetValues("Alpha") yields { "1", "2" }. Now, it just so happens that you are using a comma to join your values together into a single string, so this disparity is hidden. However, if you were joining on another value, such as an exclamation point, the results of the other answers would be

"1,2!3"

And the code here would be

"1!2!3"

Use the snippet that demonstrates the behavior you prefer.

Also answered 6/8, 2011 at 13:45 Comment(0)
T
0

In cases where you have parsed the query string with System.Web.HttpUtility.ParseQueryString(...) you can just use ToString() and you don't have to re-invent the wheel.

Even though result is NameValueCollection, the underlying type is HttpValueCollection which has the necessary ToString() override to build back a query string.

Torch answered 2/5, 2014 at 19:15 Comment(0)
E
0

I'm using Azure DocumentDB as my logging mechanism, hence writing a dynamic object, but you get the gist...

public class LogErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        int responseCode = new int();

        // Has the exception been handled.  Also, are custom errors enabled
        if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            return;

        // Check if custom exception, if so get response code
        if (filterContext.Exception is CustomException)
            responseCode = (int)((CustomException)filterContext.Exception).Code;

        // Log exception
        string id = Logging.Write(LogType.Error, new
        {
            ResponseCode = responseCode,
            Exception = new
            {
                Message = filterContext.Exception.Message,
                Data = filterContext.Exception.Data,
                Source = filterContext.Exception.Source,
                StackTrace = filterContext.Exception.StackTrace,
                InnerException = filterContext.Exception.InnerException != null ? new
                {
                    Message = filterContext.Exception.InnerException.Message,
                    Data = filterContext.Exception.InnerException.Data,
                    Source = filterContext.Exception.InnerException.Source,
                    StackTrace = filterContext.Exception.InnerException.StackTrace
                } : null
            },
            Context = filterContext.Controller != null ? new
            { 
                RouteData = filterContext.Controller.ControllerContext.RouteData,
                QueryString = filterContext.Controller.ControllerContext.HttpContext.Request.Url.Query,
                FormParams = filterContext.Controller.ControllerContext.HttpContext.Request.Form != null ? string.Join(";#", filterContext.Controller.ControllerContext.HttpContext.Request.Form.AllKeys.Select(key => key + ":" + filterContext.Controller.ControllerContext.HttpContext.Request.Form[key])) : string.Empty,
                Model = (filterContext.Controller is Controller) ? ((Controller)filterContext.Controller).ModelState : null,
                ViewBag = filterContext.Controller.ViewBag,
                ViewData = filterContext.Controller.ViewData
            } : null,
            ActionResult = filterContext.Result != null ? filterContext.Result : null,
            Referrer = filterContext.HttpContext.Request.UrlReferrer != null ? filterContext.HttpContext.Request.UrlReferrer : null
        }).Result;

        // Mark exception as handled and return
        filterContext.ExceptionHandled = true;

        // Test for Ajax call
        if (IsAjax(filterContext))
        {
            // Construct appropriate Json response
            filterContext.Result = new JsonResult()
            {
                Data = new
                {
                    code = responseCode,
                    id = id,
                    message = filterContext.Exception.Message
                },
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };

        }
        else
        {
            var result = new ViewResult();
            result.ViewName = "_CustomError";
            result.ViewBag.CorrelationId = id;
            filterContext.Result = result;
        }
    }

    /// <summary>
    /// Determine if the request is from an Ajax call
    /// </summary>
    /// <param name="filterContext">The request context</param>
    /// <returns>True or false for an Ajax call</returns>
    private bool IsAjax(ExceptionContext filterContext)
    {
        return filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest";
    }
}

I have a CustomException where I check for a application-set response code.

Additionally, I take the querystring, form data, and the model so that I can see the values passed before and after the model binder.

If its and Ajax call, I return a Json-formatted response. Otherwise, I return a custom error page.

Electrocautery answered 31/3, 2015 at 20:34 Comment(0)
B
-1
List<string> values = new List<string>();
values.AddRange(all.AllKeys.SelectMany(all.GetValues).Where(getValues => getValues != null));
string Values = string.Join(",", values.ToArray());

You can try something like the above.

Bloodshed answered 6/8, 2011 at 13:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.