Как построить строку запроса для URL в C #?

Теперь это возможно в Firefox 4 с предостережением, которое оно считает всплывающим окном и поэтому будет заблокировано всякий раз, когда появится всплывающее окно.

443
задан Keith Pinson 13 March 2014 в 17:30
поделиться

13 ответов

Если заглянуть внутрь, свойство QueryString - это NameValueCollection. Когда я делал подобные вещи, я обычно интересовался сериализацией И десериализацией, поэтому я предлагаю создать NameValueCollection, а затем перейти к:

using System.Linq;
using System.Web;
using System.Collections.Specialized;

private string ToQueryString(NameValueCollection nvc)
{
    var array = (
        from key in nvc.AllKeys
        from value in nvc.GetValues(key)
            select string.Format(
                "{0}={1}",
                HttpUtility.UrlEncode(key),
                HttpUtility.UrlEncode(value))
        ).ToArray();
    return "?" + string.Join("&", array);
}

Я полагаю, что есть очень элегантный способ сделать это и в LINQ ...

286
ответ дан 22 November 2019 в 22:57
поделиться

I added the following method to my PageBase class.

protected void Redirect(string url)
    {
        Response.Redirect(url);
    }
protected void Redirect(string url, NameValueCollection querystrings)
    {
        StringBuilder redirectUrl = new StringBuilder(url);

        if (querystrings != null)
        {
            for (int index = 0; index < querystrings.Count; index++)
            {
                if (index == 0)
                {
                    redirectUrl.Append("?");
                }

                redirectUrl.Append(querystrings.Keys[index]);
                redirectUrl.Append("=");
                redirectUrl.Append(HttpUtility.UrlEncode(querystrings[index]));

                if (index < querystrings.Count - 1)
                {
                    redirectUrl.Append("&");
                }
            }
        }

        this.Redirect(redirectUrl.ToString());
    }

To call:

NameValueCollection querystrings = new NameValueCollection();    
querystrings.Add("language", "en");
querystrings.Add("id", "134");
this.Redirect("http://www.mypage.com", querystrings);
1
ответ дан 22 November 2019 в 22:57
поделиться

Как насчет создания методов расширения, которые позволяют вам добавлять параметры в свободном стиле, как этот?

string a = "http://www.somedomain.com/somepage.html"
    .AddQueryParam("A", "TheValueOfA")
    .AddQueryParam("B", "TheValueOfB")
    .AddQueryParam("Z", "TheValueOfZ");

string b = new StringBuilder("http://www.somedomain.com/anotherpage.html")
    .AddQueryParam("A", "TheValueOfA")
    .AddQueryParam("B", "TheValueOfB")
    .AddQueryParam("Z", "TheValueOfZ")
    .ToString(); 

Вот перегрузка, которая использует строку :

public static string AddQueryParam(
    this string source, string key, string value)
{
    string delim;
    if ((source == null) || !source.Contains("?"))
    {
        delim = "?";
    }
    else if (source.EndsWith("?") || source.EndsWith("&"))
    {
        delim = string.Empty;
    }
    else
    {
        delim = "&";
    }

    return source + delim + HttpUtility.UrlEncode(key)
        + "=" + HttpUtility.UrlEncode(value);
}

И вот перегрузка, которая использует StringBuilder :

public static StringBuilder AddQueryParam(
    this StringBuilder source, string key, string value)
{
    bool hasQuery = false;
    for (int i = 0; i < source.Length; i++)
    {
        if (source[i] == '?')
        {
            hasQuery = true;
            break;
        }
    }

    string delim;
    if (!hasQuery)
    {
        delim = "?";
    }
    else if ((source[source.Length - 1] == '?')
        || (source[source.Length - 1] == '&'))
    {
        delim = string.Empty;
    }
    else
    {
        delim = "&";
    }

    return source.Append(delim).Append(HttpUtility.UrlEncode(key))
        .Append("=").Append(HttpUtility.UrlEncode(value));
}
11
ответ дан 22 November 2019 в 22:57
поделиться

Некоторое время назад я отвечал на аналогичный вопрос . По сути, лучшим способом было бы использовать класс HttpValueCollection , которым на самом деле является свойство ASP.NET Request.QueryString , к сожалению, оно является внутренним в платформе .NET. Вы можете использовать Reflector, чтобы захватить его (и поместить в свой класс Utils). Таким образом, вы можете управлять строкой запроса, как NameValueCollection, но позаботившись обо всех проблемах кодирования / декодирования URL-адресов.

