15 Commits
1.5.1 ... 2.2.0

Author SHA1 Message Date
Tommy Parnell
628f66b82a Merge pull request #25 from TerribleDev/pr-24
PR-24
2023-10-19 18:28:48 -04:00
Tommy Parnell
abb2c1d18b exclude macos ds_store, and format code 2023-10-19 18:26:35 -04:00
Tommy Parnell
c67a34f993 Merge remote-tracking branch 'origin/master' into pr-24 2023-10-19 18:25:54 -04:00
Tony Valenti
697a745510 Simplified tests and added automatic encoding of name/value pairs. 2023-10-19 17:03:45 -05:00
Tony Valenti
7e303fd08b Better Logo and it is transparent. (#22) #patch 2023-10-08 12:41:04 -04:00
Tony Valenti
737c647cbe Better Logo and it is transparent. 2023-07-12 18:25:03 -05:00
Tommy Parnell
730ee07822 add tuple api back that was accidentally removed (#21) 2023-07-12 15:51:23 -04:00
Tommy Parnell
ccf3a7a688 I hate ci #major 2023-07-12 15:37:39 -04:00
Tommy Parnell
3f7df6e00e #major Add overload for IEnumerable<KeyValuePair<string, string>>
#major

* Added overload for IEnumerable<KeyValuePair<string, string>>
* Updated to netstandard 2.0
* Added package icon
2023-07-12 15:31:44 -04:00
Tommy Parnell
22f9a8e64b update tests add github actions 2023-07-12 14:18:56 -04:00
Tony Valenti
6c9a2904a6 Use NetStandard instead of explicit versions. 2023-07-12 08:43:34 -05:00
Tony Valenti
d8bd1ce612 Updated Appveyor. I think. 2023-07-11 21:52:01 -05:00
Tony Valenti
aa1e0600da Updated versions
Added overload for IEnumerable<KeyValuePair<string, string>>
Added icon
Standardized {'s around validation
2023-07-11 21:48:44 -05:00
Tommy Parnell
819235eedb Merge pull request #17 from TerribleDev/nullchk
null checks
2018-04-14 18:06:28 -04:00
Tommy Parnell
d3a9225930 null checks 2018-04-14 18:00:53 -04:00
18 changed files with 412 additions and 158 deletions

44
.github/workflows/pr.yml vendored Normal file
View File

@@ -0,0 +1,44 @@
name: PR Build
on:
pull_request:
branches:
- master
jobs:
# dotnet test
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.x.x
- name: Build
run: make build
- name: Test
run: make test
pack:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.x.x
- name: Pack
run: VERSION=0.0.1 make pack
- name: Upload Build Artifacts
uses: actions/upload-artifact@v3
with:
name: pr-build-${{ github.event.pull_request.number }}-${{ github.sha }}
path: ./output/**
check-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.x.x
- name: Check Format
run: make check-format

73
.github/workflows/publish.yml vendored Normal file
View File

@@ -0,0 +1,73 @@
name: Publish
on:
push:
branches:
- master
jobs:
check-format:
environment: master
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.x.x
- name: Check Format
run: make check-format
test:
environment: master
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.x.x
- name: Build
run: make build
- name: Test
run: make test
- name: Upload Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./src/UriBuilder.Fluent.UnitTests/coverage.info
tag:
needs: [check-format, test]
outputs:
tagVersion: ${{ steps.tagVersion.outputs.new_tag }}
runs-on: ubuntu-latest
environment: master
steps:
- name: Checkout source code
uses: actions/checkout@v3
- name: Bump version and push tag
uses: anothrNick/github-tag-action@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WITH_V: false
DEFAULT_BUMP: minor
id: tagVersion
build:
env:
VERSION: ${{ needs.tag.outputs.tagVersion }}
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
runs-on: ubuntu-latest
environment: master
needs: [check-format, test, tag]
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.x.x
- name: Build and Pack
run: make pack
- name: Upload Build Artifacts
uses: actions/upload-artifact@v3
with:
name: release-build-${{ needs.tag.outputs.tagVersion }}
path: ./output/**
- name: Publish to NuGet
run: make publish

7
.gitignore vendored
View File

@@ -148,6 +148,7 @@ publish/
# NuGet Packages
*.nupkg
*.snupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
@@ -243,3 +244,9 @@ ModelManifest.xml
# FAKE - F# Make
.fake/
.idea
coverage.opencover.xml
coverage.json
coverage.info
.DS_Store
output

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"dotnet.defaultSolution": "UriBuilder.Fluent.sln"
}

View File

@@ -1,11 +0,0 @@
if($env:APPVEYOR_REPO_TAG -eq "true")
{
"do not publish coverall data on tag builds"
return
}
nuget install OpenCover -Source https://api.nuget.org/v3/index.json -Version 4.6.519 -OutputDirectory tools
nuget install coveralls.net -Source https://api.nuget.org/v3/index.json -Version 0.7.0 -OutputDirectory tools
.\tools\OpenCover.4.6.519\tools\OpenCover.Console.exe -oldStyle -target:"C:\Program Files\dotnet\dotnet.exe" -targetargs:" test "".\src\UriBuilder.Fluent.UnitTests\UriBuilder.Fluent.UnitTests.csproj"" -f net461 --no-build" -register:user -filter:"+[UriBuilder*]* -[*Tests]*" -returntargetcode -output:opencover_results.xml
.\tools\coveralls.net.0.7.0\tools\csmacnz.Coveralls.exe --opencover -i .\opencover_results.xml

21
Makefile Normal file
View File

@@ -0,0 +1,21 @@
clean:
dotnet clean && rm -rf ./**/bin ./**/obj && rm -rf output
build: clean restore
dotnet build --no-restore
restore: clean
dotnet restore
test:
dotnet test /p:CollectCoverage=true
release-build: clean restore
dotnet build -c Release --no-restore
pack: release-build
dotnet pack src/UriBuilder.Fluent/UriBuilder.Fluent.csproj --configuration Release --output output
publish:
dotnet nuget push output/*.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key $(NUGET_API_KEY)
dotnet nuget push output/*.snupkg --source https://api.nuget.org/v3/index.json --skip-duplicate --api-key $(NUGET_API_KEY)
coveralls-push:
dotnet tool install -g coveralls.net
coverallsnet --opencover -i UriBuilder.Fluent.UnitTests/coverage.opencover.xml --useRelativePaths
check-format:
dotnet format --verify-no-changes
default: clean build

View File

@@ -1,40 +1,34 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.14
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B4EB6F69-0F56-4875-95AD-E4DEB5D18A74}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{BE84C3E5-BA06-4A89-A786-62423FF4A87F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AC680F4D-C1B2-4F06-8464-CC987B1F0008}"
ProjectSection(SolutionItems) = preProject
appveyor.yml = appveyor.yml
Readme.md = Readme.md
EndProjectSection
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UriBuilder.Fluent", "src\UriBuilder.Fluent\UriBuilder.Fluent.csproj", "{81D561B6-AB75-4A65-B770-20EEF16E6AF7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UriBuilder.Fluent", "src\UriBuilder.Fluent\UriBuilder.Fluent.csproj", "{B8458F59-DEBD-4844-AA29-EE3B4388AA7A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UriBuilder.Fluent.UnitTests", "src\UriBuilder.Fluent.UnitTests\UriBuilder.Fluent.UnitTests.csproj", "{F421A9EE-180C-413E-A0CD-665295825646}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UriBuilder.Fluent.UnitTests", "src\UriBuilder.Fluent.UnitTests\UriBuilder.Fluent.UnitTests.csproj", "{87BEA737-87E0-4114-986F-6080FA58B187}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B8458F59-DEBD-4844-AA29-EE3B4388AA7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8458F59-DEBD-4844-AA29-EE3B4388AA7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8458F59-DEBD-4844-AA29-EE3B4388AA7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8458F59-DEBD-4844-AA29-EE3B4388AA7A}.Release|Any CPU.Build.0 = Release|Any CPU
{F421A9EE-180C-413E-A0CD-665295825646}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F421A9EE-180C-413E-A0CD-665295825646}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F421A9EE-180C-413E-A0CD-665295825646}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F421A9EE-180C-413E-A0CD-665295825646}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{81D561B6-AB75-4A65-B770-20EEF16E6AF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{81D561B6-AB75-4A65-B770-20EEF16E6AF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81D561B6-AB75-4A65-B770-20EEF16E6AF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81D561B6-AB75-4A65-B770-20EEF16E6AF7}.Release|Any CPU.Build.0 = Release|Any CPU
{87BEA737-87E0-4114-986F-6080FA58B187}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{87BEA737-87E0-4114-986F-6080FA58B187}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87BEA737-87E0-4114-986F-6080FA58B187}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87BEA737-87E0-4114-986F-6080FA58B187}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{B8458F59-DEBD-4844-AA29-EE3B4388AA7A} = {B4EB6F69-0F56-4875-95AD-E4DEB5D18A74}
{F421A9EE-180C-413E-A0CD-665295825646} = {B4EB6F69-0F56-4875-95AD-E4DEB5D18A74}
{81D561B6-AB75-4A65-B770-20EEF16E6AF7} = {BE84C3E5-BA06-4A89-A786-62423FF4A87F}
{87BEA737-87E0-4114-986F-6080FA58B187} = {BE84C3E5-BA06-4A89-A786-62423FF4A87F}
EndGlobalSection
EndGlobal

BIN
UriBulider.Fluent.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,28 +0,0 @@
image: Visual Studio 2017
configuration: Release
version: 1.0.{build}
artifacts:
- path: output\**.nupkg
init:
- git config --global core.autocrlf true
build_script:
- ps: >-
dotnet restore UriBuilder.Fluent.sln --source https://api.nuget.org/v3/index.json
dotnet build UriBuilder.Fluent.sln --configuration Release
if($env:APPVEYOR_REPO_TAG -eq "true")
{
dotnet pack src\UriBuilder.Fluent\UriBuilder.Fluent.csproj --configuration Release --output ..\..\output /p:Version=$env:APPVEYOR_REPO_TAG_NAME
}
test_script:
- ps: dotnet test -c Release .\src\UriBuilder.Fluent.UnitTests\UriBuilder.Fluent.UnitTests.csproj
deploy:
- provider: NuGet
api_key:
secure: bGn7M6dHOJ3QjwYIv7e34tcY/n9cCUZmL1MnM6jRfmnJOOfwlrS+cdRj2n8Wf31n
on:
appveyor_repo_tag: true

7
global.json Normal file
View File

@@ -0,0 +1,7 @@
{
"sdk": {
"version": "7.0.0",
"rollForward": "latestMajor",
"allowPrerelease": false
}
}

View File

@@ -16,7 +16,7 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com")
.WithPathSegment(pathWithSlashes);
Assert.Equal("http://awesome.com/" + expectedPath, url.Uri.ToString());
Assert.Equal("http://awesome.com/" + expectedPath, url.ToUriString());
}
[Fact]
@@ -25,7 +25,7 @@ namespace FluentUriBuilder.Tests
var url = new UriBuilder("http://awesome.com")
.WithPathSegment("yodawg")
.WithPathSegment("/immahslash/");
Assert.Equal("http://awesome.com/yodawg/immahslash/", url.Uri.ToString());
Assert.Equal("http://awesome.com/yodawg/immahslash/", url.ToUriString());
}
[Fact]
@@ -33,7 +33,17 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com")
.WithParameter("awesome", "yodawg");
Assert.Equal("http://awesome.com/?awesome=yodawg", url.Uri.ToString());
Assert.Equal("http://awesome.com/?awesome=yodawg", url.ToUriString());
}
[Fact]
public void TestAddUrlParameterAsTupleList()
{
var url = new UriBuilder("http://awesome.com")
.WithParameter(new List<(string, string)>()
{
("awesome", "yodawg")
});
Assert.Equal("http://awesome.com/?awesome=yodawg", url.ToUriString());
}
[Fact]
@@ -52,7 +62,7 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com")
.WithParameter("awesome", "cool", "dawg");
Assert.Equal("http://awesome.com/?awesome=cool,dawg", url.Uri.ToString());
Assert.Equal("http://awesome.com/?awesome=cool,dawg", url.ToUriString());
}
[Fact]
@@ -60,7 +70,7 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com")
.WithParameter("awesome", new List<int>() { 1, 2 }.Cast<object>());
Assert.Equal("http://awesome.com/?awesome=1,2", url.Uri.ToString());
Assert.Equal("http://awesome.com/?awesome=1,2", url.ToUriString());
}
[Fact]
@@ -68,7 +78,7 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com")
.WithParameter("awesome");
Assert.Equal("http://awesome.com/?awesome", url.Uri.ToString());
Assert.Equal("http://awesome.com/?awesome", url.ToUriString());
}
[Fact]
@@ -76,7 +86,7 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com")
.WithFragment("awesome", "cool", "dawg");
Assert.Equal("http://awesome.com/#awesome=cool,dawg", url.Uri.ToString());
Assert.Equal("http://awesome.com/#awesome=cool,dawg", url.ToUriString());
}
[Fact]
@@ -84,7 +94,7 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com")
.WithFragment("awesome", new List<int>() { 1, 2 }.Cast<object>());
Assert.Equal("http://awesome.com/#awesome=1,2", url.Uri.ToString());
Assert.Equal("http://awesome.com/#awesome=1,2", url.ToUriString());
}
[Fact]
@@ -92,14 +102,14 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com")
.WithFragment("awesome");
Assert.Equal("http://awesome.com/#awesome", url.Uri.ToString());
Assert.Equal("http://awesome.com/#awesome", url.ToUriString());
}
[Fact]
public void WithPort()
{
var url = new UriBuilder().WithPort(22);
Assert.Equal(url.Port, 22);
Assert.Equal(22, url.Port);
}
[Fact]
@@ -107,29 +117,29 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com:80")
.WithoutDefaultPort();
Assert.Equal("http://awesome.com/", url.Uri.ToString());
Assert.Equal("http://awesome.com/", url.ToUriString());
url = new UriBuilder("http://awesome.com:443")
.WithoutDefaultPort();
Assert.Equal("http://awesome.com:443/", url.Uri.ToString());
Assert.Equal("http://awesome.com:443/", url.ToUriString());
url = new UriBuilder("https://awesome.com:443")
.WithoutDefaultPort();
Assert.Equal("https://awesome.com/", url.Uri.ToString());
Assert.Equal("https://awesome.com/", url.ToUriString());
}
[Fact]
public void WithHttps()
{
var url = new UriBuilder().UseHttps(true);
Assert.Equal(url.Scheme, "https");
Assert.Equal("https", url.Scheme);
}
[Fact]
public void WithHttp()
{
var url = new UriBuilder().UseHttps(false);
Assert.Equal(url.Scheme, "http");
Assert.Equal("http", url.Scheme);
}
[Fact]
@@ -137,7 +147,7 @@ namespace FluentUriBuilder.Tests
{
//the jesus scheme?
var url = new UriBuilder().WithScheme("jesus");
Assert.Equal(url.Scheme, "jesus");
Assert.Equal("jesus", url.Scheme);
}
[Fact]
@@ -145,7 +155,7 @@ namespace FluentUriBuilder.Tests
{
//the jesus scheme?
var url = new UriBuilder().WithHost("yodawg.com");
Assert.Equal(url.Host, "yodawg.com");
Assert.Equal("yodawg.com", url.Host);
}
[Fact]
@@ -155,7 +165,7 @@ namespace FluentUriBuilder.Tests
.WithParameter("awesome", "yodawg")
.WithParameter("fun", null)
.WithParameter("cool", string.Empty);
Assert.Equal("http://awesome.com/?awesome=yodawg&fun&cool", url.Uri.ToString());
Assert.Equal("http://awesome.com/?awesome=yodawg&fun&cool", url.ToUriString());
}
[Fact]
@@ -165,7 +175,7 @@ namespace FluentUriBuilder.Tests
.WithParameter("awesome", "yodawg")
.WithParameter("supg", "no2")
.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.ToUriString());
}
[Fact]
@@ -179,7 +189,7 @@ namespace FluentUriBuilder.Tests
};
var url = new UriBuilder("http://awesome.com")
.WithParameter(dictionary);
Assert.Equal("http://awesome.com/?yo=dawg&troll=toll&hammer", url.Uri.ToString());
Assert.Equal("http://awesome.com/?yo=dawg&troll=toll&hammer", url.ToUriString());
}
[Fact]
@@ -189,7 +199,7 @@ namespace FluentUriBuilder.Tests
.WithFragment("awesome", "yodawg")
.WithFragment("fun", null)
.WithFragment("cool", string.Empty);
Assert.Equal("http://awesome.com/#awesome=yodawg&fun&cool", url.Uri.ToString());
Assert.Equal("http://awesome.com/#awesome=yodawg&fun&cool", url.ToUriString());
}
[Fact]
@@ -199,7 +209,7 @@ namespace FluentUriBuilder.Tests
.WithFragment("awesome", "yodawg")
.WithFragment("supg", "no2")
.WithFragment("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.ToUriString());
}
[Fact]
@@ -213,7 +223,7 @@ namespace FluentUriBuilder.Tests
};
var url = new UriBuilder("http://awesome.com")
.WithFragment(dictionary);
Assert.Equal("http://awesome.com/#yo=dawg&troll=toll&hammer", url.Uri.ToString());
Assert.Equal("http://awesome.com/#yo=dawg&troll=toll&hammer", url.ToUriString());
}
[Fact]
@@ -221,15 +231,8 @@ namespace FluentUriBuilder.Tests
{
var url = new UriBuilder("http://awesome.com")
.WithParameter("yo", "dawg<");
Assert.Equal("http://awesome.com/?yo=dawg%3C", url.ToEscapeString());
Assert.Equal("http://awesome.com/?yo=dawg<", url.ToUriString());
}
[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

@@ -1,16 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f421a9ee-180c-413e-a0cd-665295825646")]

View File

@@ -17,9 +17,23 @@ namespace FluentUriBuilder.Tests
Assert.Throws<ArgumentNullException>(() => tstObj.WithPathSegment(null));
Assert.Throws<ArgumentNullException>(() => tstObj.WithScheme(null));
Assert.Throws<ArgumentNullException>(() => tstObj.WithHost(null));
Assert.Throws<ArgumentNullException>(() => tstObj.WithParameter(parameterDictionary: null));
Assert.Throws<ArgumentNullException>(() => tstObj.WithParameter((IEnumerable<KeyValuePair<string, string>>)null));
Assert.Throws<ArgumentNullException>(() => tstObj.WithParameter((IEnumerable<(string, string)>)null));
Assert.Throws<ArgumentNullException>(() => tstObj.WithFragment(fragmentDictionary: null));
Assert.Throws<ArgumentOutOfRangeException>(() => tstObj.WithPort(-1));
UriBuilder nullPtr = null;
Assert.Throws<ArgumentNullException>(() => nullPtr.WithFragment("yo", "dawg"));
Assert.Throws<ArgumentNullException>(() => nullPtr.WithFragment(new Dictionary<string, string>()));
Assert.Throws<ArgumentNullException>(() => nullPtr.WithParameter("yo", "dawg"));
Assert.Throws<ArgumentNullException>(() => nullPtr.WithPathSegment("yo"));
Assert.Throws<ArgumentNullException>(() => nullPtr.WithScheme("yo"));
Assert.Throws<ArgumentNullException>(() => nullPtr.WithFragment("yo"));
Assert.Throws<ArgumentNullException>(() => nullPtr.WithoutDefaultPort());
Assert.Throws<ArgumentNullException>(() => nullPtr.WithoutDefaultPort());
Assert.Throws<ArgumentNullException>(() => nullPtr.WithPort(1));
Assert.Throws<ArgumentNullException>(() => nullPtr.WithHost("yo"));
Assert.Throws<ArgumentNullException>(() => nullPtr.UseHttps());
Assert.Throws<ArgumentNullException>(() => nullPtr.WithParameter((IEnumerable<(string, string)>)null));
}
}
}

View File

@@ -1,13 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp1.1;net461</TargetFrameworks>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<IsPackable>false</IsPackable>
<CoverletOutputFormat>lcov</CoverletOutputFormat>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="coverlet.msbuild" Version="6.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UriBuilder.Fluent\UriBuilder.Fluent.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1 @@
global using Xunit;

View File

@@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace System
{
public static class TerribleDevUriExtensions
public static partial 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.
@@ -14,19 +14,27 @@ namespace System
/// <param name="bld"></param>
/// <param name="key"></param>
/// <param name="values"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static UriBuilder WithParameter(this UriBuilder bld, string key, params string[] values) => bld.WithParameter(key, valuesEnum: values);
/// <summary>
/// Appends query strings from dictionary
/// Appends query strings from a list of key-value pairs (usually a 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)
public static UriBuilder WithParameter(this UriBuilder bld, IEnumerable<KeyValuePair<string, string>> parameterDictionary)
{
if(parameterDictionary == null) throw new ArgumentNullException(nameof(parameterDictionary));
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (parameterDictionary == null)
{
throw new ArgumentNullException(nameof(parameterDictionary));
}
foreach (var item in parameterDictionary)
{
bld.WithParameter(item.Key, item.Value);
@@ -40,9 +48,14 @@ namespace System
/// <param name="bld"></param>
/// <param name="key"></param>
/// <param name="valuesEnum"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static UriBuilder WithParameter(this UriBuilder bld, string key, IEnumerable<object> valuesEnum)
{
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentNullException(nameof(key));
@@ -62,6 +75,7 @@ namespace System
/// <param name="bld"></param>
/// <param name="key"></param>
/// <param name="values"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static UriBuilder WithFragment(this UriBuilder bld, string key, params string[] values) => bld.WithFragment(key, valuesEnum: values);
@@ -74,7 +88,14 @@ namespace System
/// <returns></returns>
public static UriBuilder WithFragment(this UriBuilder bld, IDictionary<string, string> fragmentDictionary)
{
if(fragmentDictionary == null) throw new ArgumentNullException(nameof(fragmentDictionary));
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (fragmentDictionary == null)
{
throw new ArgumentNullException(nameof(fragmentDictionary));
}
foreach (var item in fragmentDictionary)
{
bld.WithFragment(item.Key, item.Value);
@@ -88,9 +109,14 @@ namespace System
/// <param name="bld"></param>
/// <param name="key"></param>
/// <param name="valuesEnum"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static UriBuilder WithFragment(this UriBuilder bld, string key, IEnumerable<object> valuesEnum)
{
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentNullException(nameof(key));
@@ -110,10 +136,18 @@ namespace System
/// <param name="bld"></param>
/// <param name="port"></param>
/// <exception cref="ArgumentOutOfRangeException">Throws if port is less than one</exception>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static UriBuilder WithPort(this UriBuilder bld, int port)
{
if(port < 1) throw new ArgumentOutOfRangeException(nameof(port));
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (port < 1)
{
throw new ArgumentOutOfRangeException(nameof(port));
}
bld.Port = port;
return bld;
}
@@ -125,7 +159,14 @@ namespace System
/// <returns></returns>
public static UriBuilder WithoutDefaultPort(this UriBuilder bld)
{
if (bld.Uri.IsDefaultPort) bld.Port = -1;
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (bld.Uri.IsDefaultPort)
{
bld.Port = -1;
}
return bld;
}
@@ -138,6 +179,10 @@ namespace System
/// <returns></returns>
public static UriBuilder WithPathSegment(this UriBuilder bld, string pathSegment)
{
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (string.IsNullOrWhiteSpace(pathSegment))
{
throw new ArgumentNullException(nameof(pathSegment));
@@ -156,7 +201,14 @@ namespace System
/// <returns></returns>
public static UriBuilder WithScheme(this UriBuilder bld, string scheme)
{
if(string.IsNullOrWhiteSpace(scheme)) throw new ArgumentNullException(nameof(scheme));
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (string.IsNullOrWhiteSpace(scheme))
{
throw new ArgumentNullException(nameof(scheme));
}
bld.Scheme = scheme;
return bld;
}
@@ -170,7 +222,14 @@ namespace System
/// <returns></returns>
public static UriBuilder WithHost(this UriBuilder bld, string host)
{
if(string.IsNullOrWhiteSpace(host)) throw new ArgumentNullException(nameof(host));
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (string.IsNullOrWhiteSpace(host))
{
throw new ArgumentNullException(nameof(host));
}
bld.Host = host;
return bld;
}
@@ -182,9 +241,14 @@ namespace System
/// </summary>
/// <param name="bld"></param>
/// <param name="predicate">default true, if false sets scheme to http</param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static UriBuilder UseHttps(this UriBuilder bld, bool predicate = true)
{
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
bld.Scheme = predicate ? "https" : "http";
return bld;
}
@@ -193,6 +257,7 @@ namespace System
/// Escape Url query string
/// </summary>
/// <param name="bld"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static string ToEscapeString(this UriBuilder bld) => Uri.EscapeUriString(bld.Uri.ToString());
@@ -200,26 +265,42 @@ namespace System
/// Escape the whole Url string
/// </summary>
/// <param name="bld"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static string ToEscapeDataString(this UriBuilder bld) => Uri.EscapeDataString(bld.Uri.ToString());
/// <summary>
/// Returns the Uri string
/// </summary>
/// <param name="bld"></param>
/// <exception cref="ArgumentNullException"></exception>
/// <returns></returns>
public static string ToUriString(this UriBuilder bld) => bld.Uri.ToString();
/// <summary>
/// Appends x-www-form-urlencoded key and valuesEnum into initialValue.
/// </summary>
/// <exception cref="ArgumentNullException"></exception>
private static string AppendKeyValue(this string intitialValue, string key, IEnumerable<object> valuesEnum)
{
var sb = new StringBuilder($"{intitialValue}{key}");
var validValueHit = false;
foreach(var value in valuesEnum)
var encodedKey = Uri.EscapeDataString(key);
var sb = new StringBuilder($"{intitialValue}{encodedKey}");
var Values = (
from x in valuesEnum
let v = x?.ToString()
where !string.IsNullOrWhiteSpace(v)
select Uri.EscapeDataString(v)
).ToArray();
if (Values.Length > 0)
{
var toSValue = value?.ToString();
if(string.IsNullOrWhiteSpace(toSValue)) continue;
// we can't just have an = sign since its valid to have query string paramters with no value;
if(!validValueHit) toSValue = "=" + value;
validValueHit = true;
sb.Append($"{toSValue},");
sb.Append("=");
sb.Append(string.Join(",", Values));
}
return sb.ToString().TrimEnd(',');
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace System
{
public static partial class TerribleDevUriExtensions
{
/// <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, IEnumerable<(string, string)> parameterDictionary)
{
if (bld == null)
{
throw new ArgumentNullException(nameof(bld));
}
if (parameterDictionary == null) throw new ArgumentNullException(nameof(parameterDictionary));
foreach (var item in parameterDictionary)
{
bld.WithParameter(item.Item1, item.Item2);
}
return bld;
}
}
}

View File

@@ -2,21 +2,30 @@
<PropertyGroup>
<Authors>Tommy Parnell</Authors>
<TargetFrameworks>netstandard1.1;net40;net45</TargetFrameworks>
<AssemblyName>UriBuilder.Fluent</AssemblyName>
<PackageId>UriBuilder.Fluent</PackageId>
<PackageTags>Url building;Uri;Uri building;fluent;extension</PackageTags>
<PackageProjectUrl>https://github.com/TerribleDev/UriBuilder.Fluent</PackageProjectUrl>
<PackageIcon>UriBulider.Fluent.png</PackageIcon>
<PackageIconUrl />
<TargetFramework>netstandard2.0</TargetFramework>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<PackageReleaseNotes>
This package adds 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, and has no outside dependencies!
</PackageReleaseNotes>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
<ItemGroup>
<None Include="..\..\Readme.md" Pack="true" PackagePath="\" />
<None Include="..\..\UriBulider.Fluent.png" Pack="true" PackagePath="\" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
</Project>