26 Commits
1.0.0 ... 1.3.0

Author SHA1 Message Date
khyteang-lim
9b1d037a88 Added ToEscapeString() and ToEscapeDataString() (#11)
* Added ToEscapeString() and ToEscapeDataString(), added desciption in readme, and added unit tests

* added changes from PR feedback
2017-01-30 17:42:11 -05:00
Tommy Parnell
be92d91ef6 readd 461 2016-12-13 13:47:17 -05:00
Tommy Parnell
a1527c058c add path and query 2016-12-13 13:44:06 -05:00
Tommy Parnell
908d0e2433 target 45 2016-12-13 10:57:40 -05:00
Tommy Parnell
e9f3e5ed8b target 40 2016-12-06 07:48:41 -05:00
Tommy Parnell
8b053f0f77 minor doc comment 2016-11-12 16:58:01 -05:00
Tommy Parnell
b68af327ab Merge pull request #8 from TerribleDev/1.1
1.1
2016-11-12 16:52:02 -05:00
Tommy Parnell
68bf719c27 Merge pull request #7 from TerribleDev/dictOfParams
Dict of params
2016-11-12 16:49:50 -05:00
Tommy Parnell
3ff3165a42 add exception throw test 2016-11-12 16:40:22 -05:00
Tommy Parnell
16f96b9b27 add dictionary of params 2016-11-12 16:38:10 -05:00
Tommy Parnell
04e2090a95 Merge pull request #5 from TerribleDev/documentation
add docs issue #4
2016-11-12 16:25:34 -05:00
Tommy Parnell
6e3e23061a add docs issue #4 2016-11-12 14:17:46 -05:00
Tommy Parnell
91579a1700 fix nuget package url 2016-11-09 09:35:56 -05:00
Tommy Parnell
d6c78f2193 retarget to 4.5 2016-11-09 09:32:44 -05:00
Tommy Parnell
dbb9f5b404 english 2016-11-09 07:28:29 -05:00
Tommy Parnell
5bfe876f57 add comma 2016-11-09 07:28:08 -05:00
Tommy Parnell
6a31a1968e readme 2016-11-09 07:27:32 -05:00
Tommy Parnell
43bcbb3c30 add project url 2016-11-09 07:23:42 -05:00
Tommy Parnell
c66614c2fe finish up tests 2016-11-08 23:20:57 -05:00
Tommy Parnell
2885118175 add missing tests 2016-11-08 23:14:28 -05:00
Tommy Parnell
9b5bd3769f add author 2016-11-08 22:36:11 -05:00
Tommy Parnell
0b1b20f5df add author 2016-11-08 22:33:31 -05:00
Tommy Parnell
a15ad38a86 im dumb 2016-11-08 22:31:11 -05:00
Tommy Parnell
0a14c742e1 appveyor tag things 2016-11-08 22:29:21 -05:00
Tommy Parnell
103bab1eb7 readme 2016-11-08 22:26:52 -05:00
Tommy Parnell
e1817ab447 dont try to publish other packages 2016-11-08 22:26:03 -05:00
8 changed files with 211 additions and 27 deletions

View File

@@ -1,3 +1,8 @@
if($env:APPVEYOR_REPO_TAG -eq "true")
{
"do not publish coverall data on tag builds"
return
}
nuget install OpenCover -Version 4.6.519 -OutputDirectory tools nuget install OpenCover -Version 4.6.519 -OutputDirectory tools
nuget install coveralls.net -Version 0.7.0 -OutputDirectory tools nuget install coveralls.net -Version 0.7.0 -OutputDirectory tools

View File

@@ -1,10 +1,16 @@
## UriBuilder.Fluent # UriBuilder.Fluent
[![Coverage Status](https://coveralls.io/repos/github/TerribleDev/UriBuilder.Fluent/badge.svg)](https://coveralls.io/github/TerribleDev/UriBuilder.Fluent) [![Build status](https://ci.appveyor.com/api/projects/status/cp704w3bgaerufxm/branch/master?svg=true)](https://ci.appveyor.com/project/tparnell8/uribuilder-fluent/branch/master)
This places extension methods over System.UriBuilder to help deal with query string parameters, and create more of a fluent interface. Unlike other projects this builds ontop of trusty UriBuilder, and does not use custom Uri generators, or have outside dependencies. This places extension methods over System.UriBuilder to help deal with query string parameters, and create more of a fluent interface. Unlike other projects, this NetStandardLibrary compliant package builds ontop of trusty UriBuilder, does not use custom Uri generators, or have outside dependencies. Unit tests continue to be a first class citizen!
## Getting started
Just install the nuget package `install-package UriBuilder.Fluent` and thats it. The extension methods should be available to you!
## Code Example
This lets you do things like This lets you do things like
```csharp ```csharp
new UriBuilder() new UriBuilder()
@@ -15,8 +21,6 @@ new UriBuilder()
.UseHttps() .UseHttps()
.ToString() .ToString()
``` ```
result: `https://awesome.com/seg?awesome=yodawg&fun=cool,yay` result: `https://awesome.com/seg?awesome=yodawg&fun=cool,yay`
@@ -28,7 +32,50 @@ new UriBuilder("https://awesome.com/yo)
.WithParameter("id", "5") .WithParameter("id", "5")
.ToString(); .ToString();
```
result: `https://awesome.com/yo?id=5`
you can even pass a dictionary of parameters
```csharp
var dictionary = new Dictionary<string, string>()
{
["yo"] = "dawg"
};
new UriBuilder("http://awesome.com")
.WithParameter(dictionary);
``` ```
result: `https://awesome.com/yo?id=5` result: `http://awesome.com/?yo=dawg`
### ToEscapeString() vs. ToEscapeDataString()
There are two extension methods for performing Uri encoding.
#### ToEscapeString()
Performs encoding only on the Uri query string and returns the Uri as a string.
```csharp
var uri = new UriBuilder("https://awesome.com")
.WithParameter("yo", "dawg<")
.ToEscapeString();
```
result: `http://awesome.com/?yo=dawg%3C`
#### ToEscapeDataString()
Performs encoding on the whole Uri and returns the Uri as a string.
```csharp
var uri = new UriBuilder("https://awesome.com")
.WithParameter("yo", "dawg<")
.ToEscapeDataString();
```
result: `http%3A%2F%2Fawesome.com%2F%3Fyo%3Ddawg%3C`

View File

@@ -4,7 +4,7 @@ nuget:
account_feed: true account_feed: true
project_feed: true project_feed: true
artifacts: artifacts:
- path: '**\*.nupkg' - path: 'src\**\*.nupkg'
init: init:
- git config --global core.autocrlf true - git config --global core.autocrlf true
@@ -17,14 +17,14 @@ build_script:
- ps: dotnet restore - ps: dotnet restore
- ps: dotnet build -c Release .\src\UriBuilder.Fluent - ps: dotnet build -c Release .\src\UriBuilder.Fluent
- ps: dotnet build -c Release .\src\UriBuilder.Fluent.UnitTests - ps: dotnet build -c Release .\src\UriBuilder.Fluent.UnitTests
- ps: .\update-projectjson.ps1
- ps: dotnet restore
- ps: dotnet pack -c Release .\src\UriBuilder.Fluent
test_script: test_script:
- ps: dotnet test -c Release .\src\UriBuilder.Fluent.UnitTests - ps: dotnet test -c Release .\src\UriBuilder.Fluent.UnitTests
- ps: .\Coverage.ps1 - ps: .\Coverage.ps1
- ps: .\update-projectjson.ps1
- ps: dotnet restore
- ps: dotnet pack -c Release .\src\UriBuilder.Fluent
deploy: deploy:
- provider: NuGet - provider: NuGet

View File

@@ -35,6 +35,17 @@ namespace FluentUriBuilder.Tests
.WithParameter("awesome", "yodawg"); .WithParameter("awesome", "yodawg");
Assert.Equal("http://awesome.com/?awesome=yodawg", url.Uri.ToString()); Assert.Equal("http://awesome.com/?awesome=yodawg", url.Uri.ToString());
} }
[Fact]
public void PathAndQuery()
{
var url = new UriBuilder().WithPathSegment("/awesome/v1/").WithParameter("awesome", "cool").PathAndQuery();
Assert.Equal("/awesome/v1/?awesome=cool", url);
url = new UriBuilder().WithPathSegment("/awesome/v1").WithParameter("awesome", "cool").PathAndQuery();
Assert.Equal("/awesome/v1?awesome=cool", url);
url = new UriBuilder().WithPathSegment("/awesome/v1").PathAndQuery();
Assert.Equal("/awesome/v1", url);
}
[Fact] [Fact]
public void TestAddParameterArray() public void TestAddParameterArray()
@@ -97,6 +108,16 @@ namespace FluentUriBuilder.Tests
Assert.Equal(url.Host, "yodawg.com"); Assert.Equal(url.Host, "yodawg.com");
} }
[Fact]
public void AddParamWithNoValue()
{
var url = new UriBuilder("http://awesome.com")
.WithParameter("awesome", "yodawg")
.WithParameter("fun", null)
.WithParameter("cool", string.Empty);
Assert.Equal("http://awesome.com/?awesome=yodawg&fun&cool", url.Uri.ToString());
}
[Fact] [Fact]
public void TestAddTwoUrlParameters() public void TestAddTwoUrlParameters()
{ {
@@ -106,5 +127,35 @@ namespace FluentUriBuilder.Tests
.WithParameter("supgf", "no22"); .WithParameter("supgf", "no22");
Assert.Equal("http://awesome.com/?awesome=yodawg&supg=no2&supgf=no22", url.Uri.ToString()); Assert.Equal("http://awesome.com/?awesome=yodawg&supg=no2&supgf=no22", url.Uri.ToString());
} }
[Fact]
public void AddDictOfParams()
{
var dictionary = new Dictionary<string, string>()
{
["yo"] = "dawg",
["troll"] = "toll",
["hammer"] = string.Empty
};
var url = new UriBuilder("http://awesome.com")
.WithParameter(dictionary);
Assert.Equal("http://awesome.com/?yo=dawg&troll=toll&hammer", url.Uri.ToString());
}
[Fact]
public void TestToEscapedString()
{
var url = new UriBuilder("http://awesome.com")
.WithParameter("yo","dawg<");
Assert.Equal("http://awesome.com/?yo=dawg%3C", url.ToEscapeString());
}
[Fact]
public void TestToEscapedDataString()
{
var url = new UriBuilder("http://awesome.com")
.WithParameter("yo","dawg<");
Assert.Equal("http%3A%2F%2Fawesome.com%2F%3Fyo%3Ddawg%3C", url.ToEscapeDataString());
}
} }
} }

