How to parse query string of a Uri by keeping the encoding? - c#

I'm tryig to parse a query string's parameters into a NameValueCollection, using HttpUtility.ParseQueryString method:
var queryParams = HttpUtility.ParseQueryString(queryString);
The problem is, when I have an encoded parameter value, such as "%3Cscript%3Ealert(%27abc%27)%3C%2Fscript%3E" and I try to get it via a key, I get the decoded version.
var queryString = "?name=%3Cscript%3Ealert(%27abc%27)%3C%2Fscript%3E";
var queryParams = HttpUtility.ParseQueryString(queryString);
var nameValue = queryParams["name"] //<script>alert('abc')</script>
When I look at the reference source I can see that this is because of a boolean parameter urlencoded which I have no way to change. So, I'm guessing this is the expected behaviour, although I'm not sure why there is no option to change this value.
Is there any other method that will allow me to parse a query string without messing with the encoding, or am I missing something here?

Related

How to use Enyim's Memcached Client with the Append method?

The value that I'm trying to append to is a string. I've been able to convert the string to a byte array using Encoding.ASCII.GetBytes(value) and passing that to the IMemcachedClient:
Appending to Memcached (seems fine)
var value = "Some string value that should get appended";
var bytes = Encoding.ASCII.GetBytes(value);
_memcachedClient.Append(key, new ArraySegment<byte>(bytes, 0, bytes.Length));
Getting appended value from Memcached
var valueAsBase64 = _memcachedClient.Get(key) as string;
var bytes = System.Convert.FromBase64String(valueAsBase64);
var result = Encoding.ASCII.GetString(bytes);
I see the value returned, and it's a string. I'm just not sure how to get the value returned back to the string I started off with (now appended).
The issue I was running into was that I simply was initializing the entry with an empty string instead of an empty byte array. So the return type was a mangled mismash.
The issue came down to the .Append() method not setting an initial value if the key doesn't exist. I'll look a little more into it to see if there's a way of having it do an initial Put if the key doesn't exist.
This works though:
var bytes = (byte[])_cache.Get(key);
var value = Encoding.ASCII.GetString(bytes);

how to convert var type holding URL attributes to string to use them for redirecting

In the below statement i have tried to convert the var type variable "original" to string but it does not return any value to originalStr. I basiaclly need to concatenate this result with another string in order to redirect.
I have tried all the possible ways to fetch the value into string but failed. Can anyone please help to solve this.
var url = Request.Url;
var original= url.AbsoluteUri.Replace(url.PathAndQuery, string.Empty);
string originalStr= Convert.ToString(original);

Count QueryString Key in string of URL

I want to count how many query string key appear in a string of URL. The URL here is an string so I can't use Request.QueryString.AllKeys to count how many key in the url. Currently, I have an solution for this by analyze the structure of url string and using count string within a string to count query string keys in an url string. Everyone can look clearly in my sample of code:
public int CountQueryStringKey(string urlString)
{
string urlWithoutKey = urlString.Substring(0, urlString.IndexOf("?"));
string allKeyString = urlString.Substring(urlString.IndexOf("?") + 1);
string[] allKeyAndValue = allKeyString.Split('&');
return allKeyAndValue.Length;
}
It is simple but not enough. What will happen if there is no query string key in string of url, and there are always different kind of url which I'm not sure it's structure.
I need some help for a good solution in this issue.
While duplicate (Get individual query parameters from Uri) provides good enough answer I'd suggest using Uri.Query to extract query portion of the Url. Than continue with HttpUtility.ParseQueryString as recommended in other question.
Than NameValueCollection.Count to get the number of query parameters.
var queryParameters = HttpUtility.ParseQueryString(new Uri(urlString).Query);
var numberOfParameter = queryParameters.Count;
Have a look at this post. Here you can use HttpUtility to get query string parameters from the normal string
HttpUtility

Is there a simpler way to calculate this MD5 hash?

