Codebelt

Cuemon.Extensions.Collections.Specialized

Bridge multi-valued dictionaries and NameValueCollection without rewriting the surrounding pipeline.

.NET 10.0 / .NET 9.0 MIT v10.5.3 37,178 downloads

Overview

Cuemon.Extensions.Collections.Specialized adds the conversion layer between IDictionary<string, string[]> and NameValueCollection. It extends Cuemon.Collections.Specialized with a small set of extension methods so code that models repeated values as arrays can still interoperate with APIs built on System.Collections.Specialized.

The package is intentionally narrow. Its public surface focuses on converting between the two collection shapes and on case-insensitive key detection for NameValueCollection, which makes it useful at boundaries such as query-string, header, or form-style adapters.

Key APIs

DictionaryExtensions.ToNameValueCollection converts an IDictionary<string, string[]> into a NameValueCollection. The optional Action<DelimitedStringOptions<string>> delegate lets callers align how array values are flattened before the collection is handed to downstream code.

NameValueCollectionExtensions.ToDictionary rebuilds an IDictionary<string, string[]> from a NameValueCollection. Its optional Action<DelimitedStringOptions> delegate controls how delimited values are split back into arrays during the conversion.

NameValueCollectionExtensions.ContainsKey checks whether a NameValueCollection contains a key using StringComparison.OrdinalIgnoreCase. It first tries Get(key) and then falls back to scanning AllKeys, which covers entries whose lookup returns null.

Basic usage

using System.Collections.Generic;
using System.Collections.Specialized;
using Codebelt.Extensions.Xunit;
using Cuemon.Extensions.Collections.Specialized;
using Xunit;

namespace Contoso.Search.Tests;

public class FilterCollectionBridgeTest : Test
{
    public FilterCollectionBridgeTest(ITestOutputHelper output) : base(output)
    {
    }

    [Fact]
    public void ShouldRoundTripRepeatedFiltersThroughNameValueCollection()
    {
        IDictionary<string, string[]> filters = new Dictionary<string, string[]>
        {
            ["category"] = new[] { "books", "games" },
            ["sort"] = new[] { "published" }
        };

        NameValueCollection request = filters.ToNameValueCollection();
        IDictionary<string, string[]> restored = request.ToDictionary();

        TestOutput.WriteLine("Serialized category filter: " + request.Get("category"));
        Assert.True(request.ContainsKey("CATEGORY"));
        Assert.Equal(new[] { "books", "games" }, restored["category"]);
        Assert.Equal(new[] { "published" }, restored["sort"]);
    }
}

Use this pattern when request or configuration data starts as IDictionary<string, string[]> but a downstream API still expects NameValueCollection. It matters because the package keeps repeated values and case-insensitive key checks explicit at the boundary instead of scattering ad hoc parsing code through the caller.

Installation

dotnet add package Cuemon.Extensions.Collections.Specialized

Usage guidance

Adopt this package when a boundary in your application needs to move repeated values between NameValueCollection and dictionary-based models. If your code already stays on one side of that boundary, plain framework collections are simpler and you can skip the extra conversion layer.

Family packages