3

Is there a method for accesing Query parameters in the WebBrowser control or do we have to manually break apart the string? For example:

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

I simply need to access the value of parameter. I know when working with xaml pages we have the have the QueryString property. Is there something similar for working with web pages?

4

4 回答 4

5

I can't remember where I got this, possibly SO.

 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);
            }
        }
    }
于 2012-06-07T19:13:44.203 回答
2

Some important optimizations from other answers:

  • handling a # in the Uri
  • handling possible missing value like &name= in the Uri
  • not forgetting Uri.UnescapeDataString
  • returning a Dictionary instead of a IEnumerable so one can find a desired parameter easily
  • explaining that Uri.Query is unreliable on WP7
  • comparing speed for best solution

With Regex (slower than Split):

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

With Split (faster than Regex, recommended solution):

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

Note: on a Windows Phone 7 device, Uri.Query is unreliable for an Uri like "mailto:a@example.com?subject=subject&body=body". That's why we use Uri.ToString() (itself better than Uri.OriginalString). If you only want to handle "(http|https)://" or you want to optimize for a Windows Phone 8 device, you can find an optimized solution on https://stackoverflow.com/a/25167971/1033581.

If you want this Uri.Query optimization on a Windows Phone 8 device using a Windows Phone 7 app, you can check beforehand:

public static readonly bool IsVersion8 = Environment.OSVersion.Version >= new Version(8, 0);
于 2014-08-06T15:57:35.890 回答
1

Unless someone else has another way of doing it, I was able to accomplish the same thing manually:

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

I don't think this way is bad, I was just wondering if there was a built in method for this type of parsing because I know it existed in ASP.NET, .NET , etc.

于 2012-06-07T18:28:04.700 回答
0

Inspired on the answer of a 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;
}
于 2013-08-28T04:56:36.030 回答