View File

@@ -16,6 +16,7 @@ namespace FluentUriBuilder.Tests
Assert.Throws<ArgumentNullException>(() => tstObj.WithPathSegment(null)); Assert.Throws<ArgumentNullException>(() => tstObj.WithPathSegment(null));
Assert.Throws<ArgumentNullException>(() => tstObj.WithScheme(null)); Assert.Throws<ArgumentNullException>(() => tstObj.WithScheme(null));
Assert.Throws<ArgumentNullException>(() => tstObj.WithHost(null)); Assert.Throws<ArgumentNullException>(() => tstObj.WithHost(null));
Assert.Throws<ArgumentNullException>(() => tstObj.WithParameter(parameterDictionary: null));
Assert.Throws<ArgumentOutOfRangeException>(() => tstObj.WithPort(-1)); Assert.Throws<ArgumentOutOfRangeException>(() => tstObj.WithPort(-1));
} }
} }

View File

@@ -9,7 +9,7 @@
}, },
"frameworks": { "frameworks": {
"net461": {}, "net461":{},
"netcoreapp1.0": { "netcoreapp1.0": {
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": { "Microsoft.NETCore.App": {

View File

@@ -8,8 +8,39 @@ namespace System
{ {
public static class TerribleDevUriExtensions public static class TerribleDevUriExtensions
{ {
/// <summary>
/// Appends a query string parameter with a key, and many values. Multiple values will be comma seperated. If only 1 value is passed and its null or value, the key will be added to the QS.
/// </summary>
/// <param name="bld"></param>
/// <param name="key"></param>
/// <param name="values"></param>
/// <returns></returns>
public static UriBuilder WithParameter(this UriBuilder bld, string key, params string[] values) => bld.WithParameter(key, valuesEnum: values); public static UriBuilder WithParameter(this UriBuilder bld, string key, params string[] values) => bld.WithParameter(key, valuesEnum: values);
/// <summary>
/// Appends query strings from dictionary
/// </summary>
/// <param name="bld"></param>
/// <param name="parameterDictionary"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static UriBuilder WithParameter(this UriBuilder bld, IDictionary<string, string> parameterDictionary)
{
if(parameterDictionary == null) throw new ArgumentNullException(nameof(parameterDictionary));
foreach(var item in parameterDictionary)
{
bld.WithParameter(item.Key, item.Value);
}
return bld;
}
/// <summary>
/// Appends a query string parameter with a key, and many values. Multiple values will be comma seperated. If only 1 value is passed and its null or value, the key will be added to the QS.
/// </summary>
/// <param name="bld"></param>
/// <param name="key"></param>
/// <param name="valuesEnum"></param>
/// <returns></returns>
public static UriBuilder WithParameter(this UriBuilder bld, string key, IEnumerable<object> valuesEnum) public static UriBuilder WithParameter(this UriBuilder bld, string key, IEnumerable<object> valuesEnum)
{ {
if(string.IsNullOrWhiteSpace(key)) if(string.IsNullOrWhiteSpace(key))
@@ -20,8 +51,7 @@ namespace System
{ {
valuesEnum = new string[0]; valuesEnum = new string[0];
} }
var isfirst = string.IsNullOrWhiteSpace(bld.Query); var intitialValue = string.IsNullOrWhiteSpace(bld.Query) ? "" : $"{bld.Query.TrimStart('?')}&";
var intitialValue = isfirst ? "" : $"{bld.Query.TrimStart('?')}&";
var sb = new StringBuilder($"{intitialValue}{key}"); var sb = new StringBuilder($"{intitialValue}{key}");
var validValueHit = false; var validValueHit = false;
foreach(var value in valuesEnum) foreach(var value in valuesEnum)
@@ -37,6 +67,13 @@ namespace System
return bld; return bld;
} }
/// <summary>
/// Sets the port to be the port number
/// </summary>
/// <param name="bld"></param>
/// <param name="port"></param>
/// <exception cref="ArgumentOutOfRangeException">Throws if port is less than one</exception>
/// <returns></returns>
public static UriBuilder WithPort(this UriBuilder bld, int port) public static UriBuilder WithPort(this UriBuilder bld, int port)
{ {
if(port < 1) throw new ArgumentOutOfRangeException(nameof(port)); if(port < 1) throw new ArgumentOutOfRangeException(nameof(port));
@@ -44,6 +81,13 @@ namespace System
return bld; return bld;
} }
/// <summary>
/// appends a path segment to the path. Can be called multiple times to append multiple segments
/// </summary>
/// <param name="bld"></param>
/// <param name="pathSegment"></param>
/// <exception cref="ArgumentNullException">You pass a string as a path segment</exception>
/// <returns></returns>
public static UriBuilder WithPathSegment(this UriBuilder bld, string pathSegment) public static UriBuilder WithPathSegment(this UriBuilder bld, string pathSegment)
{ {
if(string.IsNullOrWhiteSpace(pathSegment)) if(string.IsNullOrWhiteSpace(pathSegment))
@@ -51,15 +95,17 @@ namespace System
throw new ArgumentNullException(nameof(pathSegment)); throw new ArgumentNullException(nameof(pathSegment));
} }
var path = pathSegment.TrimStart('/'); var path = pathSegment.TrimStart('/');
if(string.IsNullOrWhiteSpace(bld.Path))
{
bld.Path = path;
return bld;
}
bld.Path = $"{bld.Path.TrimEnd('/')}/{path}"; bld.Path = $"{bld.Path.TrimEnd('/')}/{path}";
return bld; return bld;
} }
/// <summary>
/// Sets your Uri Scheme
/// </summary>
/// <param name="bld"></param>
/// <param name="scheme"></param>
/// <exception cref="ArgumentNullException">You must pass a scheme</exception>
/// <returns></returns>
public static UriBuilder WithScheme(this UriBuilder bld, string scheme) public static UriBuilder WithScheme(this UriBuilder bld, string scheme)
{ {
if(string.IsNullOrWhiteSpace(scheme)) throw new ArgumentNullException(nameof(scheme)); if(string.IsNullOrWhiteSpace(scheme)) throw new ArgumentNullException(nameof(scheme));
@@ -67,6 +113,13 @@ namespace System
return bld; return bld;
} }
/// <summary>
///
/// </summary>
/// <param name="bld"></param>
/// <param name="host"></param>
/// <exception cref="ArgumentNullException">You must pass a ho0st</exception>
/// <returns></returns>
public static UriBuilder WithHost(this UriBuilder bld, string host) public static UriBuilder WithHost(this UriBuilder bld, string host)
{ {
if(string.IsNullOrWhiteSpace(host)) throw new ArgumentNullException(nameof(host)); if(string.IsNullOrWhiteSpace(host)) throw new ArgumentNullException(nameof(host));
@@ -74,10 +127,33 @@ namespace System
return bld; return bld;
} }
public static string PathAndQuery(this UriBuilder bld) => (bld.Path + bld.Query);
/// <summary>
/// Use Https?
/// </summary>
/// <param name="bld"></param>
/// <param name="predicate">default true, if false sets scheme to http</param>
/// <returns></returns>
public static UriBuilder UseHttps(this UriBuilder bld, bool predicate = true) public static UriBuilder UseHttps(this UriBuilder bld, bool predicate = true)
{ {
bld.Scheme = predicate ? "https" : "http"; bld.Scheme = predicate ? "https" : "http";
return bld; return bld;
} }
/// <summary>
/// Escape Url query string
/// </summary>
/// <param name="bld"></param>
/// <returns></returns>
public static string ToEscapeString(this UriBuilder bld) => Uri.EscapeUriString(bld.Uri.ToString());
/// <summary>
/// Escape the whole Url string
/// </summary>
/// <param name="bld"></param>
/// <returns></returns>
public static string ToEscapeDataString(this UriBuilder bld) => Uri.EscapeDataString(bld.Uri.ToString());
} }
} }

View File

@@ -4,9 +4,7 @@
"owners": [ "owners": [
"Tommy Parnell" "Tommy Parnell"
], ],
"repository": { "projectUrl": "https://github.com/TerribleDev/UriBuilder.Fluent",
"url":"https://github.com/TerribleDev/UriBuilder.Fluent"
},
"summary": "Fluent extensions for UriBuilder", "summary": "Fluent extensions for UriBuilder",
"tags": [ "tags": [
"Url building", "Url building",
@@ -16,13 +14,19 @@
"extension" "extension"
] ]
}, },
"dependencies": { "authors": [
"NETStandard.Library": "1.6.0" "Tommy Parnell"
}, ],
"frameworks": { "frameworks": {
"netstandard1.3": { "netstandard1.1": {
"imports": "dnxcore50",
"dependencies": {
"NETStandard.Library": "1.6.0"
}
},
"net40": {
"imports": "dnxcore50" "imports": "dnxcore50"
} },
"net45":{}
} }
} }