I use Stream reader to read context.Request.InputStream to the end and end up with a string looking like
"Gamestart=true&GamePlayer=8&CurrentDay=Monday&..."
What would be the most efficent/"clean" way to parse that in a C# console?
You can use HttpUtility.ParseQueryString
Little sample:
string queryString = "Gamestart=true&GamePlayer=8&CurrentDay=Monday"; //Hardcoded just for example
NameValueCollection qscoll = HttpUtility.ParseQueryString(querystring);
foreach (String k in qscoll.AllKeys)
{
//Prints result in output window.
System.Diagnostics.Debug.WriteLine(k + " = " + qscoll[k]);
}
HttpUtility.ParseQueryString
Parses a query string into a NameValueCollection using UTF8 encoding.
http://msdn.microsoft.com/en-us/library/ms150046.aspx
I know this is a bit of a zombie post but I thought I'd add another answer since HttpUtility adds another assembly reference (System.Web), which may be undesirable to some.
using System.Net;
using System.Text.RegularExpressions;
static readonly Regex HttpQueryDelimiterRegex = new Regex(#"\?", RegexOptions.Compiled);
static readonly Regex HttpQueryParameterDelimiterRegex = new Regex(#"&", RegexOptions.Compiled);
static readonly Regex HttpQueryParameterRegex = new Regex(#"^(?<ParameterName>\S+)=(?<ParameterValue>\S*)$", RegexOptions.Compiled);
static string GetPath(string pathAndQuery)
{
var components = HttpQueryDelimiterRegex.Split(pathAndQuery, 2);
return components[0];
}
static Dictionary<string, string> GetQueryParameters(string pathAndQuery)
{
var parameters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var components = HttpQueryDelimiterRegex.Split(pathAndQuery, 2);
if (components.Length > 1)
{
var queryParameters = HttpQueryParameterDelimiterRegex.Split(components[1]);
foreach(var queryParameter in queryParameters)
{
var match = HttpQueryParameterRegex.Match(queryParameter);
if (!match.Success) continue;
var parameterName = WebUtility.HtmlDecode(match.Groups["ParameterName"].Value) ?? string.Empty;
var parameterValue = WebUtility.HtmlDecode(match.Groups["ParameterValue"].Value) ?? string.Empty;
parameters[parameterName] = parameterValue;
}
}
return parameters;
}
I wish they would add that same method to WebUtility which is available in System.Net as of .NET 4.0.
Related
Suppose I had the following code in Python (yes, this question is about c# this is just an example)
string = "{entry1} {entry2} this is a string"
dictionary = {"entry1": "foo", "entry2": "bar"}
print(string.format(**dictionary))
# output is "foo bar this is just a string"
In this string, it would replace the {entry1} and {entry2} from the string to foo and bar using the .format()
Is there anyway I can replicate this EXACT same thing in C# (and also remove the curly braces) like the following code:
string str1 = "{entry1} {entry2} this a string";
Dictionary<string, string> dict1 = new() {
{"entry1", "foo"},
{"entry2", "bar"}
};
// how would I format this string using the given dict and get the same output?
using string interpolation you could do the following
Dictionary<string, string> dict1 = new() {
{"entry1", "foo"},
{"entry2", "bar"}
};
string result = $"{dict1["entry1"]} {dict1["entry2"]} this is a string";
You can write an extension method for a dictionary and in it manipulate your string as per your need Like
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public static class DictionaryExtensions
{
public static string ReplaceKeyInString(this Dictionary<string, string> dictionary, string inputString)
{
var regex = new Regex("{(.*?)}");
var matches = regex.Matches(inputString);
foreach (Match match in matches)
{
var valueWithoutBrackets = match.Groups[1].Value;
var valueWithBrackets = match.Value;
if(dictionary.ContainsKey(valueWithoutBrackets))
inputString = inputString.Replace(valueWithBrackets, dictionary[valueWithoutBrackets]);
}
return inputString;
}
}
Now use this extension method to convert given string to the expected string,
string input = "{entry1} {entry2} this is a string";
Dictionary<string, string> dictionary = new Dictionary<string, string>
{
{ "entry1", "foo" },
{ "entry2", "bar" }
};
var result = dictionary.ReplaceKeyInString(input);
Console.WriteLine(result);
RegEx logic credit goes to #Fabian Bigler. Here is Fabian's answer:
Get values between curly braces c#
Try online
You can replace values within {...} with a help of regular expressions:
using System.Text.RegularExpressions;
...
string str1 = "{entry1} {entry2} this a string";
Dictionary<string, string> dict1 = new() {
{ "entry1", "foo" },
{ "entry2", "bar" }
};
string result = Regex.Replace(str1, #"{([^}]+)}",
m => dict1.TryGetValue(m.Groups[1].Value, out var v) ? v : "???");
// Let's have a look:
Console.Write(result);
Outcome:
foo bar this a string
try this
foreach (var d in dict) str1=str1.Replace("{"+d.Key+"}",d.Value);
or if you like the extensions
Console.WriteLine(str1.FormatFromDictionary(dict));
public static string FormatFromDictionary(this string str, Dictionary<string, string> dict)
{
foreach (var d in dict) str = str.Replace("{" + d.Key + "}", d.Value);
return str;
}
You can use a string builder if there are may items to replace in one string
public static string FormatFromDictionary(this string str, Dictionary<string, string> dict)
{
StringBuilder sb = new StringBuilder(str, 100);
foreach (var d in dict) sb.Replace("{" + d.Key + "}", d.Value);
return sb.ToString();
}
I have this string:
http://www.edrdg.org/jmdictdb/cgi-bin/edform.py?svc=jmdict&sid=&q=1007040&a=2
How can I pick out the number between "q=" and "&" as an integer?
So in this case I want to get the number: 1007040
What you're actually doing is parsing a URI - so you can use the .Net library to do this properly as follows:
var str = "http://www.edrdg.org/jmdictdb/cgi-bin/edform.py?svc=jmdict&sid=&q=1007040&a=2";
var uri = new Uri(str);
var query = uri.Query;
var dict = System.Web.HttpUtility.ParseQueryString(query);
Console.WriteLine(dict["amp;q"]); // Outputs 1007040
If you want the numeric string as an integer then you'd need to parse it:
int number = int.Parse(dict["amp;q"]);
Consider using regular expressions
String str = "http://www.edrdg.org/jmdictdb/cgi-bin/edform.py?svc=jmdict&sid=&q=1007040&a=2";
Match match = Regex.Match(str, #"q=\d+&");
if (match.Success)
{
string resultStr = match.Value.Replace("q=", String.Empty).Replace("&", String.Empty);
int.TryParse(resultStr, out int result); // result = 1007040
}
Seems like you want a query parameter for a uri that's html encoded. You could do:
Uri uri = new Uri(HttpUtility.HtmlDecode("http://www.edrdg.org/jmdictdb/cgi-bin/edform.py?svc=jmdict&sid=&q=1007040&a=2"));
string q = HttpUtility.ParseQueryString(uri.Query).Get("q");
int qint = int.Parse(q);
A regex approach using groups:
public int GetInt(string str)
{
var match = Regex.Match(str,#"q=(\d*)&");
return int.Parse(match.Groups[1].Value);
}
Absolutely no error checking in that!
This question already has answers here:
Is there a "String.Format" that can accept named input parameters instead of index placeholders? [duplicate]
(9 answers)
Closed 4 years ago.
I'm trying to format some string dynamically with available variables in a specific context/scope.
This strings would have parts with things like {{parameter1}}, {{parameter2}} and these variables would exist in the scope where I'll try to reformat the string. The variable names should match.
I looked for something like a dynamically string interpolation approach, or how to use FormattableStringFactory, but I found nothing that really gives me what I need.
var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{{parameter2}} Today we're {{parameter1}}";
var result = MagicMethod(retrievedString, parameter1, parameter2);
// or, var result = MagicMethod(retrievedString, new { parameter1, parameter2 });
Is there an existing solution or should I (in MagicMethod) replace these parts in the retrievedString with matching members of the anonymous object given as parameter (using reflection or something like that)?
EDIT:
Finally, I created an extension method to handle this:
internal static string SpecialFormat(this string input, object parameters) {
var type = parameters.GetType();
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex( "\\{(.*?)\\}" );
var sb = new System.Text.StringBuilder();
var pos = 0;
foreach (System.Text.RegularExpressions.Match toReplace in regex.Matches( input )) {
var capture = toReplace.Groups[ 0 ];
var paramName = toReplace.Groups[ toReplace.Groups.Count - 1 ].Value;
var property = type.GetProperty( paramName );
if (property == null) continue;
sb.Append( input.Substring( pos, capture.Index - pos) );
sb.Append( property.GetValue( parameters, null ) );
pos = capture.Index + capture.Length;
}
if (input.Length > pos + 1) sb.Append( input.Substring( pos ) );
return sb.ToString();
}
and I call it like this:
var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{parameter2} Today we're {parameter1}";
var result = retrievedString.SpecialFormat( new { parameter1, parameter2 } );
Now, I don't use double braces anymore.
You can use reflection coupled with an anonymous type to do this:
public string StringFormat(string input, object parameters)
{
var properties = parameters.GetType().GetProperties();
var result = input;
foreach (var property in properties)
{
result = result.Replace(
$"{{{{{property.Name}}}}}", //This is assuming your param names are in format "{{abc}}"
property.GetValue(parameters).ToString());
}
return result;
}
And call it like this:
var result = StringFormat(retrievedString, new { parameter1, parameter2 });
While not understanding what is the dificulty you're having, I'm placing my bet on
Replace( string oldValue, string newValue )
You can replace your "tags" with data you want.
var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{{parameter2}} Today we're {{parameter1}}";
var result = retrievedString.Replace("{{parameter2}}", parameter2).Replace({{parameter1}}, parameter1);
EDIT
Author mentioned that he's looking at something that will take parameters and iterate the list. It can be done by something like
public static void Main(string[] args)
{
//your "unmodified" srting
string text = "{{parameter2}} Today we're {{parameter1}}";
//key = tag(explicitly) value = new string
Dictionary<string, string> tagToStringDict = new Dictionary<string,string>();
//add tags and it's respective replacement
tagToStringDict.Add("{{parameter1}}", "Foo");
tagToStringDict.Add("{{parameter2}}", "Bar");
//this returns your "modified string"
changeTagWithText(text, tagToStringDict);
}
public static string changeTagWithText(string text, Dictionary<string, string> dict)
{
foreach (KeyValuePair<string, string> entry in dict)
{
//key is the tag ; value is the replacement
text = text.Replace(entry.Key, entry.Value);
}
return text;
}
The function changeTagWithText will return:
"Bar Today we're Foo"
Using this method you can add all the tags to the Dictionary and it'll replace all automatically.
If you know order of parameters, you can use string.Format() method (msdn). Then, your code will look like:
var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{{0}} Today we're {{1}}";
var result = string.Format(retrievedString, parameter2, parameter1);
I am trying to remove empty url type parameters from a string using C#. My code sample is here.
public static string test ()
{
string parameters = "one=aa&two=&three=aaa&four=";
string pattern = "&[a-zA-Z][a-zA-Z]*=&";
string replacement = "";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(parameters, replacement);
return parameters;
}
public static void Main(string[] args)
{
Console.WriteLine(test());
}
I tried the code in rextester
output: one=aa&two=&three=aaa&four=
expected output: one=aa&three=aaa
You absolutely do not need to roll your own Regex for this, try using HttpUtility.ParseQueryString():
public static string RemoveEmptyUrlParameters(string input)
{
var results = HttpUtility.ParseQueryString(input);
Dictionary<string, string> nonEmpty = new Dictionary<string, string>();
foreach(var k in results.AllKeys)
{
if(!string.IsNullOrWhiteSpace(results[k]))
{
nonEmpty.Add(k, results[k]);
}
}
return string.Join("&", nonEmpty.Select(kvp => $"{kvp.Key}={kvp.Value}"));
}
Fiddle here
Regex:
(?:^|&)[a-zA-Z]+=(?=&|$)
This matches start of string or an ampersand ((?:^|&)) followed by at least one (english) letter ([a-zA-Z]+), an equal sign (=) and then nothing, made sure by the positive look-ahead ((?=&|$)) which matches end of string or a new parameter (started by &).
Code:
public static string test ()
{
string parameters = "one=aa&two=&three=aaa&four=";
string pattern = "(?:^|&)[a-zA-Z]+=(?=&|$)";
string replacement = "";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(parameters, replacement);
return result;
}
public static void Main(string[] args)
{
Console.WriteLine(test());
}
Note that this also returns the correct variable (as pointed out by Joel Anderson)
See it live here at ideone.
The results of the Regex replace is not returned by the function. The function returns the variable "parameters", which is never updated or changed.
string parameters = "one=aa&two=&three=aaa&four=";
...
string result = rgx.Replace(parameters, replacement);
return parameters;
....
Perhaps you meant
return results;
I am trying to customise a DevExpress grid filter.
Currently I return the data from my api, and so I need to parse the built in string which is returned from the grid.
An example of the filter string is;
StartsWith([name], 'test') And StartsWith([quantity], '12') And
StartsWith([id], '1') And StartsWith([date], '01/10/2015')
I would like to convert this to a Dictionary in the most efficient way?
You could use Regex for filtering the key/value pair outta your string and a simple foreach to prepare the dictionary.
This could be a solution:
public static Dictionary<string, object> FilterAPIData(string data)
{
var r = new Regex(#"\[\w+\], \'[\w/]+\'");
var result = r.Matches(data);
var dict = new Dictionary<string, object>();
foreach (Match item in result)
{
var val = item.Value.Split(',');
dict.Add(val[0], val[1]);
}
return dict;
}
Regex might be the best option for this, but I'll show you how to do it without Regex as it can be a bit difficult to understand.
Assuming your string will always be in this format you can do this:
string str = "StartsWith([name], 'test') And StartsWith([quantity], '12') And StartsWith([id], '1') And StartsWith([date], '01/10/2015')";
var strArray = str.Split(new string[]{"And "}, StringSplitOptions.None);
var dict = new Dictionary<string, string>();
foreach(var value in strArray)
{
dict.Add(GetStringBetween(value, "[", "]"), GetStringBetween(value, "'", "'"));
}
private string GetStringBetween(string value, string startDelim, string endDelim)
{
int first = value.IndexOf(startDelim) + startDelim.Length;
int last = value.LastIndexOf(endDelim);
return value.Substring(first, last - first);
}
//Output :
//name test
//quantity 12
//id 1
// date 01/10/2015
If there other formats the string can be in you can adjust as needed. I would also consider adding in more validation/error handling, but I will let you figure that out ;)