从.NET中的字符串获取url参数


239

我在.NET中有一个字符串,它实际上是一个URL。我想要一种简单的方法来从特定参数获取值。

通常,我只使用Request.Params["theThingIWant"],但是该字符串不是来自请求。我可以这样创建一个新Uri项目:

Uri myUri = new Uri(TheStringUrlIWantMyValueFrom);

我可以使用它myUri.Query来获取查询字符串...但是显然我必须找到某种正则表达式将其拆分。

我是否缺少明显的东西,或者没有创建某种形式的正则表达式的内置方法?

Answers:


494

使用返回ParseQueryStringSystem.Web.HttpUtility类的静态方法NameValueCollection

Uri myUri = new Uri("http://www.example.com?param1=good&param2=bad");
string param1 = HttpUtility.ParseQueryString(myUri.Query).Get("param1");

http://msdn.microsoft.com/zh-cn/library/ms150046.aspx中查看文档


14
这似乎没有检测到第一个参数。例如,解析“ google.com/… ”无法检测到参数q
Andrew Shepherd

@安德鲁我确认。这很奇怪(错误?)。您仍然可以使用HttpUtility.ParseQueryString(myUri.Query).Get(0),它将提取第一个参数。`
Mariusz Pawelski

任何.NET工具来构建参数化查询URL?
Shimmy Weitzhandler 2011年

6
您不能使用HttpUtility.ParseQueryString(string)!解析完整的查询URL 。顾名思义,它是解析查询字符串,而不是带有查询参数的URL。如果要执行此操作,则必须首先按?如下方式将其拆分:Url.Split('?')并使用[0]LINQ的Last()/ 来获取最后一个元素(取决于情况和所需)LastOrDefault()
Kosiek '18年

1
当我自己试用时,签名似乎已更改为:HttpUtility.ParseQueryString(uri.Query).GetValues(“ param1”)。First()
参议员


34

如果出于某种原因您不愿意使用,这是另一种选择HttpUtility.ParseQueryString()

构造它可以容忍“格式错误”的查询字符串,即http://test/test.html?empty=成为具有空值的参数。如果需要,调用者可以验证参数。

public static class UriHelper
{
    public static Dictionary<string, string> DecodeQueryParameters(this Uri uri)
    {
        if (uri == null)
            throw new ArgumentNullException("uri");

        if (uri.Query.Length == 0)
            return new Dictionary<string, string>();

        return uri.Query.TrimStart('?')
                        .Split(new[] { '&', ';' }, StringSplitOptions.RemoveEmptyEntries)
                        .Select(parameter => parameter.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries))
                        .GroupBy(parts => parts[0],
                                 parts => parts.Length > 2 ? string.Join("=", parts, 1, parts.Length - 1) : (parts.Length > 1 ? parts[1] : ""))
                        .ToDictionary(grouping => grouping.Key,
                                      grouping => string.Join(",", grouping));
    }
}

测试

[TestClass]
public class UriHelperTest
{
    [TestMethod]
    public void DecodeQueryParameters()
    {
        DecodeQueryParametersTest("http://test/test.html", new Dictionary<string, string>());
        DecodeQueryParametersTest("http://test/test.html?", new Dictionary<string, string>());
        DecodeQueryParametersTest("http://test/test.html?key=bla/blub.xml", new Dictionary<string, string> { { "key", "bla/blub.xml" } });
        DecodeQueryParametersTest("http://test/test.html?eins=1&zwei=2", new Dictionary<string, string> { { "eins", "1" }, { "zwei", "2" } });
        DecodeQueryParametersTest("http://test/test.html?empty", new Dictionary<string, string> { { "empty", "" } });
        DecodeQueryParametersTest("http://test/test.html?empty=", new Dictionary<string, string> { { "empty", "" } });
        DecodeQueryParametersTest("http://test/test.html?key=1&", new Dictionary<string, string> { { "key", "1" } });
        DecodeQueryParametersTest("http://test/test.html?key=value?&b=c", new Dictionary<string, string> { { "key", "value?" }, { "b", "c" } });
        DecodeQueryParametersTest("http://test/test.html?key=value=what", new Dictionary<string, string> { { "key", "value=what" } });
        DecodeQueryParametersTest("http://www.google.com/search?q=energy+edge&rls=com.microsoft:en-au&ie=UTF-8&oe=UTF-8&startIndex=&startPage=1%22",
            new Dictionary<string, string>
            {
                { "q", "energy+edge" },
                { "rls", "com.microsoft:en-au" },
                { "ie", "UTF-8" },
                { "oe", "UTF-8" },
                { "startIndex", "" },
                { "startPage", "1%22" },
            });
        DecodeQueryParametersTest("http://test/test.html?key=value;key=anotherValue", new Dictionary<string, string> { { "key", "value,anotherValue" } });
    }

    private static void DecodeQueryParametersTest(string uri, Dictionary<string, string> expected)
    {
        Dictionary<string, string> parameters = new Uri(uri).DecodeQueryParameters();
        Assert.AreEqual(expected.Count, parameters.Count, "Wrong parameter count. Uri: {0}", uri);
        foreach (var key in expected.Keys)
        {
            Assert.IsTrue(parameters.ContainsKey(key), "Missing parameter key {0}. Uri: {1}", key, uri);
            Assert.AreEqual(expected[key], parameters[key], "Wrong parameter value for {0}. Uri: {1}", parameters[key], uri);
        }
    }
}

对于无法使用
HttpUtility的

12

@Andrew和@CZFox

我有同样的错误,发现原因实际上是一个参数:http://www.example.com?param1而不是param1是一个期望的参数。

通过删除问号之前和包括的所有字符,可以解决此问题。因此,从本质上讲,该HttpUtility.ParseQueryString函数仅需要一个有效的查询字符串参数,该参数仅在问号后包含字符,如下所示:

HttpUtility.ParseQueryString ( "param1=good&param2=bad" )

我的解决方法:

string RawUrl = "http://www.example.com?param1=good&param2=bad";
int index = RawUrl.IndexOf ( "?" );
if ( index > 0 )
    RawUrl = RawUrl.Substring ( index ).Remove ( 0, 1 );

Uri myUri = new Uri( RawUrl, UriKind.RelativeOrAbsolute);
string param1 = HttpUtility.ParseQueryString( myUri.Query ).Get( "param1" );`

