A safer and more readable way to build URI's in .NET
To build this new URI:
ftp://user:[email protected]:888/path/to/file?param1=val1¶m2=a%23value%26with%40weird%3fcharacters#fragment
Write:
var uri = FluentUriBuilder.Create()
.Scheme(UriScheme.Ftp)
.Credentials("user", "password")
.Host("example.com")
.Port(888)
.Path("path/to/file")
.QueryParams(new {
param1 = "val1",
param2 = "a#value&with@weird?characters"
})
.Fragment("fragment")
.ToString();
You often see code that creates URI's using simple string concatenation or format strings:
var valueWithWeirdCharacters = "a#value&with@weird?characters";
var badUri1 = "http://example.com/path?param1=" + valueWithWeirdCharacters + "¶m2=asdf";
var badUri2 = string.Format("http://example.com/path?param1={0}¶m2=asdf", valueWithWeirdCharacters);
The result is an invalid URI because the value of param1
is not escaped:
"http://example.com/path?param1=a#value&with@weird?characters¶m2=asdf"
One alternative is to escape each value using Uri.EscapeDataString
:
var correctUri = "http://example.com/path?param1=" +
Uri.EscapeDataString(valueWithWeirdCharacters) +
"¶m2=asdf";
But this quickly gets ugly when you have a lot of arguments, and it is easy to forget.
Enter System.UriBuilder
:
var valueWithWeirdCharacters = "a#value&with@weird?characters";
var uriBuilder = new UriBuilder("http://example.com/path");
var parameters = HttpUtility.ParseQueryString(string.Empty);
parameters["param1"] = valueWithWeirdCharacters;
parameters["param2"] = "asdf";
uriBuilder.Query = parameters.ToString();
var correctUri = uriBuilder.AbsoluteUri;
This is correct, but also the most complicated and unreadable of all of the above examples.
This is why I created FluentUriBuilder
: to allow creating URI's in a safe and readable way:
var valueWithWeirdCharacters = "a#value&with@weird?characters";
var uri = FluentUriBuilder
.From("http://example.com/path")
.QueryParam("param1", valueWithWeirdCharacters)
.QueryParam("param2", "asdf")
.ToString();
Query parameters can also be specified using an IDictionary<TKey, TValue>
:
var params = new Dictionary<string, string> {
{ "user", "averagejoe236" },
{ "apiKey", "af43af43rcfaf34xqf" }
};
var uri = FluentUriBuilder.Create()
.Scheme(UriScheme.Http)
.Host("facebook.com")
.Path("posts")
.QueryParams(params)
.ToString();
Or one by one, by calling .QueryParam("key", "value")
repeatedly:
var uri = FluentUriBuilder.Create()
.Scheme(UriScheme.Http)
.Host("google.com")
.Path("/")
.QueryParam("q", "FluentUriBuilder")
.QueryParam("source", "hp")
.ToString();
The latter can be used to specify more query parameters with the same name.
To modify an existing URI:
var uri = FluentUriBuilder.From("http://example.com/somepath?foo=bar#baz")
.Port(8080)
.Path("/otherpath")
.RemoveQueryParams()
.RemoveFragment()
.ToUri();
This example returns a System.Uri
instance instead of a string because of the .ToUri()
call at the end.
The project currently supports .NET 2.0+. .NET Core support is planned.