Как вы проверяете свой запрос.Переменные QueryString []?
Я часто использую 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[]
s?
11 ответов
Ниже приведен метод расширения, который позволит вам написать такой код:
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.TryParse вместо этого, чтобы избавиться от блока 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.Вместо этого метод tryparse...
int id;
if (!int.TryParse(Request.QueryString["id"], out id))
{
id = -1;
}
это предполагает, что "нет" должно иметь тот же результат, что и "не целое число", конечно.
EDIT: в других случаях, когда вы все равно собираетесь использовать параметры запроса в качестве строк, я думаю, что это определенно хорошая идея проверить, что они присутствуют.
вы можете использовать методы расширения ниже, а также и сделать, как это
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;
}
Eeee это риск кармы...
У меня есть сухая блок-тестируемая абстракция, потому что, ну, потому что было слишком много переменных 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;
}
У меня на самом деле есть класс утилиты, который использует дженерики для "обертывания" сеанса, который выполняет всю "работу grunt" для меня, у меня также есть что-то почти идентичное для работы со значениями QueryString.
Это помогает удалить код dupe для (часто многочисленных) проверок..
например:
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
Я изменил ответ Брайана Уоттса, чтобы, если параметр вашего запроса не существует, и вы указали тип nullable, он вернет 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;