Replace {x} tokens in strings
Solution 1
A simple approach is to use a foreach
and a Dictionary
with a String.Replace
:
var values = new Dictionary<string, string> {
{ "{networkid}", "WHEEE!!" }
// etc.
};
var url = "http://api.example.com/sale?auth_user=xxxxx&auth_pass=xxxxx&networkid={networkid}&category=b2c&country=IT&pageid={pageid}&programid=133&saleid=1&m={master}&optinfo={optinfo}&publisher={publisher}&msisdn={userId}";
foreach(var key in values.Keys){
url = url.Replace(key,values[key]);
}
Solution 2
There is no standard way to "replace with dictionary values" in .NET. While there are a number of template engines, it's not very hard to write a small solution for such an operation. Here is an example which runs in LINQPad and utilizes a Regular Expression with a Match Evaluator.
As the result is a URL,
it is the callers responsibility to make sure all the supplied values are correctly encoded. I recommend using Uri.EscapeDataString
as appropriate .. but make sure to not double-encode, if it is processed elsewhere.
Additionally, the rules of what to do when no replacement is found should be tailored to need. If not-found replacements should be eliminated entirely along with the query string key, the following can expand the regular expression to @"\w+=({\w+})"
to also capture the parameter key in this specific template situation.
string ReplaceUsingDictionary (string src, IDictionary<string, object> replacements) {
return Regex.Replace(src, @"{(\w+)}", (m) => {
object replacement;
var key = m.Groups[1].Value;
if (replacements.TryGetValue(key, out replacement)) {
return Convert.ToString(replacement);
} else {
return m.Groups[0].Value;
}
});
}
void Main()
{
var replacements = new Dictionary<string, object> {
{ "networkid", "WHEEE!!" }
// etc.
};
var src = "http://api.example.com/sale?auth_user=xxxxx&auth_pass=xxxxx&networkid={networkid}&category=b2c&country=IT&pageid={pageid}&programid=133&saleid=1&m={master}&optinfo={optinfo}&publisher={publisher}&msisdn={userId}";
var res = ReplaceUsingDictionary(src, replacements);
// -> "http://api.example.com/sale?..&networkid=WHEEE!!&..&pageid={pageid}&..
res.Dump();
}
More advanced techniques, like reflection and transforms, are possible - but those should be left for the real template engines.
Solution 3
I am guessing you are trying to replace parameters in url
with your values. This can be done using C# HttpUtility.ParseQueryString
Get the CurrentURL from
var _myUrl = System.Web.HttpUtility.ParseQueryString(Request.RawUrl);
Read Parameter from your Query string
string value1 = _myUrl ["networkid"];
Write a value into the QueryString object.
_myUrl ["networkid"] = "Your Value";
and then finally turn it back into URL
var _yourURIBuilder= new UriBuilder(_myUrl );
_myUrl = _yourURIBuilder.ToString();
Solution 4
You can use this alos using LinQ
Dictionary<string, string> myVal = new Dictionary<string, string>();
myVal.Add("networkid", "1");
myVal.Add("pageid", "2");
myVal.Add("master", "3");
myVal.Add("optinfo", "4");
myVal.Add("publisher", "5");
myVal.Add("userId", "6");
string url = @"http://api.example.com/sale?auth_user=xxxxx&auth_pass=xxxxx&networkid={networkid}&category=b2c&country=IT&pageid={pageid}&programid=133&saleid=1&m={master}&optinfo={optinfo}&publisher={publisher}&msisdn={userId}";
myVal.Select(a => url = url.Replace(string.Concat("{", a.Key, "}"), a.Value)).ToList();
this line can do your required functionlity
myVal.Select(a => url = url.Replace(string.Concat("{", a.Key, "}"), a.Value)).ToList();
Solution 5
There is a Nuget called StringTokenFormatter that does this well https://www.nuget.org/packages/StringTokenFormatter/
Admin
Updated on June 24, 2022Comments
-
Admin almost 2 years
We have a template URL like:
http://api.example.com/sale?auth_user=xxxxx&auth_pass=xxxxx&networkid={networkid}&category=b2c&country=IT&pageid={pageid}&programid=133&saleid=1&m={master}&optinfo={optinfo}&publisher={publisher}&msisdn={userId}
and I have values for these constant tokens. How can replace all these tokens in C#?
-
user2864740 over 10 yearsNice way to borrow my replacement value ;-) Well, it is pretty simple to understand, so +1.
-
Elton over 5 yearsExcellent package for this task.
-
Brady Moritz over 3 yearsdoes this handle url encoding?
-
Brady Moritz over 3 yearsIt has URI processors built in, do you know if this handles url encoding automatically?
-
Edward Brey about 2 yearsThis algorithm runs slowly in time O(t * r) and will give incorrect results if one of the replacement values contains a token for later replacement. Details
-
Edward Brey about 2 yearsA simplified Regex-based algorithm that takes replacements as strings is here.
-
Grundy about 2 years@EdwardBrey, this is feature, not a bug :-D
-
Edward Brey about 2 years@Grundy That's funny because it's kind of true. Applying replacements recursively can be useful. To be clear, that would take a more sophisticated algorithm, one that rescanned for replacements as a second complete pass (and then again with subsequent passes until no replacements were left), to avoid missing recursive replacements occurring late in the template. It would also need to check for infinite recursion.
-
Grundy about 2 years@EdwardBrey, for now, here not a recursion, just one way replacing in loop by keys. Any way this just as simple as possibly solution :) Straight replacement without any regexp
-
Edward Brey about 2 yearsIt depends on the replacement values. For example, suppose
optinfo
isexcludeFromReceipt:{publisher},{userId}
,publisher
isAcme
, anduserId
is14
. With successive full-string replacements, you'd get ...&optinfo=excludeFromReceipt:Acme,14&publisher=Acme&msisdn=14
instead of ...&optinfo=excludeFromReceipt:{publisher},{userId}&publisher=Acme&msisdn=14
. -
Edward Brey about 2 yearsAlso worth noting is while, yes, using string.Replace is simpler in that it doesn't use Regex, it has its own complexity that a Regex-based approach avoids. Specifically, using string.Replace requires you manage your own iteration and variable mutation. Using Regex shields you from both making it simpler to prove correctness for all input cases.
-
user2864740 almost 2 years@EdwardBrey Indeed. Looking at the code above 5 years later, it appears I was still stuck on C#5 at the time.. many language improvements since.