Building Query String - c#

I have been following this link: Build query string for System.Net.HttpClient get
but my situation was a little different and was not sure what the best approach would be. As of now I am thinking about going with a for loop but figured there might be a better approach.I have a list of parameters. I thought about just for looping over the list but that would make it where the querystring would be "?foo=1?foo=2"
See below example as to what I am looking for and what I have so far
var query = HttpUtility.ParseQueryString(string.Empty);
List<String> foos = ...
query["foo"] = "1";
string queryString = query.ToString()
//Expected query string to be ?foo=1&foo=2

Try Add method on NameViewCollection
With Add method you can add multiple values for a single key.
var qs = HttpUtility.ParseQueryString(string.Empty);
qs.Add("foo", "1");
qs.Add("foo", "2");
qs.ToString(); would give you foo=1&foo=2

Related

HttpUtility.ParseQueryString does not allow to add duplicate key

I have Web API endpoint which expects a list of enum values. I am using HttpUtility.ParseQueryString to generate the query string where I want to pass multiple key-value pair in the query string as below,
../api/getdata?myEnum=One&myEnum=Two&myEnum=Three
But, the ParseQueryString is creating the query string url as below,
../api/getdata?myEnum=One%2cTwo%2cThree
Here is my code,
var queryString = System.Web.HttpUtility.ParseQueryString(string.Empty);
queryString.Add("myEnum", "One");
queryString.Add("myEnum", "Two");
queryString.Add("myEnum", "Three");
How can I create the expected query string url with duplicate keys.
../api/getdata?myEnum=One&myEnum=Two&myEnum=Three
You can achieve the expected result via the AddQueryString method of the QueryHelpers class in ASP.NET Core.
This class is contained in the Microsoft.AspNetCore.WebUtilities NuGet package.
string url = "http://yourservice/api/getdata";
url = QueryHelpers.AddQueryString(url, "myEnum", "One");
url = QueryHelpers.AddQueryString(url, "myEnum", "Two");
url = QueryHelpers.AddQueryString(url, "myEnum", "Three");
Console.WriteLine(url); // http://yourservice/api/getdata?myEnum=One&myEnum=Two&myEnum=Three
This feature has been added a while back [0] using QueryBuilder.
You can now use query builder and pass in an IEnumerable. So if I wanted to add a bunch of id=something parameters to a query I can do this:
var query = new QueryBuilder {{"id", itemIds}}.ToQueryString();
This will give me a query string in the form: ?id=1&id=2&id=...
In your particular case it would be something like this if you had an IEnumerable of your enums.
var query = new QueryBuilder {{"myEnum", myEnums}}.ToQueryString();
[0] https://github.com/dotnet/aspnetcore/issues/7945

Any .NET class that makes a query string given key value pairs or the like

Is there a class in the .NET framework which, if given a sequence/enumerable of key value pairs (or anything else I am not rigid on the format of this) can create a query string like this:
?foo=bar&gar=har&print=1
I could do this trivial task myself but I thought I'd ask to save myself from re-inventing the wheel. Why do all those string gymnastics when a single line of code can do it?
You can use System.Web.HttpUtility.ParseQueryString to create an empty System.Web.HttpValueCollection, and use it like a NameValueCollection.
Example:
var query = System.Web.HttpUtility.ParseQueryString(string.Empty);
query ["foo"] = "bar";
query ["gar"] = "har";
query ["print"] = "1";
var queryString = query.ToString(); // queryString is 'foo=bar&gar=har&print=1'
There's nothing built in to the .NET framework, as far as I know, though there are a lot of almosts.
System.Web.HttpRequest.QueryString is a pre-parsed NameValueCollection, not something that can output a querystring. System.NetHttpWebRequest expects you to pass a pre-formed URI, and System.UriBuilder has a Query property, but again, expects a pre-formed string for the entire query string.
However, running a quick search for "querystringbuilder" shows a couple of implementations for this out in the web that could serve. One such is this one by Brad Vincent, which gives you a simple fluent interface:
//take an existing string and replace the 'id' value if it exists (which it does)
//output : "?id=5678&user=tony"
strQuery = new QueryString("id=1234&user=tony").Add("id", "5678", true).ToString();
And, though not exactly very elegant, I found a method in RestSharp, as suggested by #sasfrog in the comment to my question. Here's the method.
From RestSharp-master\RestSharp\Http.cs
private string EncodeParameters()
{
var querystring = new StringBuilder();
foreach (var p in Parameters)
{
if (querystring.Length > 0)
querystring.Append("&");
querystring.AppendFormat("{0}={1}", p.Name.UrlEncode(), p.Value.UrlEncode());
}
return querystring.ToString();
}
And again, not very elegant and not really what I would have been expecting, but hey, it gets the job done and saves me some typing.
I was really looking for something like Xi Huan's answer (marked the correct answer) but this works as well.
There's nothing built into the .NET Framework that preserves the order of the query parameters, AFAIK. The following helper does that, skips null values, and converts values to invariant strings. When combined with a KeyValueList, it makes building URIs pretty easy.
public static string ToUrlQuery(IEnumerable<KeyValuePair<string, object>> pairs)
{
var q = new StringBuilder();
foreach (var pair in pairs)
if (pair.Value != null) {
if (q.Length > 0) q.Append('&');
q.Append(pair.Key).Append('=').Append(WebUtility.UrlEncode(Convert.ToString(pair.Value, CultureInfo.InvariantCulture)));
}
return q.ToString();
}

