This is a work in progress
This repository provides packages to handle various aspects of HTTP calls, especially with HttpClient
.
The package provides a way to handle building URLs.
It aims to be easier to use than the .NET UriBuilder
.
This implementation can be used to build URLs on the fly.
Basic Usage
var builder = new UrlBuilder("http://mydomain.com/test?base=query")
.SetScheme("https")
.SetPort(4242)
.AddPath("hello/big")
.AddPath("world")
.AddQuery("this", "is")
.AddQuery("a", "test");
Uri url = builder.Build(); // https://mydomain.com:4242/test/hello/big/world?base=query&this=is&a=test
Query Parameter Usage
var builder = new UrlBuilder("https://mydomain.com")
.AddQuery("multiparam", "one", "two")
.AddQuery("multiparam", "three")
.AddQuery("queryWithoutValue");
Uri url = builder.Build(); // https://mydomain.com?multiparam=one&multiparam=two&multiparam=three&queryWithoutValue
Path Variables can also be used to later replace the variable you need. This is especially useful for ImmutableUrlBuilder
s.
var builder = new UrlBuilder("https://mydomain.com")
.AddPath("{Greet}")
.AddPath("world");
int i = 5;
if(i % 2 == 0)
{
builder = builder.WithPathValue("Greet", "hi");
}
else
{
builder = builder.WithPathValue("Greet", "hello");
}
Uri url = builder.Build(); // https://mydomain.com/hello/world
While the above used UrlBuilder
is efficient, it has the problem that the internal state may be modified, e.g. when setting a path.
var builder = new UrlBuilder("https://mydomain.com")
var builder2 = builder.AddPath("pathfor2")
var url1 = builder.Build(); // https://mydomain.com/pathfor2
var url2 = builder2.Build(); // https://mydomain.com/pathfor2
This is especially bug prone when the builder is initialized in the constructor and then further mutated in methods, e.g.
public MyClient
{
private UrlBuilder _urlBuilder;
public MyClient(IOptions<MyClientOptions> options)
{
_urlBuilder = new UrlBuilder(options.Value.Url)
.SetPort(8080)
.AddPath("orders");
}
public Order GetOrder(string orderId)
{
var url = _urlBuilder.AddPath(orderId).Build(); // ❌ may have multiple order ID paths when method called multiple times
// GET order ...
}
public List<Order> GetOrders()
{
var url = _urlBuilder.Build(); // ❌ may have one or more order IDs added as path when GetOrder was called before
// GET order ...
}
}
For these cases, the ImmutableUrlBuilder
can be used.
var builder = new ImmutableUrlBuilder("https://mydomain.com")
var builder2 = builder.AddPath("pathfor2")
var url1 = builder.Build(); // https://mydomain.com
var url2 = builder2.Build(); // https://mydomain.com/pathfor2
You also can switch from a normal UrlBuilder
to the ImmutableUrlBuilder
using the AsImmutable()
-method.
Using above MyClient
-example, you may use this pattern:
public MyClient
{
private ImmutableUrlBuilder _urlBuilder;
public MyClient(IOptions<MyClientOptions> options)
{
_urlBuilder = new UrlBuilder(options.Value.Url) // e.g. https://my-domain.com
.SetPort(8080)
.AddPath("orders")
.AsImmutable();
}
public Order GetOrder(string orderId)
{
var url = _urlBuilder.AddPath(orderId).Build(); // URL will always be https://my-domain.com/orders/<orderId>
// GET order ...
}
public List<Order> GetOrders()
{
var url = _urlBuilder.Build(); // URL will always be https://my-domain.com/orders
// GET order ...
}
}