NameValueCollection 到 URL 查询?

发布于 2024-09-26 08:41:05 字数 195 浏览 4 评论 0原文

我知道我可以做到这一点

var nv = HttpUtility.ParseQueryString(req.RawUrl);

,但是有没有办法将其转换回网址?

var newUrl = HttpUtility.Something("/page", nv);

I know i can do this

var nv = HttpUtility.ParseQueryString(req.RawUrl);

But is there a way to convert this back to a url?

var newUrl = HttpUtility.Something("/page", nv);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

浊酒尽余欢 2024-10-03 08:41:05

只需在 NameValueCollection 上调用 ToString() 即可以 name1=value1&name2=value2 查询字符串就绪格式返回名称值对。请注意,NameValueCollection 类型实际上并不支持这一点,并且建议这样做会产生误导,但由于实际返回的内部类型,该行为在这里起作用,如下所述。

感谢 @mjwills 指出 HttpUtility.ParseQueryString 方法实际上返回一个内部 HttpValueCollection 对象,而不是常规 NameValueCollection (尽管文档指定了 NameValueCollection )。使用 ToString() 时,HttpValueCollection 自动对查询字符串进行编码,因此无需编写循环遍历集合并使用 UrlEncode 的例程方法。期望的结果已经返回。

有了结果,您就可以将其附加到 URL 并重定向:

var nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString());
string url = Request.Url.AbsolutePath + "?" + nameValues.ToString();
Response.Redirect(url);

目前使用 HttpValueCollection 的唯一方法是使用上面显示的 ParseQueryString 方法(除了当然是反思)。自从 请求公开此类的连接问题 已关闭,状态为“无法修复”。

顺便说一句,您可以调用 nameValues 上的 AddSetRemove 方法来修改任何在附加查询字符串项目之前。如果您对此感兴趣请参阅我对另一个问题的回复

Simply calling ToString() on the NameValueCollection will return the name value pairs in a name1=value1&name2=value2 querystring ready format. Note that NameValueCollection types don't actually support this and it's misleading to suggest this, but the behavior works here due to the internal type that's actually returned, as explained below.

Thanks to @mjwills for pointing out that the HttpUtility.ParseQueryString method actually returns an internal HttpValueCollection object rather than a regular NameValueCollection (despite the documentation specifying NameValueCollection). The HttpValueCollection automatically encodes the querystring when using ToString(), so there's no need to write a routine that loops through the collection and uses the UrlEncode method. The desired result is already returned.

With the result in hand, you can then append it to the URL and redirect:

var nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString());
string url = Request.Url.AbsolutePath + "?" + nameValues.ToString();
Response.Redirect(url);

Currently the only way to use a HttpValueCollection is by using the ParseQueryString method shown above (other than reflection, of course). It looks like this won't change since the Connect issue requesting this class be made public has been closed with a status of "won't fix."

As an aside, you can call the Add, Set, and Remove methods on nameValues to modify any of the querystring items before appending it. If you're interested in that see my response to another question.

长梦不多时 2024-10-03 08:41:05
string q = String.Join("&",
             nvc.AllKeys.Select(a => a + "=" + HttpUtility.UrlEncode(nvc[a])));
string q = String.Join("&",
             nvc.AllKeys.Select(a => a + "=" + HttpUtility.UrlEncode(nvc[a])));
是你 2024-10-03 08:41:05

创建一个使用几个循环的扩展方法。我更喜欢这个解决方案,因为它可读(无 linq),不需要 System.Web.HttpUtility,并且它支持重复键。

public static string ToQueryString(this NameValueCollection nvc)
{
    if (nvc == null) return string.Empty;

    StringBuilder sb = new StringBuilder();

    foreach (string key in nvc.Keys)
    {
        if (string.IsNullOrWhiteSpace(key)) continue;

        string[] values = nvc.GetValues(key);
        if (values == null) continue;

        foreach (string value in values)
        {
            sb.Append(sb.Length == 0 ? "?" : "&");
            sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(value));
        }
    }

    return sb.ToString();
}

示例

var queryParams = new NameValueCollection()
{
    { "order_id", "0000" },
    { "item_id", "1111" },
    { "item_id", "2222" },
    { null, "skip entry with null key" },
    { "needs escaping", "special chars ? = &" },
    { "skip entry with null value", null }
};

Console.WriteLine(queryParams.ToQueryString());

输出