How do I get SQL statement from LinqToEntities clause

I have an issue that's causing me a lot of headache. I've already googled a solution some days ago, but I didn't found it yet, if one of you guys could help me, it would be great!
I have this method to take the SQL statement for me:
private static string GetClause<T>(IQueryable<T> clause) where T : BaseEntity
{
string snippet = "FROM [dbo].[";
string sql = clause.ToString();
string sqlFirstPart = sql.Substring(sql.IndexOf(snippet));
sqlFirstPart = sqlFirstPart.Replace("AS [Extent1]", "");
sqlFirstPart = sqlFirstPart.Replace("[Extent1].", "");
return sqlFirstPart;
}
But this doesn't work when I try to use some filter (e.g. where), cause it returns me some ""#p_linq_{0}"." instead of the values. I know these are the parameters of my query, but where are they stored?
I use this for batch delete purposes on the EF5 Code First.
If you create a query with a param like this:
var name = "xxx";
var query = ctx.Persons.Where(x => x.FirstName == name);
Then you can get the sql statement and parameters like this:
var oq = ((ObjectQuery<Person>)query);
var trace = oq.ToTraceString();
var p = oq.Parameters;
Use the param name "p_linq_{0}" without the # as an index on p, p["p_linq_{0}"].

Need help to resolve pulling data using ListServiceUtility

