2011-08-06 15 views
28

Mam następujący kod:Uzyskaj wszystkie wartości w NameValueCollection na ciąg

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

starałem się bawić z otrzymujemy:

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

Ale oczywiście to nie zadziała .

Potrzebuję czegoś podobnego, aby uzyskać wszystkie wartości, ale nie wydaje mi się, aby znaleźć odpowiedni kod, aby zrobić to samo.

P.S: Nie chcę używać pętli foreach, ponieważ to jest celem pierwszego wiersza kodu.

Odpowiedz

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

Ponadto można utworzyć metodę rozszerzenia:

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

Zastosowanie:

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

Ponadto można łatwo przekonwertować NameValueCollection do bardziej poręczny Dictionary<string,string> więc:

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

otrzymujemy:

var d = c.ToDictionary(); 

Jak znalezionego reflektora NameValueCollection.AllKeys wewnętrznie wykonuje pętlę zebrać wszelkie tE klucze, zatem wydaje się, że c.Cast<string>() jest bardziej korzystne.

+0

tylko mały dodatek, czy można dodawać cytaty do każdej wartości? – Dementic

+0

@Dementic: Pewnie. Po prostu użyj 'c.Select (e => String.Format (" \ "{0} \" ", c [e]));' – abatishchev

+0

dziękuję, to była naprawdę fajna odpowiedź! – Dementic

7
string values = 
    string.Join(",", FormValues.AllKeys.SelectMany(key => FormValues.GetValues(key))); 

Edit: Pozostałe odpowiedzi mogą być lub nie być, co chcesz. Wydają się prostsze, ale wyniki mogą nie być tym, czego szukasz w każdych okolicznościach, ale z drugiej strony mogą być (twój przebieg może się różnić).

Należy pamiętać, że NameValueCollection nie jest mapowaniem 1: 1 jak słownik. Możesz dodać wiele wartości dla tego samego klucza, dlatego funkcja taka jak .GetValues(key) zwraca tablicę, a nie pojedynczy ciąg.

Jeśli masz kolekcję którym dodano

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

Odzyskiwanie collection["Alpha"] plony "1,2". Odzyskiwanie collection.GetValues("Alpha") daje plony { "1", "2" }. Teraz tak się składa, że ​​używasz przecinka do łączenia wartości w jeden ciąg znaków, więc ta różnica jest ukryta. Jednakże, jeśli były łączenia na inną wartość, jak wykrzyknikiem, wyniki innych odpowiedzi byłoby

"1,2!3" 

I kod tutaj byłoby

"1!2!3" 

Użyj fragment, który demonstruje zachowanie, które wolisz.

21
string values = string.Join(",", collection.AllKeys.Select(key => collection[key])); 
+1

Tak to zrobiłem. Najprostsze rozwiązanie, ale może nie najbardziej czytelne we wszystkich przypadkach. Można to również osiągnąć za pomocą pętli foreach i po prostu połączyć pary klucz: wartość. – Blairg23

-1
List<string> values = new List<string>(); 
values.AddRange(all.AllKeys.SelectMany(all.GetValues).Where(getValues => getValues != null)); 
string Values = string.Join(",", values.ToArray()); 

Można spróbować coś jak wyżej.

7

Poniżej tworzony jest ciąg z listy parametrów URL.

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

tj

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

byłoby

id: 75, page: 3, size: 7, user: mamaci 
0

W przypadkach, gdy masz analizowany ciąg kwerendy z System.Web.HttpUtility.ParseQueryString (...) można po prostu użyć ToString() i nie musisz ponownie wymyślać koła.

Mimo że wynikiem jest NameValueCollection, typem podstawowym jest HttpValueCollection, który ma konieczne przesłonięcie ToString() w celu utworzenia ciągu zapytania.

0

Używam Azure DocumentDB jak mój mechanizm logowania, a więc pisanie obiekt dynamiczny, ale masz sens ...

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"; 
    } 
} 

Mam CustomException gdzie mogę sprawdzić, czy zestaw aplikacji kod odpowiedzi.

Dodatkowo, biorę querystring, dane formularza i model, dzięki czemu widzę wartości przekazane przed i po segregatorze modelu.

Jeśli jego i Ajax wywołanie, zwracam odpowiedź sformatowaną Json. W przeciwnym razie zwracam niestandardową stronę błędu.

Powiązane problemy