C # ASP.NET QueryString парсер - PullRequest
       23

C # ASP.NET QueryString парсер

7 голосов
/ 22 февраля 2009

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

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

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

Код должен быть понятен ...

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

Ответы [ 7 ]

34 голосов
/ 03 сентября 2009

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

 HttpUtility.ParseQueryString(queryString);

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

 new Uri(url).Query
5 голосов
/ 22 февраля 2009

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

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

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

3 голосов
/ 17 декабря 2009

Я написал следующий метод для анализа 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=5 значение bool будет истинным, а int productId будет равно 5.

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

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

2 голосов
/ 05 сентября 2012

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

            string queryString = relayState.Split("?").ElementAt(1);
            NameValueCollection nvc = HttpUtility.ParseQueryString(queryString);
2 голосов
/ 22 февраля 2009

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

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?));
1 голос
/ 22 февраля 2009

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

0 голосов
/ 06 мая 2011

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

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

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

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

Примечание. Если вы используете pre .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();
    }
}
...