如何在WP7中拆分URI?

时间:2012-06-07 16:50:27

标签: c# silverlight windows-phone-7 query-string

是否有一种方法可以在WebBrowser控件中访问Query参数,还是我们必须手动拆分字符串?例如:

http://www.mysite.com?paramter=12345

我只需要访问参数的值。我知道在使用xaml页面时我们有QueryString属性。使用网页有类似的东西吗?

4 个答案:

答案 0 :(得分:5)

我不记得我在哪里得到这个,可能是这样。

 public static class UriExtensions
    {
        private static readonly Regex QueryStringRegex = new Regex(@"[\?&](?<name>[^&=]+)=(?<value>[^&=]+)");

        public static IEnumerable<KeyValuePair<string, string>> ParseQueryString(this Uri uri)
        {
            if (uri == null)
                throw new ArgumentException("uri");

            var matches = QueryStringRegex.Matches(uri.OriginalString);
            for (var i = 0; i < matches.Count; i++)
            {
                var match = matches[i];
                yield return new KeyValuePair<string, string>(match.Groups["name"].Value, match.Groups["value"].Value);
            }
        }
    }

答案 1 :(得分:2)

其他答案的一些重要优化:

  • 在Uri中处理
  • 在Uri
  • 中处理可能的缺失值,例如&amp; name =
  • 不要忘记Uri.UnescapeDataString
  • 返回Dictionary而不是IEnumerable,以便轻松找到所需参数
  • 解释Uri.Query在WP7上不可靠
  • 比较速度以获得最佳解决方案

使用正则表达式(比分割慢):

static readonly Regex QueryStringRegex1 = new Regex(@"^[^#]*\?([^#]*)");
static readonly Regex QueryStringRegex2 = new Regex(@"(?<name>[^&=]+)=(?<value>[^&=]*)");
public static Dictionary<string, string> QueryDictionary(this Uri uri)
{
    return QueryStringRegex1.Match(uri.ToString())// between ? and #
        .Groups
        .Cast<Group>()
        .Select(a => QueryStringRegex2.Matches(a.Value)// between ? and &
            .Cast<Match>()
            .Select(b => b.Groups)
            .ToDictionary(b => Uri.UnescapeDataString(b["name"].Value), b => Uri.UnescapeDataString(b["value"].Value)))
        .ElementAtOrDefault(1)
        ?? new Dictionary<string, string>();
}

使用Split(比Regex 更快,推荐的解决方案):

static readonly char[] QueryStringSeparator1 = "#".ToCharArray();
static readonly char[] QueryStringSeparator2 = "?".ToCharArray();
static readonly char[] QueryStringSeparator3 = "&".ToCharArray();
static readonly char[] QueryStringSeparator4 = "=".ToCharArray();
public static Dictionary<string, string> QueryDictionary(this Uri uri)
{
    return uri.ToString()
        .Split(QueryStringSeparator1, StringSplitOptions.RemoveEmptyEntries)
        .Select(a => a.Split(QueryStringSeparator2, StringSplitOptions.RemoveEmptyEntries)
            .Select(b => b.Split(QueryStringSeparator3, StringSplitOptions.RemoveEmptyEntries)
                .Select(c => c.Split(QueryStringSeparator4))
                .Where(c => c[0].Length > 0)
                .ToDictionary(c => Uri.UnescapeDataString(c[0]), c => c.Length > 1 ? Uri.UnescapeDataString(c[1]) : ""))
            .ElementAtOrDefault(1))// after ?
        .FirstOrDefault()// before #
        ?? new Dictionary<string, string>();
}

注意:在Windows Phone 7设备上,对于像“mailto:a@example.com?subject = subject&amp; body = body”这样的Uri,Uri.Query 不可靠。这就是我们使用Uri.ToString()(本身优于Uri.OriginalString)的原因。如果您只想处理“(http | https)://”或者想要针对Windows Phone 8设备进行优化,则可以在https://stackoverflow.com/a/25167971/1033581上找到优化的解决方案。

如果您希望使用Windows Phone 7应用在Windows Phone 8设备上进行Uri.Query优化,可以事先检查:

public static readonly bool IsVersion8 = Environment.OSVersion.Version >= new Version(8, 0);

答案 2 :(得分:1)

除非别人有其他办法,否则我可以手动完成同样的事情:

// The url looked something like this http://www.mysite.com?param1=value&param2=value
var parameterValue = e.Uri.Query.Split('&')
            .Where(s => s.Split('=')[0] == "param2")
            .Select(s => s.Split('=')[1])
            .FirstOrDefault();

我不认为这种方式,我只是想知道是否有这种类型的解析的内置方法,因为我知道它存在于ASP.NET,.NET等

答案 3 :(得分:0)

灵感来自similar question

的答案
public static Dictionary<string, string> ParseQueryString(Uri uri)
{
    var substring = uri.Query;
    if (substring.Length > 0)
         substring.Substring(1);

    var pairs = substring.Split('&'); 
    var output = new Dictionary<string, string>(pairs.Length);

    foreach (string piece in pairs)
    {
        var pair = piece.Split('=');
        output.Add(
            Uri.UnescapeDataString(pair[0]),
            Uri.UnescapeDataString(pair[1]));
    }

    return output;
}