2009-03-02 4 views
21

Мне любопытно, что все делают для обработки/абстрагирования QueryString в ASP.NET. В некоторых из наших веб-приложений, я вижу много это весь сайт:Преобразование/доступ к значениям QueryString в ASP.NET

int val = 0; 
if(Request.QueryString["someKey"] != null) 
{ 
val = Convert.ToInt32(Request.QueryString["someKey"]); 
} 

Какие лучшие способы справиться с этой грубостью?

ответ

24

Я склонен нравится идея абстрагирование их как свойства. Например:

 public int age { 
     get 
     { 
      if (Request.QueryString["Age"] == null) 
       return 0; 
      else 
       return int.Parse(Request.QueryString["Age"]);          
     } 
    } 

Вы могли бы добавить еще проверку, если вы хотите. Но я, как правило, люблю обматывать все мои переменные строки запроса таким образом.

EDIT: --- Также как другой плакат указал, что вы должны создавать эти свойства на каждой странице. Мой ответ - нет. Вы можете создать эти свойства в одном классе, который вы можете назвать «QueryStrings» или что-то еще. Тогда вы можете создать экземпляр этого класса на каждой странице, где вы хотите получить доступ к строкам запроса, то вы можете просто сделать что-то вроде

var queryStrings = new QueryStrings(); 
var age = queryStrings.age; 

Таким образом, вы можете инкапсулировать всю логику для доступа и обработки каждого типа переменного запроса в одном обслуживаемом месте.

EDIT2: --- И поскольку это экземпляр класса, вы также можете использовать инъекцию зависимостей для инъекции класса QueryStrings в любом месте, где вы его используете. StructureMap хорошо справляется с этим. Это также позволяет вам макетировать класс QueryStrings и вводить это, если вы хотите выполнить автоматическое модульное тестирование. Это намного проще обмануть, чем объект Request ASP.Net.

+0

Добавленный бонус здесь заключается в том, что он сообщает будущим разработчикам, что именно ожидать от строки запроса, когда они сначала садятся с вашим кодом. –

+0

Да, спасибо, что заметили это. Это определенно намерение. – 7wp

+0

+1 - отличный способ справиться с этим – nailitdown

8

Одно дело - вы не записываете пустые значения здесь. У вас может быть URL-адрес «http://example.com?someKey=&anotherKey=12345», и в этом случае значение параметра «someKey» равно «» (пустое). Вы можете использовать string.IsNullOrEmpty() для проверки как нулевого, так и пустого состояний.

Я также изменил бы «someKey», который будет храниться в переменной. Таким образом, вы не повторяете буквальные строки в нескольких местах. Это упрощает обслуживание.

int val = 0; 
string myKey = "someKey"; 
if (!string.IsNullOrEmpty(Request.QueryString[myKey])) 
{ 
    val = int.Parse(Request.QueryString[myKey]); 
} 

Надеюсь, что это поможет!

Ян

+0

это, скорее всего, исключение! –

+0

, вы обязательно захотите включить обработку ошибок. Это дано, не так ли? :) –

+0

'int val = 0; строка myKey = "someKey"; string strVal = HttpContext.Current.Request.QueryString [myKey]; if (! String.IsNullOrEmpty (strVal) &&! Int.TryParse (strVal, out val)) { val = 0; } ' – GFoley83

3

Написать какой-то вспомогательный метод (библиотека), чтобы справиться с этим ...

public static void GetInt(this NameValueCollection nvCol, string key, out int keyValue, int defaultValue) 
{ 
    if (string.IsNullOrEmpty(nvCol[key]) || !int.TryParse(nvCol[key], out keyValue)) 
     keyValue = defaultValue; 
} 

Или что-то вдоль этих линий ...

+0

Но программист должен знать ожидаемый тип, в который должна быть возвращена строка запроса. (Чтобы узнать, какую функцию вызывать) Если вы завернете его с помощью свойства getter, как в ответе, который я дал, тогда все, что вам нужно знать, - это имя свойства, которым вы пользуетесь. Intellisense сделает все остальное. – 7wp

+0

Да, точно так же, как программист должен был знать ожидаемый тип строки запроса для настройки свойства. Мое решение состоит в том, чтобы остановить повторяющиеся yucky заявления «если» во всем шоу, как описано в вопросе. Что они делают с кодом после этого до них - эй, положите его в собственность! – Charlino

+0

, но как только свойство настроено, то есть оно сделано.другим программистам, которые приходят после этого, не придется догадываться, какие данные содержатся в строке запроса и какая должна быть конкретная проверка. вы можете обернуть все это в свойстве. – 7wp

1

Мы использовали константы, чтобы сохранить все эти «свободные» ключи в центре города:

