Теперь это возможно в Firefox 4 с предостережением, которое оно считает всплывающим окном и поэтому будет заблокировано всякий раз, когда появится всплывающее окно.
Если заглянуть внутрь, свойство 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 ...
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);
Как насчет создания методов расширения, которые позволяют вам добавлять параметры в свободном стиле, как этот?
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));
}
Некоторое время назад я отвечал на аналогичный вопрос . По сути, лучшим способом было бы использовать класс 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¶mA=A¶mB=B
Не проверено, но я думаю, что что-то в этом роде будет работать довольно хорошо
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();
Версия на основе метода быстрого расширения:
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, чтобы выбрать, какие параметры будут добавлены в строку.
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).
Вы можете создать новый записываемый экземпляр 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
В 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);
Строка запроса может быть добавлена к 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);
}
РЕДАКТИРОВАТЬ - как указано в комментариях , это не выход.
Есть такой класс - URI Class. «Обеспечивает объектное представление унифицированного идентификатора ресурса (URI) и легкий доступ к частям URI». (Microsoft docs).
В следующем примере создается экземпляр класса Uri и используется его для создания экземпляра WebRequest.
Пример C #
Uri siteUri = new Uri (" http: // www .contoso.com / ");
WebRequest wr = WebRequest.Create (siteUri);
Обратите внимание, в этом классе много методов.
Вот реализация, которая использует очень базовые языковые функции. Это часть класса, который мы должны портировать и поддерживать в объекте 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();
}
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();
}