【问题标题】:C# ASP.NET QueryString parserC# ASP.NET QueryString 解析器
【发布时间】:2009-02-22 12:45:30
【问题描述】:

如果您一直在寻找一种简洁明了的方式来解析您的查询字符串值,我想出了这个:

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

我一直都想拥有这样的东西,最后做对了……至少我是这么认为的……

代码应该是不言自明的......

感谢任何改进它的 cmets 或建议。

【问题讨论】:

  • 也许您在代码堆栈中较早处理它,但请记住,查询字符串中的键可以有多个值,即 x=1,2,3
  • @jro 我会认为多值大小写是无效的,因为就查询字符串而言,它只有一个值,一个字符串“1,2,3”,解析它就像其他任何东西一样不正确。

标签: c# asp.net query-string


【解决方案1】:

一种简单的解析方式(如果你不想进行类型转换)是

 HttpUtility.ParseQueryString(queryString);

您可以从 URL 中提取查询字符串

 new Uri(url).Query

【讨论】:

  • 这仅在 url 是完整 url 时有效。如果有相对 url,则不支持 Uri 的 Query 成员。
【解决方案2】:

鉴于您只处理三种不同的类型,我建议改为使用三种不同的方法 - 泛型方法最好适用于类型约束允许的每个类型参数。

此外,我强烈建议您为 intDateTime 指定要使用的文化 - 它不应该真正取决于服务器恰好所处的文化。(如果您有代码猜测用户的文化,你可以改用它。)最后,我还建议支持一组明确指定的DateTime 格式,而不是TryParse 默认支持的任何格式。 (我几乎总是使用ParseExact/TryParseExact 而不是Parse/TryParse。)

请注意,字符串版本实际上不需要做任何事情,因为value 已经是一个字符串(尽管您当前的代码将“”转换为null,这可能是也可能不是您想要的)。

【讨论】:

  • +1 用于 ParseExact/TryParseExact,尤其是因为您可以传递格式数组。
【解决方案3】:

我编写了以下方法来将 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 将为 false,int productId 将等于 0。

对于?noProductId=notIncluded 的查询字符串,bool 将为 false,int productId 将等于 0。

【讨论】:

    【解决方案4】:

    在我的应用程序中,我一直在使用以下功能:-

    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?));
    

    【讨论】:

      【解决方案5】:

      这是一个旧答案,但我做了以下事情:

                  string queryString = relayState.Split("?").ElementAt(1);
                  NameValueCollection nvc = HttpUtility.ParseQueryString(queryString);
      

      【讨论】:

        【解决方案6】:

        在我看来,您正在进行很多不必要的类型转换。 tempValue 变量是您尝试返回的类型的前导。同样在字符串的情况下,值已经是一个字符串,所以只需返回它。

        【讨论】:

          【解决方案7】:

          基于Ronalds answer,我更新了自己的查询字符串解析方法。我使用它的方式是将它作为扩展方法添加到 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", "/");
          }
          

          然后我可以编写我的其余代码并依赖查询字符串项的存在和正确格式,因此我不必在每次想要访问它时都对其进行测试。

          注意:如果您使用的是 .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();
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-12-25
            • 2012-01-28
            • 1970-01-01
            • 1970-01-01
            • 2022-10-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多