HttpValueCollection расширяет NameValueCollection и имеет конструктор, который принимает закодировала строку запроса (включая амперсанды и вопросительные знаки) и переопределяла метод ToString () для последующего перестроения строки запроса из базовой коллекции.

Пример:

  var coll = new HttpValueCollection();

  coll["userId"] = "50";
  coll["paramA"] = "A";
  coll["paramB"] = "B";      

  string query = coll.ToString(true); // true means use urlencode

  Console.WriteLine(query); // prints: userId=50&paramA=A&paramB=B
30
ответ дан 22 November 2019 в 22:57
поделиться

Не проверено, но я думаю, что что-то в этом роде будет работать довольно хорошо

public class QueryString
{
    private Dictionary<string,string> _Params = new Dictionary<string,string>();

    public overide ToString()
    {
        List<string> returnParams = new List<string>();

        foreach (KeyValuePair param in _Params)
        {
            returnParams.Add(String.Format("{0}={1}", param.Key, param.Value));
        }

        // return String.Format("?{0}", String.Join("&", returnParams.ToArray())); 

        // credit annakata
        return "?" + String.Join("&", returnParams.ToArray());
    }

    public void Add(string key, string value)
    {
        _Params.Add(key, HttpUtility.UrlEncode(value));
    }
}

QueryString query = new QueryString();

query.Add("param1", "value1");
query.Add("param2", "value2");

return query.ToString();
5
ответ дан 22 November 2019 в 22:57
поделиться

Версия на основе метода быстрого расширения:

class Program
{
    static void Main(string[] args)
    {
        var parameters = new List<KeyValuePair<string, string>>
                             {
                                 new KeyValuePair<string, string>("A", "AValue"),
                                 new KeyValuePair<string, string>("B", "BValue")
                             };

        string output = "?" + string.Join("&", parameters.ConvertAll(param => param.ToQueryString()).ToArray());
    }
}

public static class KeyValueExtensions
{
    public static string ToQueryString(this KeyValuePair<string, string> obj)
    {
        return obj.Key + "=" + HttpUtility.UrlEncode(obj.Value);
    }
}

Вы можете использовать предложение where, чтобы выбрать, какие параметры будут добавлены в строку.

4
ответ дан 22 November 2019 в 22:57
поделиться

Assuming that you want to reduce dependencies to other assemblies and to keep things simple, you can do:

var sb = new System.Text.StringBuilder();

sb.Append("a=" + HttpUtility.UrlEncode("TheValueOfA") + "&");
sb.Append("b=" + HttpUtility.UrlEncode("TheValueOfB") + "&");
sb.Append("c=" + HttpUtility.UrlEncode("TheValueOfC") + "&");
sb.Append("d=" + HttpUtility.UrlEncode("TheValueOfD") + "&");

sb.Remove(sb.Length-1, 1); // Remove the final '&'

string result = sb.ToString();

This works well with loops too. The final ampersand removal needs to go outside of the loop.

Note that the concatenation operator is used to improve readability. The cost of using it compared to the cost of using a StringBuilder is minimal (I think Jeff Atwood posted something on this topic).

3
ответ дан 22 November 2019 в 22:57
поделиться

Вы можете создать новый записываемый экземпляр HttpValueCollection , вызвав System.Web.HttpUtility.ParseQueryString (string.Empty) , а затем использовать его как любой NameValueCollection . После добавления необходимых значений вы можете вызвать ToString в коллекции, чтобы получить строку запроса, как показано ниже:

NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty);

queryString["key1"] = "value1";
queryString["key2"] = "value2";

return queryString.ToString(); // Returns "key1=value1&key2=value2", all URL-encoded

HttpValueCollection является внутренним, поэтому вы не можете напрямую создавать экземпляр. Однако, получив экземпляр, вы можете использовать его как любой другой NameValueCollection . Поскольку фактический объект, с которым вы работаете, представляет собой HttpValueCollection , вызов метода ToString вызовет переопределенный метод HttpValueCollection , который форматирует коллекцию как строку запроса в кодировке URL.

После поиска в SO и в Интернете ответа на аналогичную проблему, это самое простое решение, которое я смог найти.

.NET Core

Если вы работаете в .NET Core, вы можете использовать Класс Microsoft.AspNetCore.WebUtilities.QueryHelpers , который значительно упрощает это.

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.queryhelpers

658
ответ дан 22 November 2019 в 22:57
поделиться

