Вопрос

Я часто использую Request.QueryString[] переменные.

В моем Page_load Я часто делаю такие вещи, как:

       int id = -1;

        if (Request.QueryString["id"] != null) {
            try
            {
                id = int.Parse(Request.QueryString["id"]);
            }
            catch
            {
                // deal with it
            }
        }

        DoSomethingSpectacularNow(id);

Все это кажется немного неуклюжим и вздорным.Как вы справляетесь со своими Request.QueryString[]с?

Это было полезно?

Решение

Ниже приведен метод расширения, который позволит вам писать подобный код:

int id = request.QueryString.GetValue<int>("id");
DateTime date = request.QueryString.GetValue<DateTime>("date");

Он использует TypeDescriptor чтобы выполнить преобразование.Исходя из ваших потребностей, вы могли бы добавить перегрузку, которая принимает значение по умолчанию вместо создания исключения:

public static T GetValue<T>(this NameValueCollection collection, string key)
{
    if(collection == null)
    {
        throw new ArgumentNullException("collection");
    }

    var value = collection[key];

    if(value == null)
    {
        throw new ArgumentOutOfRangeException("key");
    }

    var converter = TypeDescriptor.GetConverter(typeof(T));

    if(!converter.CanConvertFrom(typeof(string)))
    {
        throw new ArgumentException(String.Format("Cannot convert '{0}' to {1}", value, typeof(T)));
    }

    return (T) converter.ConvertFrom(value);
}

Другие советы

Используйте int.Вместо этого попробуйте выполнить синтаксический анализ, чтобы избавиться от блока try-catch:

if (!int.TryParse(Request.QueryString["id"], out id))
{
  // error case
}

Попробуй этого чувака...

List<string> keys = new List<string>(Request.QueryString.AllKeys);

Тогда вы сможете очень легко найти у парня строку с помощью...

keys.Contains("someKey")

Я использую небольшой вспомогательный метод:

public static int QueryString(string paramName, int defaultValue)
{
    int value;
    if (!int.TryParse(Request.QueryString[paramName], out value))
        return defaultValue;
    return value;
}

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

int id = QueryString("id", 0);

Ну, во-первых, используйте int.Вместо этого попробуйте проанализировать...

int id;
if (!int.TryParse(Request.QueryString["id"], out id))
{
    id = -1;
}

Это предполагает, что "not present", конечно, должно иметь тот же результат, что и "not an integer".

Редактировать:В других случаях, когда вы все равно собираетесь использовать параметры запроса в виде строк, я думаю, что это определенно хорошая идея - проверить, что они присутствуют.

Вы также можете использовать описанные ниже методы расширения и поступить следующим образом

int? id = Request["id"].ToInt();
if(id.HasValue)
{

}

// Методы расширения

public static int? ToInt(this string input) 
{
    int val;
    if (int.TryParse(input, out val))
        return val;
    return null;
}

public static DateTime? ToDate(this string input)
{
    DateTime val;
    if (DateTime.TryParse(input, out val))
        return val;
    return null;
}

public static decimal? ToDecimal(this string input)
{
    decimal val;
    if (decimal.TryParse(input, out val))
        return val;
    return null;
}
if(!string.IsNullOrEmpty(Request.QueryString["id"]))
{
//querystring contains id
}

Ииии, это риск для кармы...

У меня есть СУХАЯ абстракция, поддающаяся модульному тестированию, потому что, ну, потому что было слишком много переменных querystring, чтобы сохранить их при устаревшем преобразовании.

Приведенный ниже код взят из служебного класса, конструктору которого требуется ввод NameValueCollection (this.source), а массив строк "keys" - потому, что устаревшее приложение было довольно органичным и разработало возможность использования нескольких разных строк в качестве потенциального ключа ввода.Однако мне вроде как нравится расширяемость.Этот метод проверяет коллекцию на наличие ключа и возвращает его в требуемом типе данных.

private T GetValue<T>(string[] keys)
{
    return GetValue<T>(keys, default(T));
}

private T GetValue<T>(string[] keys, T vDefault)
{
    T x = vDefault;

    string v = null;

    for (int i = 0; i < keys.Length && String.IsNullOrEmpty(v); i++)
    {
        v = this.source[keys[i]];
    }

    if (!String.IsNullOrEmpty(v))
    {
        try
        {
            x = (typeof(T).IsSubclassOf(typeof(Enum))) ? (T)Enum.Parse(typeof(T), v) : (T)Convert.ChangeType(v, typeof(T));
        }
        catch(Exception e)
        {
            //do whatever you want here
        }
    }

    return x;
}

На самом деле у меня есть служебный класс, который использует Generics для "переноса" сеанса, который выполняет всю "грубую работу" за меня, у меня также есть что-то почти идентичное для работы со значениями QueryString .

Это помогает устранить ошибку кода при (часто многочисленных) проверках..

Например:

public class QueryString
{
    static NameValueCollection QS
    {
        get
        {
            if (HttpContext.Current == null)
                throw new ApplicationException("No HttpContext!");

            return HttpContext.Current.Request.QueryString;
        }
    }

    public static int Int(string key)
    {
        int i; 
        if (!int.TryParse(QS[key], out i))
            i = -1; // Obviously Change as you see fit.
        return i;
    }

    // ... Other types omitted.
}

// And to Use..
void Test()
{
    int i = QueryString.Int("test");
}

ПРИМЕЧАНИЕ:

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

Надеюсь, это поможет / даст пищу для размышлений.

У меня есть функции для каждого (на самом деле это один небольшой класс с большим количеством статики):

  • GetIntegerFromQuerystring(val)
  • GetIntegerFromPost(val)
  • ....

Он возвращает -1 в случае сбоя (что почти всегда нормально для меня, у меня есть и некоторые другие функции для отрицательных чисел).

Dim X as Integer = GetIntegerFromQuerystring("id")
If x = -1 Then Exit Sub

Я изменил ответ Брайана Уоттса так, что если параметр, который вы запрашиваете, не существует, и вы указали тип с нулевым значением, он вернет null :

public static T GetValue<T>(this NameValueCollection collection, string key)
    {
        if (collection == null)
        {
            return default(T);
        }

        var value = collection[key];

        if (value == null)
        {
           return default(T);
        }

        var type = typeof(T);

        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            type = Nullable.GetUnderlyingType(type);
        }

        var converter = TypeDescriptor.GetConverter(type);

        if (!converter.CanConvertTo(value.GetType()))
        {
            return default(T);
        }

        return (T)converter.ConvertTo(value, type);
    }

Теперь вы можете сделать это :

Request.QueryString.GetValue<int?>(paramName) ?? 10;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top