I'm working on implementing a hosted checkout, and the hosted checkout is supposed to redirect the user back to my website so that I can show a custom receipt page.
This is a sample querystring that I'd get back:
trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref4=&ref5=&hashValue=33dacf84682470f267b2cc6d528b1594
To validate the request, I'm supposed to remove &hashValue=f3cf58ef0fd363e0c2241938b04f1068 from the end of the querystring, and then append a key. I then perform an MD5 hash of the entire string, and the result should be 33dacf84682470f267b2cc6d528b1594, same as the original.
This is easy, except that a few of the fields are causing a problem for me. This is the code I use (taken from a dummy application, so you can ignore some of the bad coding):
// Split up the query string parameters
string[] parameters = GetQueryString().Split(new[] { "&" }, StringSplitOptions.None);
var querySet = new List<string>();
// Rebuild the query string, encoding the values.
foreach (string s in parameters)
{
// Every field that contains a "." will need to be encoded except for trnAmount
querySet.Add(param.Contains("trnAmount") ? param : UrlEncodeToUpper(param));
}
// Create the querystring without the hashValue, we need to calculate our hash without it.
string qs = string.Join("&", querySet.ToArray());
qs = qs.Substring(0, qs.IndexOf("&hashValue"));
qs = qs + "fb76124fea73488fa11995dfa4cbe89b";
var encoding = new UTF8Encoding();
var md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(encoding.GetBytes(qs));
var calculatedHash = BitConverter.ToString(hash).Replace("-", String.Empty).ToLower();
This is the UrlEncode method I use.
private static string UrlEncodeToUpper(string value)
{
// Convert their encoding into uppercase so we can do our hash
value = Regex.Replace(value, "(%[0-9af][0-9a-f])", c => c.Value.ToUpper());
// Encode the characters that they missed
value = value.Replace("-", "%2D").Replace(".", "%2E").Replace("_", "%5F");
return value;
}
This all works (until someone enters a character I haven't accounted for), except this seems more complicated than it should be. I know I'm not the only one who has to implement this HCO into an ASP.NET application, so I don't think the simple validation should be so complicated.
Am I missing an easier way to do this? Having to loop through the fields, encoding some of them while skipping others, converting their encoding to uppercase and then selectively replacing characters seems a little... odd.
Here's a better way to work with query strings:
var queryString = "trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref4=&ref5=&hashValue=33dacf84682470f267b2cc6d528b1594";
var values = HttpUtility.ParseQueryString(queryString);
// remove the hashValue parameter
values.Remove("hashValue");
var result = values.ToString();
// At this stage result = trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref4=&ref5=
// now add some other query string value
values["foo"] = "bar"; // you can stuff whatever you want it will be properly url encoded
Then I didn't quite understand what you wanted to do. You want to calculate an MD5 on the result? You could do that and then append to the query string.

Get individual query parameters from Uri [duplicate]

This question already has answers here:
Get URL parameters from a string in .NET
(17 answers)
Closed 4 years ago.
I have a uri string like: http://example.com/file?a=1&b=2&c=string%20param
Is there an existing function that would convert query parameter string into a dictionary same way as ASP.NET Context.Request does it.
I'm writing a console app and not a web-service so there is no Context.Request to parse the URL for me.
I know that it's pretty easy to crack the query string myself but I'd rather use a FCL function is if exists.
Use this:
string uri = ...;
string queryString = new System.Uri(uri).Query;
var queryDictionary = System.Web.HttpUtility.ParseQueryString(queryString);
This code by Tejs isn't the 'proper' way to get the query string from the URI:
string.Join(string.Empty, uri.Split('?').Skip(1));
You can use:
var queryString = url.Substring(url.IndexOf('?')).Split('#')[0]
System.Web.HttpUtility.ParseQueryString(queryString)
MSDN
This should work:
string url = "http://example.com/file?a=1&b=2&c=string%20param";
string querystring = url.Substring(url.IndexOf('?'));
System.Collections.Specialized.NameValueCollection parameters =
System.Web.HttpUtility.ParseQueryString(querystring);
According to MSDN. Not the exact collectiontype you are looking for, but nevertheless useful.
Edit: Apparently, if you supply the complete url to ParseQueryString it will add 'http://example.com/file?a' as the first key of the collection. Since that is probably not what you want, I added the substring to get only the relevant part of the url.
I had to do this for a modern windows app. I used the following:
public static class UriExtensions
{
private static readonly Regex _regex = new Regex(#"[?&](\w[\w.]*)=([^?&]+)");
public static IReadOnlyDictionary<string, string> ParseQueryString(this Uri uri)
{
var match = _regex.Match(uri.PathAndQuery);
var paramaters = new Dictionary<string, string>();
while (match.Success)
{
paramaters.Add(match.Groups[1].Value, match.Groups[2].Value);
match = match.NextMatch();
}
return paramaters;
}
}
Have a look at HttpUtility.ParseQueryString() It'll give you a NameValueCollection instead of a dictionary, but should still do what you need.
The other option is to use string.Split().
string url = #"http://example.com/file?a=1&b=2&c=string%20param";
string[] parts = url.Split(new char[] {'?','&'});
///parts[0] now contains http://example.com/file
///parts[1] = "a=1"
///parts[2] = "b=2"
///parts[3] = "c=string%20param"
For isolated projects, where dependencies must be kept to a minimum, I found myself using this implementation:
var arguments = uri.Query
.Substring(1) // Remove '?'
.Split('&')
.Select(q => q.Split('='))
.ToDictionary(q => q.FirstOrDefault(), q => q.Skip(1).FirstOrDefault());
Do note, however, that I do not handle encoded strings of any kind, as I was using this in a controlled setting, where encoding issues would be a coding error on the server side that should be fixed.
In a single line of code:
string xyz = Uri.UnescapeDataString(HttpUtility.ParseQueryString(Request.QueryString.ToString()).Get("XYZ"));
Microsoft Azure offers a framework that makes it easy to perform this.
http://azure.github.io/azure-mobile-services/iOS/v2/Classes/MSTable.html#//api/name/readWithQueryString:completion:
You could reference System.Web in your console application and then look for the Utility functions that split the URL parameters.

Categories

Resources