public class Constants 
{ 
    public class QueryString 
    { 
    public const string PostID = "pid"; 
    public const string PostKey = "key"; 
    } 
    public class Cookie 
    { 
    public const string UserID = "mydomain.com-userid"; 
    } 
    public class Cache 
    { 
    public const string PagedPostList = "PagedPostList-{0}-{1}"; 
    } 
    public class Context 
    { 
    public const string PostID = "PostID"; 
    } 
    public class Security 
    { 
    public const RoleAdministrator = "Administrator"; 
    } 
} 

Таким образом, вы легко получить доступ к константы, которые Вам нужны:

public void Index() 
{ 
    if (Request[Constants.QueryString.PostKey] == "eduncan911") 
    { 
    // do something 
    } 
} 

public object GetPostsFromCache(int postID, int userID) 
{ 
    String cacheKey = String.Format(
     Constants.Cache.PagedPostList 
     , userID 
     , postID); 
    return Cache[cacheKey] as IList<Post>; 
} 
0

Я с плакатом, который предложил вспомогательные методы (я бы прокомментировал его, но пока не могу). Кто-то другой не соглашался с ним в пользу создания свойств, но мой ответ на это заключается в том, что он не изящно справляется с проблемой проверки нулей или неправильного форматирования и т. Д. Если у вас есть вспомогательные методы, вся эта логика может быть написана один раз и централизованная.

Если у вас много страниц, добавление свойств для каждого может быть более трудоемким, чем того стоит. Но это, очевидно, просто предпочтение, поэтому каждому его.

Одна хорошая вещь, которую вы могли бы улучшить в другом вспомогательном методе плаката, заключается в том, чтобы вместо параметра out указать ссылочный параметр (смените на ref). Таким образом вы можете установить значение по умолчанию для свойства, если оно не передано. Иногда вам могут понадобиться дополнительные параметры, например, тогда вы можете начать с некоторого значения по умолчанию для тех случаев, когда необязательный параметр явно не передается (проще, чем значение по умолчанию передается отдельно). Вы даже можете добавить логический параметр IsRequired в конце и заставить его генерировать исключение, если для bool установлено значение true и параметр не передан. Это может быть полезно во многих случаях.

+0

Вам не нужно создавать свойства на каждой странице. Только один класс, содержащий все свойства, которые вы ожидаете использовать. Затем вы можете создать экземпляр этого класса на страницах, которые вы используете для доступа к параметрам запроса. – 7wp

+0

Ну, это предполагает, что у вас есть одинаковые параметры запроса на каждой странице. В большой системе у вас будет огромное количество разных, так же как у вас разные параметры для разных методов. Кажется, что консистенция - это хорошо. – x4000

3

Вот что я придумал. Он использует дженерики возвращать сильно типизированное значение из QueryString или дополнительного значения по умолчанию, если параметр не в QueryString:

/// <summary> 
    /// Gets the given querystring parameter as a the specified value <see cref="Type"/> 
    /// </summary> 
    /// <typeparam name="T">The type to convert the querystring value to</typeparam> 
    /// <param name="name">Querystring parameter name</param> 
    /// <param name="defaultValue">Default value to return if parameter not found</param> 
    /// <returns>The value as the specified <see cref="Type"/>, or the default value if not found</returns> 
    public static T GetValueFromQueryString<T>(string name, T defaultValue) where T : struct 
    { 
     if (String.IsNullOrEmpty(name) || HttpContext.Current == null || HttpContext.Current.Request == null) 
      return defaultValue; 

     try 
     { 
      return (T)Convert.ChangeType(HttpContext.Current.Request.QueryString[name], typeof(T)); 
     } 
     catch 
     { 
      return defaultValue; 
     } 
    } 

    /// <summary> 
    /// Gets the given querystring parameter as a the specified value <see cref="Type"/> 
    /// </summary> 
    /// <typeparam name="T">The type to convert the querystring value to</typeparam> 
    /// <param name="name">Querystring parameter name</param> 
    /// <returns>The value as the specified <see cref="Type"/>, or the types default value if not found</returns> 
    public static T GetValueFromQueryString<T>(string name) where T : struct 
    { 
     return GetValueFromQueryString(name, default(T)); 
    } 

С момента написания этого поста я написал очень небольшую библиотеку классов для работы значения QueryString - см https://github.com/DanDiplo/QueryString-Helper

+0

+1 для приятного простого использования дженериков. – GFoley83

+0

Получение: 'Строка типа 'должна быть невообразимым значением типа, чтобы использовать ее в качестве параметра' T 'в обобщенном ...' –

+0

@PierreLebon Strings - это типы значений, поэтому ограничение общего характера структуры не будет с ними. Но вам не нужно их преобразовывать, поскольку значение уже является строкой. Начиная с этого поста я написал небольшую библиотеку - см. Https://github.com/DanDiplo/QueryString-Helper - это должно помочь вам. –

1

по мне, лучший способ, чтобы получить строку запроса значение, как следующее:
Если строки запроса не найден, то значение val будет 0.

int val = 0; 
int.TryParse(Request.QueryString["someKey"], out val); 
Смежные вопросы