Get URL parameters from a string in .NET - c#

I've got a string in .NET which is actually a URL. I want an easy way to get the value from a particular parameter.
Normally, I'd just use Request.Params["theThingIWant"], but this string isn't from the request. I can create a new Uri item like so:
Uri myUri = new Uri(TheStringUrlIWantMyValueFrom);
I can use myUri.Query to get the query string...but then I apparently have to find some regexy way of splitting it up.
Am I missing something obvious, or is there no built in way to do this short of creating a regex of some kind, etc?

Use static ParseQueryString method of System.Web.HttpUtility class that returns NameValueCollection.
Uri myUri = new Uri("http://www.example.com?param1=good&param2=bad");
string param1 = HttpUtility.ParseQueryString(myUri.Query).Get("param1");
Check documentation at http://msdn.microsoft.com/en-us/library/ms150046.aspx

This is probably what you want
var uri = new Uri("http://domain.test/Default.aspx?var1=true&var2=test&var3=3");
var query = HttpUtility.ParseQueryString(uri.Query);
var var2 = query.Get("var2");

Here's another alternative if, for any reason, you can't or don't want to use HttpUtility.ParseQueryString().
This is built to be somewhat tolerant to "malformed" query strings, i.e. http://test/test.html?empty= becomes a parameter with an empty value. The caller can verify the parameters if needed.
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));
}
}
Test
[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);
}
}
}

Looks like you should loop over the values of myUri.Query and parse it from there.
string desiredValue;
foreach(string item in myUri.Query.Split('&'))
{
string[] parts = item.Replace("?", "").Split('=');
if(parts[0] == "desiredKey")
{
desiredValue = parts[1];
break;
}
}
I wouldn't use this code without testing it on a bunch of malformed URLs however. It might break on some/all of these:
hello.html?
hello.html?valuelesskey
hello.html?key=value=hi
hello.html?hi=value?&b=c
etc

#Andrew and #CZFox
I had the same bug and found the cause to be that parameter one is in fact: http://www.example.com?param1 and not param1 which is what one would expect.
By removing all characters before and including the question mark fixes this problem. So in essence the HttpUtility.ParseQueryString function only requires a valid query string parameter containing only characters after the question mark as in:
HttpUtility.ParseQueryString ( "param1=good&param2=bad" )
My workaround:
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" );`

You can just use the Uri to get the list of the query strings or find a specific parameter.
Uri myUri = new Uri("http://www.example.com?param1=good&param2=bad");
var params = myUri.ParseQueryString();
var specific = myUri.ParseQueryString().Get("param1");
var paramByIndex = myUri.ParseQueryString().Get(2);
You can find more from here: https://learn.microsoft.com/en-us/dotnet/api/system.uri?view=net-5.0

You can use the following workaround for it to work with the first parameter too:
var param1 =
HttpUtility.ParseQueryString(url.Substring(
new []{0, url.IndexOf('?')}.Max()
)).Get("param1");

Or if you don't know the URL (so as to avoid hardcoding, use the AbsoluteUri
Example ...
//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;
}

Use .NET Reflector to view the FillFromString method of System.Web.HttpValueCollection. That gives you the code that ASP.NET is using to fill the Request.QueryString collection.

Single line LINQ solution:
Dictionary<string, string> ParseQueryString(string query)
{
return query.Replace("?", "").Split('&').ToDictionary(pair => pair.Split('=').First(), pair => pair.Split('=').Last());
}

if you want in get your QueryString on Default page .Default page means your current page url .
you can try this code :
string paramIl = HttpUtility.ParseQueryString(this.ClientQueryString).Get("city");

This is actually very simple, and that worked for me :)
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();
}

For anyone who wants to loop through all query strings from a string
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
}

Here is a sample that mentions what dll to include
var testUrl = "https://www.google.com/?q=foo";
var data = new Uri(testUrl);
// Add a reference to System.Web.dll
var args = System.Web.HttpUtility.ParseQueryString(data.Query);
args.Set("q", "my search term");
var nextUrl = $"{data.Scheme}://{data.Host}{data.LocalPath}?{args.ToString()}";

Easiest way how to get value of know the param name:
using System.Linq;
string loc = "https://localhost:5000/path?desiredparam=that_value&anotherParam=whatever";
var c = loc.Split("desiredparam=").Last().Split("&").First();//that_value

HttpContext.Current.Request.QueryString.Get("id");

I used it and it run perfectly
<%=Request.QueryString["id"] %>

Related

Json.Net convert complex querystring to JsonString