I have a method that I want to pull back data from a sharepoint list. In the method I have the following code:
var listPath = new Uri(string.Format("{0}/forms/", SitePath));
var fieldNames = new List<string> {"Id","UserName", "FullName"};
var query = XElement.Parse(#"<Query/>");
var listData = ListServiceUtility.GetListItemData(listPath, listName, string.Empty, fieldNames, query, false, 50);
when I break out listData I only have data for FullName, I don't have the other fields I wanted that I have in fieldNames.
I have not found much in the way of examples in C# and the VB example only makes a call for 1 field. Kind of pointless if I cant bring back more than one field in a list.
Am I using the wrong method? How can I get more than one field in my collection of data?
Any help would be appreciated.

How can I remove item from querystring in asp.net using c#?

I want remove "Language" querystring from my url. How can I do this? (using Asp.net 3.5 , c#)
Default.aspx?Agent=10&Language=2
I want to remove "Language=2", but language would be the first,middle or last. So I will have this
Default.aspx?Agent=20
If it's the HttpRequest.QueryString then you can copy the collection into a writable collection and have your way with it.
NameValueCollection filtered = new NameValueCollection(request.QueryString);
filtered.Remove("Language");
Here is a simple way. Reflector is not needed.
public static string GetQueryStringWithOutParameter(string parameter)
{
var nameValueCollection = System.Web.HttpUtility.ParseQueryString(HttpContext.Current.Request.QueryString.ToString());
nameValueCollection.Remove(parameter);
string url = HttpContext.Current.Request.Path + "?" + nameValueCollection;
return url;
}
Here QueryString.ToString() is required because Request.QueryString collection is read only.
Finally,
hmemcpy answer was totally for me and thanks to other friends who answered.
I grab the HttpValueCollection using Reflector and wrote the following code
var hebe = new HttpValueCollection();
hebe.Add(HttpUtility.ParseQueryString(Request.Url.Query));
if (!string.IsNullOrEmpty(hebe["Language"]))
hebe.Remove("Language");
Response.Redirect(Request.Url.AbsolutePath + "?" + hebe );
My personal preference here is rewriting the query or working with a namevaluecollection at a lower point, but there are times where the business logic makes neither of those very helpful and sometimes reflection really is what you need. In those circumstances you can just turn off the readonly flag for a moment like so:
// reflect to readonly property
PropertyInfo isreadonly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
// make collection editable
isreadonly.SetValue(this.Request.QueryString, false, null);
// remove
this.Request.QueryString.Remove("foo");
// modify
this.Request.QueryString.Set("bar", "123");
// make collection readonly again
isreadonly.SetValue(this.Request.QueryString, true, null);
I answered a similar question a while ago. Basically, the best way would be to use the class HttpValueCollection, which the QueryString property actually is, unfortunately it is internal in the .NET framework.
You could use Reflector to grab it (and place it into your Utils class). This way you could manipulate the query string like a NameValueCollection, but with all the url encoding/decoding issues taken care for you.
HttpValueCollection extends NameValueCollection, and has a constructor that takes an encoded query string (ampersands and question marks included), and it overrides a ToString() method to later rebuild the query string from the underlying collection.
Try this ...
PropertyInfo isreadonly =typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
isreadonly.SetValue(this.Request.QueryString, false, null);
this.Request.QueryString.Remove("foo");
Gather your query string by using HttpContext.Request.QueryString. It defaults as a NameValueCollection type.
Cast it as a string and use System.Web.HttpUtility.ParseQueryString() to parse the query string (which returns a NameValueCollection again).
You can then use the Remove() function to remove the specific parameter (using the key to reference that parameter to remove).
Use case the query parameters back to a string and use string.Join() to format the query string as something readable by your URL as valid query parameters.
See below for a working example, where param_to_remove is the parameter you want to remove.
Let's say your query parameters are param1=1&param_to_remove=stuff&param2=2. Run the following lines:
var queryParams = System.Web.HttpUtility.ParseQueryString(HttpContext.Request.QueryString.ToString());
queryParams.Remove("param_to_remove");
string queryString = string.Join("&", queryParams.Cast<string>().Select(e => e + "=" + queryParams[e]));
Now your query string should be param1=1&param2=2.
You don't make it clear whether you're trying to modify the Querystring in place in the Request object. Since that property is read-only, I guess we'll assume you just want to mess with the string.
... In which case, it's borderline trivial.
grab the querystring off the Request
.split() it on '&'
put it back together into a new string, while sniffing for and tossing out anything starting with "language"
Get the querystring collection, parse it into a (name=value pair) string, excluding the one you want to REMOVE, and name it newQueryString
Then call Response.Redirect(known_path?newqueryString);
You're probably going to want use a Regular Expression to find the parameter you want to remove from the querystring, then remove it and redirect the browser to the same file with your new querystring.
Yes, there are no classes built into .NET to edit query strings. You'll have to either use Regex or some other method of altering the string itself.
If you have already the Query String as a string, you can also use simple string manipulation:
int pos = queryString.ToLower().IndexOf("parameter=");
if (pos >= 0)
{
int pos_end = queryString.IndexOf("&", pos);
if (pos_end >= 0) // there are additional parameters after this one
queryString = queryString.Substring(0, pos) + queryString.Substring(pos_end + 1);
else
if (pos == 0) // this one is the only parameter
queryString = "";
else // this one is the last parameter
queryString=queryString.Substring(0, pos - 1);
}
well I have a simple solution , but there is a little javascript involve.
assuming the Query String is "ok=1"
string url = Request.Url.AbsoluteUri.Replace("&ok=1", "");
url = Request.Url.AbsoluteUri.Replace("?ok=1", "");
Response.Write("<script>window.location = '"+url+"';</script>");
string queryString = "Default.aspx?Agent=10&Language=2"; //Request.QueryString.ToString();
string parameterToRemove="Language"; //parameter which we want to remove
string regex=string.Format("(&{0}=[^&\s]+|{0}=[^&\s]+&?)",parameterToRemove);
string finalQS = Regex.Replace(queryString, regex, "");
https://regexr.com/3i9vj
Parse Querystring into a NameValueCollection. Remove an item. And use the toString to convert it back to a querystring.
using System.Collections.Specialized;
NameValueCollection filteredQueryString = System.Web.HttpUtility.ParseQueryString(Request.QueryString.ToString());
filteredQueryString.Remove("appKey");
var queryString = '?'+ filteredQueryString.ToString();
ASP .NET Core (native, don't have to reference any additional libraries)
Within an ASP .NET Core Controller you would have access to an instance of Request
Request.Query is a query collection representing the query parameters, cast it to a list
From which you can filter and remove the params you want
Use QueryString.Create, which can take the list you just filtered as an input & generate a query string directly
var removeTheseParams = new List<string> {"removeMe1", "removeMe2"}.AsReadOnly();
var filteredQueryParams = Request.Query.ToList().Where(filterKvp => !removeTheseParams.Contains(filterKvp.Key));
var filteredQueryString = QueryString.Create(queryParamsFilteredList).ToString();
//Example: Console.Writeline(filteredQueryString) will give you "?q1=v1&q2=v2"
Optional Part Below: Can also encode those values if they are unsafe,
so in addition to the Where() above UrlEncode the query parameter keys and values using a Select() as shown below:
//Optional
.Select(cleanKvp => new KeyValuePair<string, string?>(UrlEncoder.Default.Encode(cleanKvp.Key),UrlEncoder.Default.Encode(cleanKvp.Value)))

Categories

Resources