2009-03-02 16 views
21

Jestem ciekawy, co każdy robi dla obsługi/abstrakcji QueryString w ASP.NET. W niektórych naszych aplikacjach internetowych widzę wiele tego na całej witrynie:Konwersja/uzyskiwanie wartości zapytania w ASP.NET

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

Jakie są lepsze sposoby na radzenie sobie z tą brutalnością?

Odpowiedz

24

Ja lubię pomysł abstrakcji ich jako właściwości. Na przykład:

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

Można dodać więcej walidację jeśli chciał. Ale w ten sposób lubię owijać wszystkie moje zmienne łańcucha zapytania.

EDYCJA: --- Również jako kolejny plakat wskazał, że musisz utworzyć te właściwości na każdej stronie. Moja odpowiedź brzmi: nie, nie. Możesz utworzyć te właściwości w jednej klasie, którą możesz nazwać "QueryStrings" lub coś podobnego. Następnie można instancję tej klasy w każdej stronie, na której chcesz uzyskać dostęp do ciągów zapytań, to możesz po prostu zrobić coś jak

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

ten sposób można upakować wszystkie logiki dostępu i obsługi każdego typu zmiennej zapytania w jednej możliwej do utrzymania lokalizacji.

EDIT2: --- EDIT2: --- A ponieważ jest to instancja klasy, można również użyć iniekcji zależności, aby wstrzyknąć klasę QueryStrings w każdym miejscu, w którym ją używasz. StructureMap dobrze sobie z tym radzi. Umożliwia to również makiety klasy QueryStrings i wstrzykiwanie jej, jeśli chcesz przeprowadzić automatyczne testy jednostkowe. O wiele łatwiej jest to udowodnić niż obiekt Request ASP.Net.

+0

Dodatkową zaletą jest to, że mówi przyszłym programistom dokładnie to, czego można oczekiwać od ciągu zapytania, gdy po raz pierwszy usiądzie z kodem. –

+0

Tak, dziękuję, że to zauważyłeś. To zdecydowanie jest intencja. – 7wp

+0

+1 - świetny sposób na poradzenie sobie z nim – nailitdown

8

Jedną z rzeczy jest to, że nie przechwytujesz tu pustych wartości. Możesz mieć adres URL typu "http://example.com?someKey=&anotherKey=12345" iw tym przypadku wartość parametru "someKey" to "" (puste). Możesz użyć string.IsNullOrEmpty(), aby sprawdzić stan pusty i pusty.

Zmienilabym również "someKey", aby była przechowywana w zmiennej. W ten sposób nie powtarzasz literalnych ciągów w wielu miejscach. Ułatwia to utrzymanie.

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

Mam nadzieję, że to pomoże!

Ian

+0

To prawdopodobnie rzuci wyjątek! –

+0

z pewnością chcesz uwzględnić obsługę błędów. To prawda, prawda? :) –

+0

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

3

Napisz jakąś metodę pomocnika (biblioteka), aby go obsługiwać ...

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

lub coś wzdłuż tych linii ...

+0

Ale programista musiałby znać oczekiwany typ łańcucha zapytania, który powinien zostać zwrócony jako. (Aby dowiedzieć się, do której funkcji należy wywołać) Jeśli otoczysz ją za pomocą gettera właściwości, tak jak w udzielonej odpowiedzi, to wszystko, co musisz wiedzieć, to nazwa właściwości, której szukasz. Intellisense zrobi resztę. – 7wp

+0

Tak, tak jak programista musiałby znać oczekiwany typ ciągu zapytania, aby ustawić właściwość. Moim rozwiązaniem jest zatrzymanie powtarzających się obrzydliwych wypowiedzi "jeśli" w całym serialu, jak opisano w pytaniu. To, co robią z kodem po tym, zależy od nich - hej, włóż to do nieruchomości! – Charlino

+0

, ale po ustawieniu nieruchomości, to jest zrobione.inni programiści, którzy przyjdą po to, nie będą musieli odgadnąć, jakie dane znajdują się w ciągu zapytania i jaka konkretna walidacja powinna nastąpić. możesz zawinąć to wszystko w nieruchomości. – 7wp

1

używaliśmy stałe zachować wszystkie te „luźne” klucze w centralnej lokalizacji:

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

w ten sposób można łatwo uzyskać dostęp do stałych musisz z:

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

Jestem z plakatem, który zasugerował metody pomocnicze (chciałbym wypowiedzieć się na jego temat, ale nie może jeszcze). Ktoś inny nie zgodził się z nim na rzecz tworzenia właściwości, ale moja odpowiedź brzmi, że nie radzi sobie z problemem sprawdzania wartości zerowych lub nieprawidłowego formatowania itp. Jeśli masz metody pomocnicze, całą tę logikę można zapisać raz i scentralizowany.

Jeśli masz dużo stron, dodawanie właściwości dla każdego może być bardziej czasochłonne, niż jest warte. Ale to oczywiście tylko preferencja, więc każdemu z nich.

Jedną z fajniejszych rzeczy, które można poprawić na podstawie metody pomocniczej drugiego plakatu, jest ustawienie parametru wyjściowego zamiast tego (zmiana na ref). W ten sposób możesz ustawić domyślną wartość właściwości, na wypadek gdyby nie została przekazana. Czasem możesz potrzebować opcjonalnych parametrów, na przykład - wtedy możesz zacząć od pewnej wartości domyślnej dla tych przypadków, w których parametr opcjonalny nie jest jawnie przekazywany (łatwiejsze niż posiadanie wartości domyślnej przekazywanej osobno). Można nawet dodać parametr boolowski IsRequired na końcu i wywołać wyjątek, jeśli wartość bool ma wartość true, a parametr nie zostanie przekazany. To może być pomocne w wielu przypadkach.

+0

Nie musisz tworzyć właściwości na każdej stronie. Tylko jedna klasa zawierająca wszystkie właściwości, których oczekujesz. Następnie możesz utworzyć instancję tej klasy na stronach, z których korzystasz, aby uzyskać dostęp do parametrów zapytania. – 7wp

+0

Zakłada się, że na każdej stronie są jednak takie same parametry zapytania. W dużym systemie będziesz mieć ogromną liczbę różnych, tak jak masz różne parametry do różnych metod. Wygląda na to, że konsystencja to dobra rzecz. – x4000

3

Oto, co wymyśliłem. Wykorzystuje rodzajowych zwrócić silnie wpisany wartość z QueryString lub opcjonalną wartość domyślną, jeśli parametr nie jest w 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)); 
    } 

Od pisania tego posta pisałem bardzo małą bibliotekę klas do manipulowania wartości kwerendy - zobacz https://github.com/DanDiplo/QueryString-Helper

+0

+1 za przyjemne proste użycie leków generycznych. – GFoley83

+0

Uzyskiwanie: 'Łańcuch typu 'musi być niedozwolonym wartością typu, aby użyć go jako parametru' T 'w typowym ...' –

+0

@PierreLebon Struny są typami wartości, więc strukturalne ograniczenie strukturalne nie będzie z nimi. Ale nie musisz ich konwertować, ponieważ wartość jest już ciągiem. Od tego postu napisałem małą bibliotekę - patrz https://github.com/DanDiplo/QueryString-Helper - która powinna ci pomóc. –

1

Według mnie, najlepszym sposobem, aby uzyskać wartość ciągu kwerendy jest jak następuje:
Jeśli querystring nie zostanie znaleziony, to wartość val będzie 0.

int val = 0; 
int.TryParse(Request.QueryString["someKey"], out val); 
Powiązane problemy