I am implementing a utility method to convert queryString to JsonString.
My code is as follows:
public static string GetJsonStringFromQueryString(string queryString)
{
var nvs = HttpUtility.ParseQueryString(queryString);
var dict = nvs.AllKeys.ToDictionary(k => k, k => nvs[k]);
return JsonConvert.SerializeObject(dict, new KeyValuePairConverter());
}
when I test with the following code:
var postString = "product[description]=GreatStuff" +
"&product[extra_info]=Extra";
string json = JsonHelper<Product>.GetJsonStringFromQueryString(postString);
I got
{
"product[description]":"GreatStuff",
"product[extra_info]":"Extra",
...
}
what I would like to get is
{
"product":{
"description": "GreatStuff",
"extra_info" : "Extra",
...
}
}
How can I achieve this without using System.Web.Script Assembly? (I am on Xamarin and have no access to that library)
You need to remove the product[key] (excepting the product property name or key...) part to get what you want...
That is, you should pre-process your query string before parsing it this way:
string queryString = "product[description]=GreatStuff" +
"&product[extra_info]=Extra";
var queryStringCollection = HttpUtility.ParseQueryString(queryString);
var cleanQueryStringDictionary = queryStringCollection.AllKeys
.ToDictionary
(
key => key.Replace("product[", string.Empty).Replace("]", string.Empty),
key => queryStringCollection[key]
);
var holder = new { product = cleanQueryStringDictionary };
string jsonText = JsonConvert.SerializeObject(holder);

Compare Dictionary Key of type string to another string in C#

I'm actually trying to check if a string is equal to any of the key's in my Dictionary object.
Here is what I have done so far:
using (var oStreamReader = new StreamReader(path))
{
Dictionary<String, String> typeNames = new Dictionary<string, string>();
typeNames.Add("Kind","nvarchar(1000)");
typeNames.Add("Name","nvarchar(1000)");
DataTable oDataTable = new DataTable();
var headLine = oStreamReader.ReadLine().Trim().Replace("\"", "");
var columnNames = headLine.Split(new[] { ';' });
String[] oStreamDataValues;
/*
*create DataTable header with specific datatypes and names
*/
int countCol = 0;
foreach (string readColumn in columnNames)
{
if ((readColumn.ToString().Replace("\"", "").CompareTo(typeNames) == true))
{
// this comparison doesn't work
}
}
}
I am not quite sure what exactly you are trying to achieve. If you have a C# dictonary you can use linq to check for values that match the required value, e.g.
string valueToCompare = "Value to match";
Dictionary<string, string> dict = new Dictionary<string, string>
{
{"Key 1", "A value"},
{"Key 2", "Another value"}
};
bool found= dict.Values
.Any(value
=>
value.Equals(valueToCompare,
StringComparison.CurrentCultureIgnoreCase)
);
Since you want check if exist an entry in your Dictionary that as the same key of one of the values in your columnNames object I suggest you to use ContainsKey method
Dictionary<string, string> d = new Dictionary<string, string>();
string keyvalue;
if (d.ContainsKey("value to find"))
{
if (d.TryGetValue("value to find", out keyvalue))
{
//// here keyvalue variable has the value
}
else
{
///value is null or throws exception
}
}
else
{
////key no exists
}
I have solved this (by inspiration of Paul Houlston and Thomas Lielacher)
string headLine = oStreamReader.ReadLine().Trim().Replace("\"", "");
string columnNames = headLine.Split(new[] { ';' });
foreach (string readColumn in columnNames)
{
if (typeNames.Keys.Contains(readColumn, StringComparer.CurrentCultureIgnoreCase) == true)
{
DataColumn oDataColumn = new DataColumn(readColumn,typeof(System.String));
oDataTable.Columns.Add(oDataColumn);
}
}

Validate if URL exist in List using linq