实例化URI时,出现错误“无效的URI:无法确定URI的格式”。我认为此解决方案无法按预期工作。
Paul Matthews

@PaulMatthews,你是对的。在给出此解决方案时,我使用的是较旧的.net Framework 2.0。为了确认您的陈述,我将这个解决方案复制并粘贴到Joseph Albahara的LINQPad v2中,并收到与您提到的相同的错误。
Mo Gauvin

@PaulMatthews,要修复,请删除以下行:Uri myUri = new Uri(RawUrl); 并仅将RawUrl传递到最后一条语句,如下所示:string param1 = HttpUtility.ParseQueryString(RawUrl).Get(“ param2”);
Mo Gauvin

是的,名称和文档中仅解析查询字符串部分。这不是错误。我什至不知道他们怎么能使它更清晰。ParseQueryString解析查询字符串。
PandaWood

12

看起来您应该循环遍历的值myUri.Query并从那里解析它。

 string desiredValue;
 foreach(string item in myUri.Query.Split('&'))
 {
     string[] parts = item.Replace("?", "").Split('=');
     if(parts[0] == "desiredKey")
     {
         desiredValue = parts[1];
         break;
     }
 }

但是,如果不对一堆格式错误的URL进行测试,我将不会使用此代码。它可能会中断以下所有/全部:

  • hello.html?
  • hello.html?valuelesskey
  • hello.html?key=value=hi
  • hello.html?hi=value?&b=c
  • 等等

4

您也可以使用以下变通办法使其与第一个参数一起使用:

var param1 =
    HttpUtility.ParseQueryString(url.Substring(
        new []{0, url.IndexOf('?')}.Max()
    )).Get("param1");

2

使用.NET反射来观看FillFromString的方法System.Web.HttpValueCollection。这样就为您提供了ASP.NET用于填充Request.QueryString集合的代码。


1

或者,如果您不知道网址(为避免硬编码,请使用 AbsoluteUri

例子...

        //get the full URL
        Uri myUri = new Uri(Request.Url.AbsoluteUri);
        //get any parameters
        string strStatus = HttpUtility.ParseQueryString(myUri.Query).Get("status");
        string strMsg = HttpUtility.ParseQueryString(myUri.Query).Get("message");
        switch (strStatus.ToUpper())
        {
            case "OK":
                webMessageBox.Show("EMAILS SENT!");
                break;
            case "ER":
                webMessageBox.Show("EMAILS SENT, BUT ... " + strMsg);
                break;
        }

0

如果要在默认页面上获取QueryString。默认页面表示当前页面的url。您可以尝试以下代码:

string paramIl = HttpUtility.ParseQueryString(this.ClientQueryString).Get("city");

0

这实际上非常简单,对我有用:)

        if (id == "DK")
        {
            string longurl = "selectServer.aspx?country=";
            var uriBuilder = new UriBuilder(longurl);
            var query = HttpUtility.ParseQueryString(uriBuilder.Query);
            query["country"] = "DK";

            uriBuilder.Query = query.ToString();
            longurl = uriBuilder.ToString();
        } 

0

对于任何想要遍历字符串中所有查询字符串的人

        foreach (var item in new Uri(urlString).Query.TrimStart('?').Split('&'))
        {
            var subStrings = item.Split('=');

            var key = subStrings[0];
            var value = subStrings[1];

            // do something with values
        }


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.