C# ASP.NET QueryString parser


7

Jeśli zostały patrząc na miły i czysty sposób analizować swoje wartości ciągu kwerendy, mam wymyślić to:

/// <summary> 
    /// Parses the query string and returns a valid value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="key">The query string key.</param> 
    /// <param name="value">The value.</param> 
    protected internal T ParseQueryStringValue<T>(string key, string value) 
    { 
     if (!string.IsNullOrEmpty(value)) 
     { 
      //TODO: Map other common QueryString parameters type ... 
      if (typeof(T) == typeof(string)) 
      { 
       return (T)Convert.ChangeType(value, typeof(T)); 
      } 
      if (typeof(T) == typeof(int)) 
      { 
       int tempValue; 
       if (!int.TryParse(value, out tempValue)) 
       { 
        throw new ApplicationException(string.Format("Invalid QueryString parameter {0}. The value " + 
                   "'{1}' is not a valid {2} type.", key, value, "int")); 
       } 
       return (T)Convert.ChangeType(tempValue, typeof(T)); 
      } 
      if (typeof(T) == typeof(DateTime)) 
      { 
       DateTime tempValue; 
       if (!DateTime.TryParse(value, out tempValue)) 
       { 
        throw new ApplicationException(string.Format("Invalid QueryString parameter {0}. The value " + 
                 "'{1}' is not a valid {2} type.", key, value, "DateTime")); 
       } 
       return (T)Convert.ChangeType(tempValue, typeof(T)); 
      } 
     } 
     return default(T); 
    } 

Zawsze chciałem mieć coś takiego i wreszcie to dobrze ... przynajmniej tak mi się wydaje ...

Kod powinien być oczywista ...

jakieś uwagi lub sugestie, aby lepiej są doceniane.

  0

Może poradzisz sobie z wcześniejszym stosem kodu, ale pamiętaj, że klucz może mieć wiele wartości w tekście zapytania, tj. X = 1,2,3 22 lut. 092009-02-22 15:58:07

  0

@jro Uważam, że przypadek wielu wartości jest nieważny, ponieważ o ile Querystring dotyczy tylko jednej wartości, ciągu "1,2,3", analizując go jako dowolny coś innego nie byłoby poprawne. 06 maj. 112011-05-06 13:37:25

5

Biorąc pod uwagę, że zajmujesz się tylko trzema różnymi typami, sugerowałbym zamiast tego trzy różne metody - metody ogólne są najlepsze, gdy działają dobrze z każdym argumentem typu dozwolonym przez ograniczenia typu.

Ponadto, gorąco polecam, że dla int i DateTime określić kulturę w użyciu - nie powinien naprawdę zależy od kultury serwer dzieje się w (Jeśli masz kod do odgadnięcia kultury. użytkownik, możesz go użyć zamiast tego.) Na koniec, proponuję także wsparcie dla dobrze określonego zestawu formatów DateTime, a nie tylko domyślnie obsługuje to, co obsługuje TryParse. (I dość dużo zawsze użycie ParseExact/TryParseExact zamiast Parse/TryParse).

Zauważ, że wersja ciąg naprawdę nie trzeba nic robić, skoro value jest już łańcuch (choć bieżących konwertuje kod " "do null, które mogą być lub nie być tym, co chcesz).

  0

+1 dla ParseExact/TryParseExact, zwłaszcza, że ​​można przekazać tablicę formatów. 22 lut. 092009-02-22 13:25:07


1

Wydaje mi się, że robisz wiele nietypowych konwersji. Zmienne tempValue odpowiadają typowi, który próbujesz zwrócić. Podobnie w przypadku łańcucha wartość jest już ciągiem, więc po prostu zwróć ją.


2

W mojej aplikacji używam następujących funkcji: -

public static class WebUtil 
{ 
    public static T GetValue<T>(string key, StateBag stateBag, T defaultValue) 
    { 
     object o = stateBag[key]; 

     return o == null ? defaultValue : (T)o; 
    } 
} 