?order_id=0000&item_id=1111&item_id=2222&needs%20escaping=special%20chars%20%3F%20%3D%20%26

Make an extension method that uses a couple of loops. I prefer this solution because it's readable (no linq), doesn't require System.Web.HttpUtility, and it supports duplicate keys.

public static string ToQueryString(this NameValueCollection nvc)
{
    if (nvc == null) return string.Empty;

    StringBuilder sb = new StringBuilder();

    foreach (string key in nvc.Keys)
    {
        if (string.IsNullOrWhiteSpace(key)) continue;

        string[] values = nvc.GetValues(key);
        if (values == null) continue;

        foreach (string value in values)
        {
            sb.Append(sb.Length == 0 ? "?" : "&");
            sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(value));
        }
    }

    return sb.ToString();
}

Example

var queryParams = new NameValueCollection()
{
    { "order_id", "0000" },
    { "item_id", "1111" },
    { "item_id", "2222" },
    { null, "skip entry with null key" },
    { "needs escaping", "special chars ? = &" },
    { "skip entry with null value", null }
};

Console.WriteLine(queryParams.ToQueryString());

Output

?order_id=0000&item_id=1111&item_id=2222&needs%20escaping=special%20chars%20%3F%20%3D%20%26
你是暖光i 2024-10-03 08:41:05

这应该不需要太多代码即可工作:

NameValueCollection nameValues = HttpUtility.ParseQueryString(String.Empty);
nameValues.Add(Request.QueryString);
// modify nameValues if desired
var newUrl = "/page?" + nameValues;

其想法是使用 HttpUtility.ParseQueryString 生成类型为 HttpValueCollection 的空集合。此类是 NameValueCollection 的子类,被标记为 internal,因此您的代码无法轻松创建它的实例。

HttpValueCollection 的好处是 ToString 方法会为您处理编码。通过利用 NameValueCollection.Add(NameValueCollection) 方法,您可以将现有查询字符串参数添加到新创建的对象中,而无需先将 Request.QueryString 集合转换为url 编码的字符串,然后将其解析回集合中。

该技术也可以作为扩展方法公开:

public static string ToQueryString(this NameValueCollection nameValueCollection)
{
    NameValueCollection httpValueCollection = HttpUtility.ParseQueryString(String.Empty);
    httpValueCollection.Add(nameValueCollection);
    return httpValueCollection.ToString();
}

This should work without too much code:

NameValueCollection nameValues = HttpUtility.ParseQueryString(String.Empty);
nameValues.Add(Request.QueryString);
// modify nameValues if desired
var newUrl = "/page?" + nameValues;

The idea is to use HttpUtility.ParseQueryString to generate an empty collection of type HttpValueCollection. This class is a subclass of NameValueCollection that is marked as internal so that your code cannot easily create an instance of it.

The nice thing about HttpValueCollection is that the ToString method takes care of the encoding for you. By leveraging the NameValueCollection.Add(NameValueCollection) method, you can add the existing query string parameters to your newly created object without having to first convert the Request.QueryString collection into a url-encoded string, then parsing it back into a collection.

This technique can be exposed as an extension method as well:

public static string ToQueryString(this NameValueCollection nameValueCollection)
{
    NameValueCollection httpValueCollection = HttpUtility.ParseQueryString(String.Empty);
    httpValueCollection.Add(nameValueCollection);
    return httpValueCollection.ToString();
}
_畞蕅 2024-10-03 08:41:05

实际上,您也应该对键进行编码,而不仅仅是值。

string q = String.Join("&",
nvc.AllKeys.Select(a => $"{HttpUtility.UrlEncode(a)}={HttpUtility.UrlEncode(nvc[a])}"));

Actually, you should encode the key too, not just value.

string q = String.Join("&",
nvc.AllKeys.Select(a => $"{HttpUtility.UrlEncode(a)}={HttpUtility.UrlEncode(nvc[a])}"));
独木成林 2024-10-03 08:41:05

由于 NameValueCollection 同一键可以有多个值,因此如果您关心查询字符串的格式(因为它将作为逗号分隔值而不是“数组表示法”返回),您可以考虑下列。

示例

var nvc = new NameValueCollection();
nvc.Add("key1", "val1");
nvc.Add("key2", "val2");
nvc.Add("empty", null);
nvc.Add("key2", "val2b");

变为:key1=val1&key2[]=val2&empty&key2[]=val2b 而不是 key1=val1&key2=val2,val2b&empty

