2009-02-22 3 views
7

Если Вы ищете хороший и чистый способ разобрать ваши строковые значения запроса, я пришел с этим:C# ASP.NET QueryString анализатор

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

Я всегда хотела иметь что-то подобное и, наконец, получил это право ... по крайней мере я так думаю ...

код должен быть сам объяснительный ...

Любые комментарии или предложения, чтобы сделать его лучше оценены.

+0

Возможно, вы справляетесь с этим раньше своего кода, но помните, что ключ может иметь несколько значений в querystring, т. Е. X = 1,2,3 – jro

+0

@jro. Я считаю, что случай с несколькими значениями недействителен, поскольку запрос вызывает только одно значение, строку «1,2,3», анализируя ее как любую другое дело не будет правильным. – rtpHarry

ответ

5

Учитывая, что вы обрабатываете только три разных типа, я бы предложил три разных метода: универсальные методы лучше всего подходят для каждого аргумента типа, разрешенного ограничениями типа.

Кроме того, я настоятельно рекомендую, чтобы для int и DateTime вы указывали культуру, которую нужно использовать, - она ​​не должна зависеть от культуры, в которой находится сервер. (Если у вас есть код, чтобы угадать культуру пользователь, вы могли бы использовать это.) Наконец, я также предлагаю поддерживать хорошо определенный набор форматов DateTime, а не только то, что TryParse поддерживает по умолчанию. (Я довольно много всегда использование ParseExact/TryParseExact вместо Parse/TryParse.)

Обратите внимание, что строка версии на самом деле не нужно ничего делать, учитывая, что value уже строка (хотя текущий код новообращенных " "до null, который может быть или не быть тем, что вы хотите).

+0

+1 для ParseExact/TryParseExact особенно, поскольку вы можете передать массив форматов. – Richard

1

Мне кажется, что вы делаете много ненужных преобразований типов. Переменные tempValue представляют собой тип, который вы пытаетесь вернуть. Аналогично в строковом случае значение уже является строкой, поэтому просто верните ее.

2

В моем приложении я использую следующие функции: -

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

Требуемые по умолчанию возвращаются, если параметр не указан, тип выводится из DefaultValue и исключение литейные поднимаются по мере необходимости ,

Использование выглядит следующим образом: -

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

Простой способ разбора (если вы не хотите, чтобы делать преобразования типов) является

HttpUtility.ParseQueryString(queryString); 

Вы можете извлечь строки запроса из URL с

new Uri(url).Query 
+4

Это работает только в том случае, если URL-адрес является полным URL-адресом. Если у вас есть относительный url, то член Query Uri не поддерживается. – jrwren

3

Я написал следующий метод для синтаксического анализа QueryString для строго типизированных значений:

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

Пример использования:

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

Для строк запроса о ?productId=5bool будет истинным и int productId будет равна 5.

Для строки запроса из ?productId=hellobool будут ложными и int productId будет равен 0.

Для строки запроса из ?noProductId=notIncludedbool будут ложными и int productId будет равен 0.

0

На основе Ronalds answer я обновляемой мой собственный метод разбора строк. Способ, которым я его использую, заключается в том, чтобы добавить его как метод расширения объекта страницы, поэтому для меня легко проверить значения и типы запроса и перенаправить, если запрос страницы недействителен.

Метод расширения выглядит следующим образом:

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

Это позволяет мне делать такие вещи, как следующее:

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

Затем я могу написать остальную часть моего кода и полагаться на существование и правильно формат элемента запроса, поэтому мне не нужно его проверять каждый раз, когда я хочу получить к нему доступ.

Примечание: Если вы используете предварительно .NET 4, то вы будете также хотеть следующий 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

Это старый ответ, но я сделал следующее:

  string queryString = relayState.Split("?").ElementAt(1); 
      NameValueCollection nvc = HttpUtility.ParseQueryString(queryString); 
Смежные вопросы