Replace {x} tokens in strings

13,105

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/

Share:
13,105
Admin
Author by

Admin

Updated on June 24, 2022

Comments

  • Admin
    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
    user2864740 over 10 years
    Nice way to borrow my replacement value ;-) Well, it is pretty simple to understand, so +1.
  • Elton
    Elton over 5 years
    Excellent package for this task.
  • Brady Moritz
    Brady Moritz over 3 years
    does this handle url encoding?
  • Brady Moritz
    Brady Moritz over 3 years
    It has URI processors built in, do you know if this handles url encoding automatically?
  • Edward Brey
    Edward Brey about 2 years
    This 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
    Edward Brey about 2 years
    A simplified Regex-based algorithm that takes replacements as strings is here.
  • Grundy
    Grundy about 2 years
    @EdwardBrey, this is feature, not a bug :-D
  • Edward Brey
    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
    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
    Edward Brey about 2 years
    It depends on the replacement values. For example, suppose optinfo is excludeFromReceipt:{publisher},{userId}, publisher is Acme, and userId is 14. With successive full-string replacements, you'd get ...&optinfo=excludeFromReceipt:Acme,14&publisher=Acme&msisdn‌​=14 instead of ...&optinfo=excludeFromReceipt:{publisher},{userId}&publishe‌​r=Acme&msisdn=14.
  • Edward Brey
    Edward Brey about 2 years
    Also 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
    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.