В dotnet базовом QueryHelpers. AddQueryString () примет IDictionary пар "ключ-значение". Для сохранения нескольких выделений памяти и циклов ЦП, можно использовать SortedList<> вместо IDictionary<>, с соответствующей способностью и объектами, добавленными в порядке сортировки...

var queryParams = new SortedList<string,string>(2);
queryParams.Add("abc", "val1");
queryParams.Add("def", "val2");

string requestUri = QueryHelpers.AddQueryString("https://localhost/api", queryParams);
0
ответ дан 22 November 2019 в 22:57
поделиться

Строка запроса может быть добавлена к URL:

  1. создают объект коллекции значения имени
  2. , добавляют объекты строки запроса, и их значения к этому объекту
  3. кодируют этот объект коллекции значения имени к URL, код предоставлен в ссылке ниже

https://blog.codingnovice.com/blog

public ActionResult Create()
{
//declaring name value collection object
NameValueCollection collection = new NameValueCollection();

//adding new value to the name value collection object
collection.Add("Id1", "wwe323");
collection.Add("Id2", "454w");
collection.Add("Id3", "tyt5656");
collection.Add("Id4", "343wdsd");

//generating query string
string url = GenerateQueryString(collection);

return View();
}
private string GenerateQueryString(NameValueCollection collection)
{
var querystring = (
from key in collection.AllKeys
from value in collection.GetValues(key)
select string.Format( "{0}={1}",
HttpUtility.UrlEncode(key),
HttpUtility.UrlEncode(value))
).ToArray();
return "?" + string.Join("&", querystring);
}
0
ответ дан 22 November 2019 в 22:57
поделиться

РЕДАКТИРОВАТЬ - как указано в комментариях , это не выход.

Есть такой класс - URI Class. «Обеспечивает объектное представление унифицированного идентификатора ресурса (URI) и легкий доступ к частям URI». (Microsoft docs).

В следующем примере создается экземпляр класса Uri и используется его для создания экземпляра WebRequest.

Пример C #

Uri siteUri = new Uri (" http: // www .contoso.com / ");

WebRequest wr = WebRequest.Create (siteUri);

Обратите внимание, в этом классе много методов.

-6
ответ дан 22 November 2019 в 22:57
поделиться

Вот реализация, которая использует очень базовые языковые функции. Это часть класса, который мы должны портировать и поддерживать в объекте C, поэтому мы решили иметь больше строк кода, но проще портировать и понять программистом, который не очень знаком с C #.

        /// <summary>
        /// Builds a complete http url with query strings.
        /// </summary>
        /// <param name="pHostname"></param>
        /// <param name="pPort"></param>
        /// <param name="pPage">ex "/index.html" or index.html</param>
        /// <param name="pGetParams">a Dictionary<string,string> collection containing the key value pairs.  Pass null if there are none.</param>
        /// <returns>a string of the form: http://[pHostname]:[pPort/[pPage]?key1=val1&key2=val2...</returns>

  static public string buildURL(string pHostname, int pPort, string pPage, Dictionary<string,string> pGetParams)
        {
            StringBuilder sb = new StringBuilder(200);
            sb.Append("http://");
            sb.Append(pHostname);
            if( pPort != 80 ) {
                sb.Append(pPort);
            }
            // Allows page param to be passed in with or without leading slash.
            if( !pPage.StartsWith("/") ) {
                sb.Append("/");
            }
            sb.Append(pPage);

            if (pGetParams != null && pGetParams.Count > 0)
            {
                sb.Append("?");
                foreach (KeyValuePair<string, string> kvp in pGetParams)
                {
                    sb.Append(kvp.Key);
                    sb.Append("=");
                    sb.Append( System.Web.HttpUtility.UrlEncode(kvp.Value) );
                    sb.Append("&");
                }
                sb.Remove(sb.Length - 1, 1); // Remove the final '&'
            }
            return sb.ToString();
        }
-2
ответ дан 22 November 2019 в 22:57
поделиться
public string UrlQueryStr(object data)
{
    if (data == null)
        return string.Empty;

    object val;
    StringBuilder sb = new StringBuilder();

    foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(data))
    {
        if ((val = prop.GetValue(data)) != null)
        {
            sb.AppendFormat("{0}{1}={2}", sb.Length == 0 ? '?' : '&',
                HttpUtility.UrlEncode(prop.Name), HttpUtility.UrlEncode(val.ToString()));
        }
    }
    return sb.ToString();
}
-3
ответ дан 22 November 2019 в 22:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: