C# ASP.NET QueryString parser


7

Se sono state cercando un modo bello e pulito per analizzare i tuoi valori di stringa di query, ho messo a punto questo:

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

Ho sempre voluto avere qualcosa di simile e infine capito bene ... almeno io la penso così ...

Il codice dovrebbe essere auto esplicativo ...

Eventuali commenti o suggerimenti per renderlo migliore sono apprezzati.

  0

Forse lo gestisci in anticipo sullo stack di codice, ma ricorda che una chiave può avere più valori in una sequenza di interrogazioni, ovvero x = 1,2,3 22 feb. 092009-02-22 15:58:07

  0

@jro Considererei il caso con più valori non valido perché fino a la querystring riguarda il suo unico valore, una stringa di "1,2,3", analizzandola come qualsiasi cos'altro non sarebbe corretto. 06 mag. 112011-05-06 13:37:25

5

Dato che si gestiscono solo tre tipi diversi, suggerirei invece tre metodi diversi: i metodi generici sono i migliori quando funzionano bene con ogni argomento di tipo consentito dai vincoli di tipo.

Inoltre, mi sento di raccomandare con forza che per int e DateTime si specifica la cultura da usare - non dovrebbe in realtà dipende dalla cultura del server sembra essere (se si dispone di codice di indovinare la cultura del. utente, è possibile utilizzarlo.) Infine, suggerirei anche di supportare un set ben specificato di formati DateTime piuttosto che qualsiasi supporto TryParse per impostazione predefinita. (Ho praticamente sempre uso ParseExact/TryParseExact invece di Parse/TryParse.)

Si noti che la versione stringa non ha veramente bisogno di fare nulla, visto che value è già una stringa (anche se i tuoi converte il codice correnti " "a null, che può o non può essere quello che vuoi).

  0

+1 per ParseExact/TryParseExact, specialmente se è possibile passare una serie di formati. 22 feb. 092009-02-22 13:25:07


1

Mi sembra che stiate facendo un sacco di conversioni di tipo spiacevoli. Le variabili tempValue sono carine del tipo che stai cercando di restituire. Allo stesso modo nel caso di stringa il valore è già una stringa, quindi è sufficiente restituirlo.


2

Nella mia domanda ho usato la seguente funzione: -

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

Il predefinito richiesto viene restituito se il parametro non è stato fornito, il tipo è dedotto da defaultValue e le eccezioni di fusione sono allevati secondo necessità .

uso è il seguente: -

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

34

Un modo semplice per analizzare (se non volete fare conversioni di tipo) è

HttpUtility.ParseQueryString(queryString); 

È possibile estrarre querystring da un URL con

new Uri(url).Query 
+4

Funziona solo se url è un URL completo. Se si dispone di un url relativo, il membro Query di Uri non è supportato. 27 mar. 112011-03-27 23:46:49


3

Ho scritto il seguente metodo per analizzare la QueryString con valori fortemente digitati:

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

Esempio di utilizzo:

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

Per una querystring di ?productId=5 del bool sarebbe vero e int productId sarebbe uguale 5.

Per una querystring di ?productId=hello del bool sarebbe falsa e int productId sarebbe uguale a 0.

Per una querystring di ?noProductId=notIncluded del bool sarebbe falsa e int productId sarebbe uguale a 0.


0

Sulla base di Ronalds answer Ho aggiornato il mio metodo di parsing di querystring. Il modo in cui lo uso è di aggiungerlo come metodo di estensione all'oggetto Page così è facile per me controllare i valori e i tipi di querystring e reindirizzare se la richiesta di pagina non è valida.

Il metodo di estensione si presenta così:

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

Questo mi permette di fare le cose come le seguenti:

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

posso quindi scrivere il resto del mio codice e invocare l'esistenza e la corretta formato dell'elemento querystring quindi non devo testarlo ogni volta che voglio accedervi.

Nota: Se si utilizza pre .net 4 poi si vuole anche il seguente metodo di estensione RedirectPermanent:

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

Questa è una risposta vecchia, ma ho fatto la seguente:

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