Introduction
If you build a lot of URLs in .NET, you've probably found that it can be get a bit cumbersome. You start with basic string
building. But even with proper use of String.Format
, dealing optional parameters and URL encoding still gets messy quickly. You can't help but think there must be a better way.
At some point, you discover UriBuilder and think all your problems are solved. But you quickly realize that while UriBuilder
is great for assembling the bits on the left side of the URL (host, port, scheme, etc.), it offers little help on the right side (path segments and query string), and that's where all the variability tends to be. You find that most of the time you're starting with a config setting or fixed constant representing some "base" URL, and regress back to string-building to construct the rest.
Sound familiar? Maybe you've rolled your own library to address some of these gaps. If not, you might want to check out Flurl. Flurl is a tiny library that sets out to solve these problems with as little "noise" as possible.
Show Me Some Code!
Here's what Flurl looks like:
using Flurl;
var url = "http://www.some-api.com"
.AppendPathSegments("path", "to", "endpoint")
.SetQueryParams(new {
api_key = ConfigurationManager.AppSettings["SomeApiKey"],
max_results = 20,
q = "Don't worry, I'll get encoded!"
});
If extension methods, fluent APIs, and anonymous objects are not your cup of tea, Flurl supports a more traditional style that gives you the same results:
Url url = new Url("http://www.some-api.com");
url.AppendPathSegment("endpoint");
url.QueryParams["api_key"] = ConfigurationManager.AppSettings["SomeApiKey"];
url.QueryParams["max_results"] = 20;
url.QueryParams["q"] = "Don't worry, I'll get encoded!";
There's also a singular version of AppendPathSegments
and SetQueryParams
:
url.AppendPathSegment("one").SetQueryParam("x", 5);
SetQueryParam(s)
overwrites existing values of the same name:
"http://mysite.com".SetQueryParams(new { x = 1, y = 2 }).SetQueryParam("y", 3);
In some rare cases, you might actually want the same key specified multiple times in the query string
. Pass an array of values to achieve this:
"http://mysite.com".SetQueryParam("x", new[] { 1, 2 });
When a null
value is passed to SetQueryParam(s)
, the key/value pair is excluded entirely. This behavior can be leveraged to help cut down on messy conditional logic.
"http://mysite.com".SetQueryParams(new { x = 1, y = null, z = 3 });
A URL object converts back to a string
implicitly. You can use ToString()
explicitly if you prefer, but the compiler won't complain if you don't:
Response.Redirect(url);
Flurl can also be used to parse an existing URL, again focusing on the "right side":
var url = new Url("http://site.com/some/long/path?x=1&y=2");
var path = url.Path;
var query = url.QueryParams;
var root = Url.GetRoot(url);
How often do you forget whether that "BaseURL
" app setting already contains a trailing slash? Wish there was an equivalent to Path.Combine
for URLs so you don't need to worry about it? Flurl gives you one:
var url = Url.Combine("http://foo.com/", "/too/", "/many/", "/slashes", "too", "few");
AppendPathSegment
has the same behavior with respect to ensuring there is one and only one separator between segments.
Encoding
Flurl takes care of encoding characters in URLs but takes a different approach with path segments than it does with query string
values. The assumption is that query string
values are highly variable (such as from user input), whereas path segments tend to be more "fixed" and may already be encoded, in which case you don't want to double-encode. Here are the rules Flurl follows:
- Query
string
values are fully URL-encoded. - For path segments, reserved characters such as / and % are not encoded.
- For path segments, illegal characters such as spaces are encoded.
- For path segments, the ? character is encoded, since query strings get special treatment.
Portability
Flurl is a portable class library, meaning you can use it in your Xamarin, Silverlight, and Windows Phone apps just as easily as applications targeting the "full" .NET framework.
Where Do I Get it?
Flurl is freely available on NuGet:
PM> Install-Package Flurl
Flurl.Http
There are many reasons you might need to build URLs. For me, it's mostly for the purpose of calling RESTful APIs. I built Flurl.Http
as companion library that allows you to seamlessly call the URL along the same fluent chain that you build it. It covers a lot of the same territory as other HTTP client libraries like RestSharp. I plan to cover Flurl.Http
in depth in a future article, but for now you can check out the main website for details.