Wymagana domyślny jest zwracany, jeśli parametr nie został dostarczony, typ jest wywnioskować z DefaultValue i wyjątki odlewnicze są podnoszone w miarę potrzeby .

użycia jest następujący: -

var foo = WebUtil.GetValue("foo", ViewState, default(int?)); 

34

prosty sposób analizowania (jeśli nie chcesz robić typu konwersji) jest

HttpUtility.ParseQueryString(queryString); 

Można wyodrębnić ciągu kwerendy z URL z

new Uri(url).Query 
+4

Działa to tylko wtedy, gdy URL jest pełnym adresem URL. Jeśli masz względny adres URL, członek Query użytkownika Uri nie jest obsługiwany. 27 mar. 112011-03-27 23:46:49


3

Napisałem następującą metodę do parsowania QueryString do mocno wpisanych wartości:

public static bool TryGetValue<T>(string key, out T value, IFormatProvider provider) 
{ 
    string queryStringValue = HttpContext.Current.Request.QueryString[key]; 

    if (queryStringValue != null) 
    { 
     // Value is found, try to change the type 
     try 
     { 
      value = (T)Convert.ChangeType(queryStringValue, typeof(T), provider); 
      return true; 
     } 
     catch 
     { 
      // Type could not be changed 
     } 
    } 

    // Value is not found, return default 
    value = default(T); 
    return false; 
} 

Przykład zastosowania:

int productId = 0; 
bool success = TryGetValue<int>("ProductId", out productId, CultureInfo.CurrentCulture); 

Dla kwerendy z ?productId=5bool byłoby właściwe i int productId będzie równa 5.

Dla kwerendy z ?productId=hellobool byłby fałszywy i int productId będzie równa 0.

Dla kwerendy z ?noProductId=notIncludedbool byłby fałszywy i int productId będzie równa 0.


0

oparciu o Ronalds answer mam zaktualizowanego moja własna metoda analizy parsowania. Sposób, w jaki go używam, polega na dodaniu go jako metody rozszerzenia na obiekcie strony, co ułatwia mi sprawdzenie wartości i typów kwerendy i przekierowanie, jeśli żądanie strony jest nieprawidłowe.

Metoda rozszerzenie wygląda następująco:

public static class PageHelpers 
{ 
    public static void RequireOrPermanentRedirect<T>(this System.Web.UI.Page page, string QueryStringKey, string RedirectUrl) 
    { 
     string QueryStringValue = page.Request.QueryString[QueryStringKey]; 

     if(String.IsNullOrEmpty(QueryStringValue)) 
     { 
      page.Response.RedirectPermanent(RedirectUrl); 
     } 

     try 
     { 
      T value = (T)Convert.ChangeType(QueryStringValue, typeof(T)); 
     } 
     catch 
     { 
      page.Response.RedirectPermanent(RedirectUrl); 
     } 
    } 
} 

To pozwala mi robić rzeczy, jak następuje:

protected void Page_Load(object sender, EventArgs e) 
{ 
    Page.RequireOrPermanentRedirect<int>("CategoryId", "/"); 
} 

mogę następnie napisać resztę mojego kodu i powoływać się na istnienie i prawidłowe format elementu zapytania, więc nie muszę go testować za każdym razem, gdy chcę uzyskać do niego dostęp.

Uwaga: Jeśli używasz pre .NET 4 a następnie będzie również chcą następujące RedirectPermanent metodę rozszerzenia:

public static class HttpResponseHelpers 
{ 
    public static void RedirectPermanent(this System.Web.HttpResponse response, string uri) 
    { 
     response.StatusCode = 301; 
     response.StatusDescription = "Moved Permanently"; 
     response.AddHeader("Location", uri); 
     response.End(); 
    } 
} 

2

Jest to stary odpowiedź, ale zrobiłem co następuje:

  string queryString = relayState.Split("?").ElementAt(1); 
      NameValueCollection nvc = HttpUtility.ParseQueryString(queryString);