2009-02-22 12 views
7

Si usted ha estado buscando una manera agradable y limpio para analizar los valores de cadena de consulta, me han llegado con esto:C# ASP.NET cadena de consulta analizador

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

Siempre he querido tener algo por el estilo y finalmente lo hizo bien ... al menos eso creo ...

El código debe explicarse por sí misma ...

Cualquier comentario o sugerencia para que sea mejor son apreciadas.

+0

Tal vez lo maneje antes de la pila de códigos, pero recuerde que una clave puede tener varios valores en una cadena de consulta, es decir, x = 1,2,3 – jro

+0

@jro. Considero que el caso de valores múltiples no es válido porque hasta la cadena de consulta se refiere a su único valor, una cadena de "1,2,3", analizándolo como cualquier Lo demás no sería correcto. – rtpHarry

Respuesta

5

Dado que solo maneja tres tipos diferentes, sugeriría tres métodos diferentes en su lugar: los métodos genéricos son mejores cuando funcionan bien con cada argumento de tipo permitido por las restricciones de tipo.

Además, recomiendo encarecidamente que para int y DateTime especifique la cultura a utilizar, no debería depender realmente de la cultura en la que se encuentre el servidor. (Si tiene código para adivinar la cultura de la usuario, podría usar eso en su lugar.) Finalmente, también recomendaría admitir un conjunto bien especificado de formatos DateTime en lugar de solo lo que sea compatible con TryParse de manera predeterminada. (Yo casi siempre uso ParseExact/TryParseExact en lugar de Parse/TryParse.)

Tenga en cuenta que la versión de cadena en realidad no necesita hacer nada, ya que value ya es una cadena (aunque sus conversos del código actual " "a null, que puede ser o no lo que desee).

+0

+1 para ParseExact/TryParseExact, especialmente porque puede pasar una variedad de formatos. – Richard

1

Me parece que estás haciendo un montón de conversiones de tipo extrañas. Las variables tempValue están listas del tipo que está intentando devolver. Del mismo modo, en el caso de cadena, el valor ya es una cadena, así que solo devuélvalo.

2

En mi solicitud He estado usando la siguiente función: -

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

El valor predeterminado requerido se devuelve si el parámetro no se ha suministrado, el tipo se infiere de defaultValue y excepciones de fundición se planteó como necesario .

uso es el siguiente: -

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

Una forma sencilla de analizar (si usted no quiere hacer las conversiones de tipos) es

HttpUtility.ParseQueryString(queryString); 

se puede extraer cadena de consulta de una URL con

new Uri(url).Query 
+4

Esto solo funciona si url es una url completa. Si tiene una url relativa, entonces el miembro de Query de Uri no es compatible. – jrwren

3

He escrito el siguiente método para analizar el QueryString a los valores fuertemente tipados:

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

Ejemplo de uso:

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

Para una cadena de consulta de ?productId=5 la bool sería cierto y int productId sería igual a 5.

Para una cadena de consulta de ?productId=hello la bool sería falso y int productId sería igual a 0.

Para una cadena de consulta de ?noProductId=notIncluded la bool sería falso y int productId sería igual a 0.

0

Basado en Ronalds answer He actualizado mi propio método de análisis querystring. La forma en que lo uso es agregarlo como un método de extensión en el objeto de la página, así que es fácil para mí verificar los valores y tipos de la cadena de consulta y redirigir si la solicitud de la página no es válida.

El método de extensión es similar a esto:

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

Esto me permite hacer cosas como la siguiente:

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

entonces puedo escribir el resto de mi código y se basan en la existencia y correcto formato del elemento de la cadena de consulta, así que no tengo que probarlo cada vez que quiero acceder a él.

Nota: Si está utilizando .NET pre 4 a continuación, se quiere también quieren el siguiente método de extensión 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

Ésta es una vieja respuesta, pero he hecho lo siguiente:

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