代码

string qs = string.Join("&", 
    // "loop" the keys
    nvc.AllKeys.SelectMany(k => {
        // "loop" the values
        var values = nvc.GetValues(k);
        if(values == null) return new[]{ k };
        return nvc.GetValues(k).Select( (v,i) => 
            // 'gracefully' handle formatting
            // when there's 1 or more values
            string.Format(
                values.Length > 1
                    // pick your array format: k[i]=v or k[]=v, etc
                    ? "{0}[]={1}"
                    : "{0}={1}"
                , k, HttpUtility.UrlEncode(v), i)
        );
    })
);

或者如果你不太喜欢 Linq...

string qs = nvc.ToQueryString(); // using...

public static class UrlExtensions {
    public static string ToQueryString(this NameValueCollection nvc) {
        return string.Join("&", nvc.GetUrlList());
    }

    public static IEnumerable<string> GetUrlList(this NameValueCollection nvc) {
        foreach(var k in nvc.AllKeys) {
            var values = nvc.GetValues(k);
            if(values == null)  { yield return k; continue; }
            for(int i = 0; i < values.Length; i++) {
                yield return
                // 'gracefully' handle formatting
                // when there's 1 or more values
                string.Format(
                    values.Length > 1
                        // pick your array format: k[i]=v or k[]=v, etc
                        ? "{0}[]={1}"
                        : "{0}={1}"
                    , k, HttpUtility.UrlEncode(values[i]), i);
            }
        }
    }
}

正如评论中已经指出的那样,除了 这个答案< /a> 大多数其他答案都解决了这种情况(Request.QueryString 是一个 HttpValueCollection,“不是”NameValueCollection),而不是文字问题。

更新:解决了评论中的空值问题。

Because a NameValueCollection can have multiple values for the same key, if you are concerned with the format of the querystring (since it will be returned as comma-separated values rather than "array notation") you may consider the following.

Example

var nvc = new NameValueCollection();
nvc.Add("key1", "val1");
nvc.Add("key2", "val2");
nvc.Add("empty", null);
nvc.Add("key2", "val2b");

Turn into: key1=val1&key2[]=val2&empty&key2[]=val2b rather than key1=val1&key2=val2,val2b&empty.

Code

string qs = string.Join("&", 
    // "loop" the keys
    nvc.AllKeys.SelectMany(k => {
        // "loop" the values
        var values = nvc.GetValues(k);
        if(values == null) return new[]{ k };
        return nvc.GetValues(k).Select( (v,i) => 
            // 'gracefully' handle formatting
            // when there's 1 or more values
            string.Format(
                values.Length > 1
                    // pick your array format: k[i]=v or k[]=v, etc
                    ? "{0}[]={1}"
                    : "{0}={1}"
                , k, HttpUtility.UrlEncode(v), i)
        );
    })
);

or if you don't like Linq so much...

string qs = nvc.ToQueryString(); // using...

public static class UrlExtensions {
    public static string ToQueryString(this NameValueCollection nvc) {
        return string.Join("&", nvc.GetUrlList());
    }

    public static IEnumerable<string> GetUrlList(this NameValueCollection nvc) {
        foreach(var k in nvc.AllKeys) {
            var values = nvc.GetValues(k);
            if(values == null)  { yield return k; continue; }
            for(int i = 0; i < values.Length; i++) {
                yield return
                // 'gracefully' handle formatting
                // when there's 1 or more values
                string.Format(
                    values.Length > 1
                        // pick your array format: k[i]=v or k[]=v, etc
                        ? "{0}[]={1}"
                        : "{0}={1}"
                    , k, HttpUtility.UrlEncode(values[i]), i);
            }
        }
    }
}

As has been pointed out in comments already, with the exception of this answer most of the other answers address the scenario (Request.QueryString is an HttpValueCollection, "not" a NameValueCollection) rather than the literal question.

Update: addressed null value issue from comment.

捶死心动 2024-10-03 08:41:05

简短的答案是在 NameValueCollection 上使用 .ToString() 并将其与原始 url 结合起来。

不过,我想指出一些事情:

您不能在 Request.RawUrl 上使用 HttpUtility.ParseQueryStringParseQueryString() 方法正在查找如下所示的值:?var=value&var2=value2

如果您想获取 QueryString 参数的 NameValueCollection,只需使用 Request.QueryString()

var nv = Request.QueryString;

