How to parse a comma-separated string from app.config

I had to parse a list of comma-separated HTTP Response Codes from the app.config file and use them to retry HTTP POST requests if the response code was contained in that list.

This article explains how to parse a list of comma-separated values from the app.config and put them into a HashSet so it can be used as a lookup later on.

Add the right reference

  1. In your project > right-click References
  2. Add Reference
  3. Search for System.Configuration
  4. Check it > OK

The Code

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
  <appSettings>
    <add key="transientHttpErrorCodes" value="408,429,503"/>
  </appSettings>
</configuration>

Parser.cs

using System;
using System.Collections.Generic;

namespace HowToParseCSVIntoLookup
{
    public class Parser
    {
        public HashSet<int> ParseIntoLookup(string csv)
        { 
            var lookup = new HashSet<int>();

            if (string.IsNullOrEmpty(csv))
            {
                return lookup;
            }

            foreach (var value in csv.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                int tmp;
                if (Int32.TryParse(value, out tmp))
                {
                    lookup.Add(tmp);
                }
            }

            return lookup;
        }
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Configuration;

namespace HowToParseCSVIntoLookup
{
    class Program
    {
        static void Main(string[] args)
        {
            var csv = ConfigurationManager.AppSettings["transientHttpErrorCodes"];
            Parser parser = new Parser();

            HashSet<int> transientHttpErrorCodeLookup = parser.ParseIntoLookup(csv);

            //let's verify that we can use the lookup. 
            //Let's say we got error code 429 - Too Many Requests
            int testErrorCode = 429;
            bool shouldWeTryAgain = transientHttpErrorCodeLookup.Contains(testErrorCode);
            Console.WriteLine($"We received error code {testErrorCode}. Should we try again? {shouldWeTryAgain}");

            Console.ReadKey();
        }
    }
}

The Tests

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;

namespace HowToParseCSVIntoLookup.Tests
{
    [TestClass()]
    public class ParserTests
    {
        [TestMethod()]
        public void ParseIntoLookupTest_WhenCSVNull_ReturnsEmptySet()
        {
            //arrange
            Parser parser = new Parser();
            string csv = null;

            //act
            var actual = parser.ParseIntoLookup(csv);

            //assert
            Assert.IsFalse(actual.Any());
        }
        [TestMethod()]
        public void ParseIntoLookupTest_WhenCSVEmpty_ReturnsEmptySet()
        {
            //arrange
            Parser parser = new Parser();
            string csv = "";

            //act
            var actual = parser.ParseIntoLookup(csv);

            //assert
            Assert.IsFalse(actual.Any());
        }
        [TestMethod()]
        public void ParseIntoLookupTest_WhenIntegerCannotBeParsed_DueToSpaceInBetweenDigits_ItIsExcluded()
        {
            //arrange
            Parser parser = new Parser();
            string csv = "12 03";

            //act
            var actual = parser.ParseIntoLookup(csv);

            //assert
            Assert.IsFalse(actual.Any());
        }
        [TestMethod()]
        public void ParseIntoLookupTest_WhenIntegerCannotBeParsed_DueToNonNumericCharacter_ItIsExcluded()
        {
            //arrange
            Parser parser = new Parser();
            string csv = "12a";

            //act
            var actual = parser.ParseIntoLookup(csv);

            //assert
            Assert.IsFalse(actual.Any());
        }
        [TestMethod()]
        public void ParseIntoLookupTest_WhenIntegerCannotBeParsed_DueToExceedingMaxInt_ItIsExcluded()
        {
            //arrange
            Parser parser = new Parser();
            string csv = $"{Int32.MaxValue}0";

            //act
            var actual = parser.ParseIntoLookup(csv);

            //assert
            Assert.IsFalse(actual.Any());
        }
        [TestMethod()]
        public void ParseIntoLookupTest_WhenAnIntegerCanBeParsed_ItIsIncluded()
        {
            //arrange
            Parser parser = new Parser();
            string csv = "1";

            //act
            var actual = parser.ParseIntoLookup(csv);

            //assert
            Assert.IsTrue(actual.Contains(1), message: "Doesn't contain 1");
        }
        [TestMethod()]
        public void ParseIntoLookupTest_EmptyValues_AreExcluded()
        {
            //arrange
            Parser parser = new Parser();
            string csv = "1,,";

            //act
            var actual = parser.ParseIntoLookup(csv);

            //assert
            Assert.AreEqual(1, actual.Count);
        }
        [TestMethod()]
        public void ParseIntoLookupTest_WhenThereAreDuplicateIntegers_OnlyOneIsAdded()
        {
            //arrange
            Parser parser = new Parser();
            string csv = "1,1";

            //act
            var actual = parser.ParseIntoLookup(csv);

            //assert
            Assert.AreEqual(1, actual.Count);
            Assert.IsTrue(actual.Contains(1), message: "Doesn't contain 1");
        }

        [TestMethod()]
        public void ParseIntoLookupTest_WhenContainsMultipleCommaSeparated_ParsableIntegers_TheyAreIncluded()
        {
            //arrange
            List<int> expected = new List<int>()
            {
                1, 2, 3
            };
            Parser parser = new Parser();
            string csv = string.Join(",", expected);

            //act
            var actual = parser.ParseIntoLookup(csv);

            //assert
            CollectionAssert.AreEquivalent(expected, actual.ToList());
        }
    }
}

Leave a Comment