I Have a object List and I need to validate to check if a given url exist in the list. Think LINQ will be a good approach, but I'm not quite sure how to go about it.
var url1 = new WhiteListItem() {Url = "*.aaaaa.com/*"};
var url2 = new WhiteListItem() { Url = "www.bbbbb.com/*" };
var url3 = new WhiteListItem() { Url = "www.ccccc.com" };
var url4 = new WhiteListItem() { Url = "www.ddddd.com/ddddddd" };
var validUrls = new List<WhiteListItem> {url1, url2, url3, url4};
Just to clarify, I'm trying to get the following results for given url:
True - www.aaaaa.com/something?aaa=something/something
True - mobi.aaaaa.com/Something
False - aaaaa.com (Because no sub-domain present)
True - www.bbbbb.com/something/something
True - www.bbbbb.com
False - mobi.bbbbb.com (Because only www sub-domain allowed)
I Think you get the picture. Please help or just point me in a correct direction. Code examples will be highly appreciated.
#stovroz, thanx for coming back to me. I thought I should do something like that, here is my function: Please let me know if you see any loopholes. Not sure if the use of a stringbuilder was an overkill?
And Then 1 last question how can I say that "/" can be present at the end but not permitted to pass.
private static Regex CreateRegularExpression(string urlString)
{
var sb = new StringBuilder(urlString.Trim());
sb.Replace(".", #"\.");
if (sb.ToString().EndsWith(#"/"))
{
sb.Append("?");
}
if (sb.ToString().EndsWith(#"/*"))
{
sb.Insert(sb.Length - 1, '.');
}
if (sb.ToString().IndexOf("https://", StringComparison.Ordinal) >= 0)
{
sb.Replace("https://", #"\bhttps://");
}
else if (sb.ToString().IndexOf("http://", StringComparison.Ordinal) >= 0)
{
sb.Replace("http://", #"\bhttp://");
}
else
{
sb = new StringBuilder(Config.AllowedProtocolRegExp + sb.ToString());
}
sb.Replace(#"://*\.", #"://[\x2DA-Za-z0-9]*\.");
return new Regex(sb.ToString());
}
I think it would be better if you could express your whitelist rules as regular expressions, either as a single composite regular expression, or as a list of separate expressions and checking if any match, something like:
var whitelist = new [] {#".*\.aaaaa\.com/*.", #"www.bbbbb.com/.*"};
var list = new [] { "mobi.aaaaa.com/Something", "mobi.bbbbb.com/" };
var matches = list.Where(x => whitelist.Any(y => Regex.IsMatch(x, y)));
Update:
As you've got a large number of patters to match on which are already in wildcard syntax, you can convert those to Regex syntax first by using the following function:
public string WildcardToRegex(string pattern)
{
return "^" + Regex.Escape(pattern).
Replace("\\*", ".*").
Replace("\\?", ".") + "$";
}
(from http://www.codeproject.com/Articles/11556/Converting-Wildcards-to-Regexes)
so:
var wildcardWhitelist = new [] { "*.aaaaa.com/*", "www.bbbbb.com/*" };
var regexWhitelist = wildcardWhitelist.Select(x => WildcardToRegex(x));
var list = new [] { "mobi.aaaaa.com/Something", "mobi.bbbbb.com/" };
var matches = list.Where(x => regexWhitelist.Any(y => Regex.IsMatch(x, y)));
var urls = new List<WhiteListItem>
{
new WhiteListItem() {Url = "*.aaaaa.com/*"},
new WhiteListItem() { Url = "www.bbbbb.com/*" },
new WhiteListItem() { Url = "www.ccccc.com" },
new WhiteListItem() { Url = "www.ddddd.com/ddddddd" };
};
var validatedUrls = urls.Select(u => new
{
// here you can use Regular Expression pattern to validate your Urls
//or you can use your custom method
IsPassed = Regex.IsMatch("",u.Url),
Url = u.Url,
}).ToList();
var goodUrls = validatedUrls.Where(u=> u.IsPassed).Select(u=>u.Url);
var badUrls = validatedUrls.Where(u=> !u.IsPassed).Select(u=>u.Url);

How to Sort NameValue Collection and Store it in a string

Here I am storing two set of querystring parameters into two different namevalue collection. The querystring parameter order may vary so I just want to sort the order and then I need to store namevalue collection to a string.
Updated Code :
string url1 = #"http://www.somewebsitesampletest.com/dcs7o?data=142248494&dcp=smre&nparam=4567P&email=xxx.com";
string url2 = #"http://www.somewebsitesampletest.com/dcs7o?dcp=smre&data=142248494&email=xxx.com&nparam=4567P";
var NameValueCollection1 = HttpUtility.ParseQueryString(url1);
var NameValueCollection2 = HttpUtility.ParseQueryString(url2);
ExpectedResult:
After Sorting and converting to string the result should look like the below one
string query1 = "data=142248494&dcp=smre&email=xxx.com&nparam=4567P";
string query2 = "data=142248494&dcp=smre&email=xxx.com&nparam=4567P";
Here's a solution using Linq.
Basically it changes the NameValueCollection to an IEnumerable of the keys using Cast<T>, then the rest is fairly self explanatory.
public string GetSortedQueryString(string url)
{
var queryString = HttpUtility.ParseQueryString(url);
// Ignore null keys (caused by your ?& at the start of the query string
var orderedKeys = queryString.Cast<string>().Where(k => k != null).OrderBy(k => k);
return string.Join("&", orderedKeys.Select(k => string.Format("{0}={1}", k, queryString[k])));
}
Results for your URLs would be:
data=142248494&dcp=smre&email=xxx.com&nparam=4567P
data=142248494&dcp=smre&email=xxx.com&nparam=4567P
Email comes before nparam, unlike your expected solution (I'm assuming that was a mistake).
use LINQ with a Dictionary and a list of KeyValuePair :
string url1 = #"http://www.somewebsitesampletest.com/dcs7o?&data=142248494&dcp=smre&nparam=4567P&email=xxx.com";
string query1 ="";
Dictionary<String, String> paramDict = new Dictionary<string, string>();
var query = from match in urlString.Split('?').Where(m => m.Contains('='))
.SelectMany(pr => pr.Split('&'))
where match.Contains('=')
select new KeyValuePair<string, String>(
match.Split('=')[0],
match.Split('=')[1]);
query.ToList().ForEach(kvp => paramDict.Add(kvp.Key, kvp.Value));
var List<KeyValuePair<string, string>> paramList = paramDict.ToList();
paramList.Sort();
foreach (KeyValuePair<string, int> pair in list)
{
query1+=pair.Key+"="+pair.Value+"&";
}
query1=query1.TrimEnd('&');
I made this fiddle because I needed to sort querystring values in order to properly compare URIs: (H/T to Jacob's answer)
https://dotnetfiddle.net/eEhkNk
This preserves duplicate keys:
public static string[] QueryStringOmissions = new string[] { "b" };
public static NameValueCollection SortAndRemove(NameValueCollection collection)
{
var orderedKeys = collection.Cast<string>().Where(k => k != null).OrderBy(k => k);
var newCollection = HttpUtility.ParseQueryString(String.Empty);
foreach(var key in orderedKeys)
{
if (!QueryStringOmissions.Contains(key))
{
foreach(var val in collection.GetValues(key).Select(x => x).OrderBy(x => x).ToArray())
{
newCollection.Add(key, val);
}
}
}
return newCollection;
}

filtering a tuple based on item 3 in the tuple

I need to print a list of countries that use dollars as a currency from a web service.
the data comes form a class called country services which contains this tuple:
public static IEnumerable<Tuple<string, string, string, string>> GetCountryData()
{
var countryService = new CountryServiceProxy.country();
var xmlStringResult = countryService.GetCurrencies();
var result = new List<Tuple<string, string, string, string>>();
var xPathDoc = new XPathDocument(new XmlTextReader(new StringReader(xmlStringResult)));
var navigator = xPathDoc.CreateNavigator();
var nodes = navigator.Select("//Table");
var nodeNames = new[] {"Name", "CountryCode", "Currency", "CurrencyCode"};
while (nodes.MoveNext())
{
var nodeValues = new[] {string.Empty, string.Empty, string.Empty, string.Empty};
for (var i = 0; i < nodeNames.Length; i++)
{
var node = nodes.Current.SelectSingleNode(nodeNames[i]);
if (node != null)
{
nodeValues[i] = node.Value;
}
}
result.Add(new Tuple<string, string, string, string>(nodeValues[0], nodeValues[1], nodeValues[2], nodeValues[3]));
}
return result;
}
I need to call that method and use it to print out a list with countries that use dollars:
private static IEnumerable<Country> Excercise4()
{
// var data = CountryService.GetCountryData().Where(x => x.Item3.Contains("Dollar"));
// ////var data = CountryService.GetCountryData().Where(x => x.Item3 == "Dollar");
// //Console.WriteLine(data);
return new List<Country>
{
new Country("da", "C1", "$", "Dollar"),
new Country("Country2", "C3", "$", "Dollar")
};
}
so far my method looks like this. i cant seem to figure out how to print out the tuple , havent used tuple before.
my write method is as follows:
ConsoleHelper.PrintCountryResults(Excercise4(), "Return a list of Country objects who's currency is Dollar");
ConsoleHelper.Pause(PauseMessage);
and the console helper class looks like this :
public static void PrintCountryResults(IEnumerable<Country> results, string title)
{
PrintHeader(title);
foreach (var result in results)
{
Console.WriteLine("{0, -30}{1, -5}{2, -15}{3, -5}", result.CountryName, result.CountryCode, result.CurrencyName, result.CurrencyCode);
}
}
any help would be appreciated as i said havent used tuple before first try at them ..
Thanx
You can filter the properties of the tuple by referencing the ItemX property with X being the 1-based index of the property that you're interested in. in you case if the currency is the third item, filtering the tuples would look like
var countriesUsingDollarAsACurrency = GetCountryData().Where(tuple => tuple.Item3 == "Dollar");

Categories

Resources