要重建 URL,只需使用 nv.ToString()。

string url = String.Format("{0}?{1}", Request.Path, nv.ToString());

如果您尝试解析 url 字符串而不是使用 Request 对象,请使用 UriHttpUtility.ParseQueryString 方法。

Uri uri = new Uri("<THE URL>");
var nv = HttpUtility.ParseQueryString(uri.Query);
string url = String.Format("{0}?{1}", uri.AbsolutePath, nv.ToString());

The short answer is to use .ToString() on the NameValueCollection and combine it with the original url.

However, I'd like to point out a few things:

You cant use HttpUtility.ParseQueryString on Request.RawUrl. The ParseQueryString() method is looking for a value like this: ?var=value&var2=value2.

If you want to get a NameValueCollection of the QueryString parameters just use Request.QueryString().

var nv = Request.QueryString;

To rebuild the URL just use nv.ToString().

string url = String.Format("{0}?{1}", Request.Path, nv.ToString());

If you are trying to parse a url string instead of using the Request object use Uri and the HttpUtility.ParseQueryString method.

Uri uri = new Uri("<THE URL>");
var nv = HttpUtility.ParseQueryString(uri.Query);
string url = String.Format("{0}?{1}", uri.AbsolutePath, nv.ToString());
ま柒月 2024-10-03 08:41:05

我总是使用 UriBuilder 将带有查询字符串的 url 转换回有效且正确编码的 url。

var url = "http://my-link.com?foo=bar";

var uriBuilder = new UriBuilder(url);
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
query.Add("yep", "foo&bar");

uriBuilder.Query = query.ToString();
var result = uriBuilder.ToString();

// http://my-link.com:80/?foo=bar&yep=foo%26bar

I always use UriBuilder to convert an url with a querystring back to a valid and properly encoded url.

var url = "http://my-link.com?foo=bar";

var uriBuilder = new UriBuilder(url);
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
query.Add("yep", "foo&bar");

uriBuilder.Query = query.ToString();
var result = uriBuilder.ToString();

// http://my-link.com:80/?foo=bar&yep=foo%26bar
没有伤那来痛 2024-10-03 08:41:05

在 AspNet Core 2.0 中,您可以使用 QueryHelpers AddQueryString 方法。

In AspNet Core 2.0 you can use QueryHelpers AddQueryString method.

何以笙箫默 2024-10-03 08:41:05

正如 @Atchitutchuk 建议的那样,您可以在 ASP.NET Core 中使用 QueryHelpers.AddQueryString:

    public string FormatParameters(NameValueCollection parameters)
    {
        var queryString = "";
        foreach (var key in parameters.AllKeys)
        {
            foreach (var value in parameters.GetValues(key))
            {
                queryString = QueryHelpers.AddQueryString(queryString, key, value);
            }
        };

        return queryString.TrimStart('?');
    }

As @Atchitutchuk suggested, you can use QueryHelpers.AddQueryString in ASP.NET Core:

    public string FormatParameters(NameValueCollection parameters)
    {
        var queryString = "";
        foreach (var key in parameters.AllKeys)
        {
            foreach (var value in parameters.GetValues(key))
            {
                queryString = QueryHelpers.AddQueryString(queryString, key, value);
            }
        };

        return queryString.TrimStart('?');
    }
叹倦 2024-10-03 08:41:05

这对我来说很有效:

public ActionResult SetLanguage(string language = "fr_FR")
        {            
            Request.UrlReferrer.TryReadQueryAs(out RouteValueDictionary parameters);            
            parameters["language"] = language;            
            return RedirectToAction("Index", parameters);            
        }

This did the trick for me:

public ActionResult SetLanguage(string language = "fr_FR")
        {            
            Request.UrlReferrer.TryReadQueryAs(out RouteValueDictionary parameters);            
            parameters["language"] = language;            
            return RedirectToAction("Index", parameters);            
        }
好倦 2024-10-03 08:41:05

你可以使用。

var ur = new Uri("/page",UriKind.Relative);

如果此 nv 是字符串类型,您可以附加到 uri 第一个参数。
喜欢

var ur2 = new Uri("/page?"+nv.ToString(),UriKind.Relative);

You can use.

var ur = new Uri("/page",UriKind.Relative);

if this nv is of type string you can append to the uri first parameter.
Like

var ur2 = new Uri("/page?"+nv.ToString(),UriKind.Relative);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文