Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a simple way to format query strings when using the .NET HttpClient class?

I have some code in different places where I have a Dictionary<string,string> containing parameters that needs to go on the query string. I've got some of my own code for formatting this so that it can be added to the end of the URL. Is there something built into this library that will do this for me?

like image 283
Brian Lyttle Avatar asked Oct 22 '25 08:10

Brian Lyttle


1 Answers

You might want to consider using UriTemplates to construct Uris. The syntax is specified in RFC6570. I wrote a library that has a nuget package here.

With UriTemplates you can not only fill in query parameters like,

    [Fact]
    public void ShouldAllowUriTemplateWithQueryParamsWithOneValue()
    {
        var template = new UriTemplate("http://example.org/foo{?bar,baz}");
        template.SetParameter("baz", "yo");


        var uriString = template.Resolve();
        Assert.Equal("http://example.org/foo?baz=yo", uriString);
    }

Don't worry if you don't supply a query string parameter, the token will be removed.

It also handles path parameters,

    [Fact]
    public void ShouldAllowUriTemplateWithMultiplePathSegmentParameter()
    {
        var template = new UriTemplate("http://example.org/foo/{bar}/baz/{blar}");
        template.SetParameter("bar", "yo");
        template.SetParameter("blar", "yuck");
        var uriString = template.Resolve();
        Assert.Equal("http://example.org/foo/yo/baz/yuck", uriString);
    }

and some really nifty stuff with parameters that are lists and dictionaries,

    [Fact]
    public void ShouldAllowListAndSingleValueInQueryParam()
    {
        var template = new UriTemplate("http://example.org{/id*}{?fields,token}");
        template.SetParameter("id", new List<string>() { "person", "albums" });
        template.SetParameter("fields", new List<string>() { "id", "name", "picture" });
        template.SetParameter("token", "12345");
        var uriString = template.Resolve();
        Assert.Equal("http://example.org/person/albums?fields=id,name,picture&token=12345", uriString);
    }

and it will handle all sorts of tricky URI encoding issues,

    [Fact]
    public void ShouldHandleUriEncoding()
    {
        var template = new UriTemplate("http://example.org/sparql{?query}");
        template.SetParameter("query", "PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?book ?who WHERE { ?book dc:creator ?who }");
        var uriString = template.Resolve();
        Assert.Equal("http://example.org/sparql?query=PREFIX%20dc%3A%20%3Chttp%3A%2F%2Fpurl.org%2Fdc%2Felements%2F1.1%2F%3E%20SELECT%20%3Fbook%20%3Fwho%20WHERE%20%7B%20%3Fbook%20dc%3Acreator%20%3Fwho%20%7D", uriString);
    }


    [Fact]
    public void ShouldHandleEncodingAParameterThatIsAUriWithAUriParameter()
    {
        var template = new UriTemplate("http://example.org/go{?uri}");
        template.SetParameter("uri", "http://example.org/?uri=http%3A%2F%2Fexample.org%2F");
        var uriString = template.Resolve();
        Assert.Equal("http://example.org/go?uri=http%3A%2F%2Fexample.org%2F%3Furi%3Dhttp%253A%252F%252Fexample.org%252F", uriString);
    }

The only item that still is not working is encoding double byte Unicode characters in URIs. There is also a preview release that is PCL library allow you to use it in WinRT and on Windows Phone.

like image 179
Darrel Miller Avatar answered Oct 24 '25 22:10

Darrel Miller