diff --git a/JsonApiDotnetCore.sln b/JsonApiDotnetCore.sln
index ad130ce4b1..769230390d 100644
--- a/JsonApiDotnetCore.sln
+++ b/JsonApiDotnetCore.sln
@@ -41,7 +41,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JsonApiDotNetCore", "src\Js
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GettingStarted", "src\Examples\GettingStarted\GettingStarted.csproj", "{067FFD7A-C66B-473D-8471-37F5C95DF61C}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTests", "test\IntegrationTests\IntegrationTests.csproj", "{CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTests", "test\IntegrationTests\IntegrationTests.csproj", "{CEB08B86-6BF1-4227-B20F-45AE9C1CC6D9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -56,11 +56,15 @@ Global
{CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x64.Build.0 = Debug|Any CPU
{CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Debug|x86.Build.0 = Debug|Any CPU
{CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|Any CPU.Build.0 = Release|Any CPU
{CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x64.ActiveCfg = Release|Any CPU
+ {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x64.Build.0 = Release|Any CPU
{CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x86.ActiveCfg = Release|Any CPU
+ {CAF331F8-9255-4D72-A1A8-A54141E99F1E}.Release|x86.Build.0 = Release|Any CPU
{4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F15A8F8-5BC6-45A1-BC51-03F921B726A4}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -98,6 +102,7 @@ Global
{03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x86.ActiveCfg = Release|Any CPU
{03032A2F-664D-4DD8-A82F-AD8A482EDD85}.Release|x86.Build.0 = Release|Any CPU
{DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x64.ActiveCfg = Debug|Any CPU
{DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x64.Build.0 = Debug|Any CPU
{DF0FCFB2-CB12-44BA-BBB5-1BE0BCFCD14C}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -111,11 +116,15 @@ Global
{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x64.Build.0 = Debug|Any CPU
{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Debug|x86.Build.0 = Debug|Any CPU
{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|Any CPU.Build.0 = Release|Any CPU
{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x64.ActiveCfg = Release|Any CPU
+ {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x64.Build.0 = Release|Any CPU
{C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x86.ActiveCfg = Release|Any CPU
+ {C916EBDA-3429-4FEA-AFB3-DF7CA32A8C6A}.Release|x86.Build.0 = Release|Any CPU
{789085E1-048F-4996-B600-791B9CA3A663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{789085E1-048F-4996-B600-791B9CA3A663}.Debug|Any CPU.Build.0 = Debug|Any CPU
{789085E1-048F-4996-B600-791B9CA3A663}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -143,11 +152,15 @@ Global
{21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x64.Build.0 = Debug|Any CPU
{21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Debug|x86.Build.0 = Debug|Any CPU
{21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|Any CPU.Build.0 = Release|Any CPU
{21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x64.ActiveCfg = Release|Any CPU
+ {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x64.Build.0 = Release|Any CPU
{21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x86.ActiveCfg = Release|Any CPU
+ {21D27239-138D-4604-8E49-DCBE41BCE4C8}.Release|x86.Build.0 = Release|Any CPU
{067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{067FFD7A-C66B-473D-8471-37F5C95DF61C}.Debug|x64.ActiveCfg = Debug|Any CPU
diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore
deleted file mode 100644
index 5a3c72cbbb..0000000000
--- a/benchmarks/.gitignore
+++ /dev/null
@@ -1,239 +0,0 @@
-_data/
-*-report-default.md
-*-report.csv
-*-report.html
-
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-build/
-bld/
-[Bb]in/
-[Oo]bj/
-
-# Visual Studio 2015 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUNIT
-*.VisualState.xml
-TestResult.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# DNX
-project.lock.json
-artifacts/
-
-*_i.c
-*_p.c
-*_i.h
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding add-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# TODO: Comment the next line if you want to checkin your web deploy settings
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# NuGet Packages
-*.nupkg
-# The packages folder can be ignored because of Package Restore
-**/packages/*
-# except build/, which is used as an MSBuild target.
-!**/packages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/packages/repositories.config
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Microsoft Azure ApplicationInsights config file
-ApplicationInsights.config
-
-# Windows Store app package directory
-AppPackages/
-BundleArtifacts/
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.pfx
-*.publishsettings
-node_modules/
-orleans.codegen.cs
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-*.mdf
-*.ldf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-
-# FAKE - F# Make
-.fake/
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.JsonApiContext.PathIsRelationship_Benchmarks-report-github.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.JsonApiContext.PathIsRelationship_Benchmarks-report-github.md
deleted file mode 100644
index 6be58e241a..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.JsonApiContext.PathIsRelationship_Benchmarks-report-github.md
+++ /dev/null
@@ -1,12 +0,0 @@
-```ini
-BenchmarkDotNet=v0.10.10, OS=Mac OS X 10.12
-Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
-.NET Core SDK=2.1.4
- [Host] : .NET Core 2.0.5 (Framework 4.6.0.0), 64bit RyuJIT
- DefaultJob : .NET Core 2.0.5 (Framework 4.6.0.0), 64bit RyuJIT
-```
-
-| Method | Mean | Error | StdDev | Gen 0 | Allocated |
-| ---------- | --------: | ---------: | ---------: | -----: | --------: |
-| UsingSplit | 421.08 ns | 19.3905 ns | 54.0529 ns | 0.4725 | 744 B |
-| Current | 52.23 ns | 0.8052 ns | 0.7532 ns | - | 0 B |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.LinkBuilder.LinkBuilder_GetNamespaceFromPath_Benchmarks-report-github.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.LinkBuilder.LinkBuilder_GetNamespaceFromPath_Benchmarks-report-github.md
deleted file mode 100644
index 72951396e8..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.LinkBuilder.LinkBuilder_GetNamespaceFromPath_Benchmarks-report-github.md
+++ /dev/null
@@ -1,16 +0,0 @@
-``` ini
-
-BenchmarkDotNet=v0.10.10, OS=Mac OS X 10.12
-Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
-.NET Core SDK=2.1.4
- [Host] : .NET Core 2.0.5 (Framework 4.6.0.0), 64bit RyuJIT
- Job-XFMVNE : .NET Core 2.0.5 (Framework 4.6.0.0), 64bit RyuJIT
-
-LaunchCount=3 TargetCount=20 WarmupCount=10
-
-```
-| Method | Mean | Error | StdDev | Gen 0 | Allocated |
-|--------------------------- |-----------:|----------:|----------:|-------:|----------:|
-| UsingSplit | 1,197.6 ns | 11.929 ns | 25.933 ns | 0.9251 | 1456 B |
-| UsingSpanWithStringBuilder | 1,542.0 ns | 15.249 ns | 33.792 ns | 0.9460 | 1488 B |
-| UsingSpanWithNoAlloc | 272.6 ns | 2.265 ns | 5.018 ns | 0.0863 | 136 B |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
deleted file mode 100755
index b3ebd8a29c..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Query.QueryParser_Benchmarks-report-github.md
+++ /dev/null
@@ -1,16 +0,0 @@
-``` ini
-
-BenchmarkDotNet=v0.10.10, OS=Mac OS X 10.12
-Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
-.NET Core SDK=2.0.0
- [Host] : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
- Job-WKDOLS : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
-
-LaunchCount=3 TargetCount=20 WarmupCount=10
-
-```
-| Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Allocated |
-|--------------- |-------------:|-----------:|-----------:|---------:|--------:|----------:|
-| AscendingSort | 4.316 us | 1.3773 us | 3.0232 us | 0.5066 | 0.1303 | 1.08 KB |
-| DescendingSort | 3.300 us | 0.0314 us | 0.0682 us | 0.5123 | 0.1318 | 1.13 KB |
-| ComplexQuery | 2,041.642 us | 41.5631 us | 92.1010 us | 312.5000 | 80.2734 | 648.99 KB |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.RequestMiddleware.ContainsMediaTypeParameters_Benchmarks-report-github.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.RequestMiddleware.ContainsMediaTypeParameters_Benchmarks-report-github.md
deleted file mode 100644
index 066e7b2036..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.RequestMiddleware.ContainsMediaTypeParameters_Benchmarks-report-github.md
+++ /dev/null
@@ -1,14 +0,0 @@
-``` ini
-
-BenchmarkDotNet=v0.10.10, OS=Mac OS X 10.12
-Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
-.NET Core SDK=2.1.4
- [Host] : .NET Core 2.0.5 (Framework 4.6.0.0), 64bit RyuJIT
- DefaultJob : .NET Core 2.0.5 (Framework 4.6.0.0), 64bit RyuJIT
-
-
-```
-| Method | Mean | Error | StdDev | Gen 0 | Allocated |
-|----------- |----------:|----------:|----------:|-------:|----------:|
-| UsingSplit | 157.28 ns | 2.9689 ns | 5.8602 ns | 0.2134 | 336 B |
-| Current | 39.96 ns | 0.6489 ns | 0.6070 ns | - | 0 B |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
deleted file mode 100755
index 6c8c3f2905..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiDeserializer_Benchmarks-report-github.md
+++ /dev/null
@@ -1,13 +0,0 @@
-``` ini
-
-BenchmarkDotNet=v0.10.10, OS=Mac OS X 10.12
-Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
-.NET Core SDK=2.0.0
- [Host] : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
- DefaultJob : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
-
-
-```
-| Method | Mean | Error | StdDev |
-|------------------------ |---------:|----------:|----------:|
-| DeserializeSimpleObject | 27.05 us | 0.5353 us | 0.5950 us |
diff --git a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md b/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
deleted file mode 100755
index f86bf0faa9..0000000000
--- a/benchmarks/BenchmarkDotNet.Artifacts/results/Benchmarks.Serialization.JsonApiSerializer_Benchmarks-report-github.md
+++ /dev/null
@@ -1,13 +0,0 @@
-``` ini
-
-BenchmarkDotNet=v0.10.10, OS=Mac OS X 10.12
-Processor=Intel Core i5-5257U CPU 2.70GHz (Broadwell), ProcessorCount=4
-.NET Core SDK=2.0.0
- [Host] : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
- DefaultJob : .NET Core 1.1.4 (Framework 4.6.25714.03), 64bit RyuJIT
-
-
-```
-| Method | Mean | Error | StdDev |
-|---------------------- |---------:|----------:|----------:|
-| SerializeSimpleObject | 7.195 us | 0.1436 us | 0.1816 us |
diff --git a/benchmarks/BenchmarkResource.cs b/benchmarks/BenchmarkResource.cs
new file mode 100644
index 0000000000..0d3ae2c8bf
--- /dev/null
+++ b/benchmarks/BenchmarkResource.cs
@@ -0,0 +1,25 @@
+using JsonApiDotNetCore.Models;
+
+namespace Benchmarks
+{
+ public class BenchmarkResource : Identifiable
+ {
+ [Attr(BenchmarkResourcePublicNames.NameAttr)]
+ public string Name { get; set; }
+
+ [HasOne]
+ public SubResource Child { get; set; }
+ }
+
+ public class SubResource : Identifiable
+ {
+ [Attr]
+ public string Value { get; set; }
+ }
+
+ public static class BenchmarkResourcePublicNames
+ {
+ public const string NameAttr = "full-name";
+ public const string Type = "simple-types";
+ }
+}
diff --git a/benchmarks/Benchmarks.csproj b/benchmarks/Benchmarks.csproj
index 60a9a8bf42..02bfbf378d 100644
--- a/benchmarks/Benchmarks.csproj
+++ b/benchmarks/Benchmarks.csproj
@@ -2,10 +2,9 @@
Exe
$(NetCoreAppVersion)
- Benchmarks
-
+
diff --git a/benchmarks/DependencyFactory.cs b/benchmarks/DependencyFactory.cs
new file mode 100644
index 0000000000..0c268bc7c5
--- /dev/null
+++ b/benchmarks/DependencyFactory.cs
@@ -0,0 +1,29 @@
+using System;
+using JsonApiDotNetCore.Builders;
+using JsonApiDotNetCore.Internal.Contracts;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Query;
+using Moq;
+
+namespace Benchmarks
+{
+ internal static class DependencyFactory
+ {
+ public static IResourceGraph CreateResourceGraph()
+ {
+ IResourceGraphBuilder builder = new ResourceGraphBuilder();
+ builder.AddResource(BenchmarkResourcePublicNames.Type);
+ return builder.Build();
+ }
+
+ public static IResourceDefinitionProvider CreateResourceDefinitionProvider(IResourceGraph resourceGraph)
+ {
+ var resourceDefinition = new ResourceDefinition(resourceGraph);
+
+ var resourceDefinitionProviderMock = new Mock();
+ resourceDefinitionProviderMock.Setup(provider => provider.Get(It.IsAny())).Returns(resourceDefinition);
+
+ return resourceDefinitionProviderMock.Object;
+ }
+ }
+}
diff --git a/benchmarks/JsonApiContext/PathIsRelationship_Benchmarks.cs b/benchmarks/JsonApiContext/PathIsRelationship_Benchmarks.cs
deleted file mode 100644
index 83fe6fc53c..0000000000
--- a/benchmarks/JsonApiContext/PathIsRelationship_Benchmarks.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Attributes.Exporters;
-
-namespace Benchmarks.JsonApiContext
-{
- [MarkdownExporter, MemoryDiagnoser]
- public class PathIsRelationship_Benchmarks
- {
- private const string PATH = "https://example.com/api/v1/namespace/articles/relationships/author/";
-
- [Benchmark]
- public void Current()
- => JsonApiDotNetCore.Services.JsonApiContext.PathIsRelationship(PATH);
-
- [Benchmark]
- public void UsingSplit() => UsingSplitImpl(PATH);
-
- private bool UsingSplitImpl(string path)
- {
- var split = path.Split('/');
- return split[split.Length - 2] == "relationships";
- }
- }
-}
diff --git a/benchmarks/LinkBuilder/LinkBuilderGetNamespaceFromPathBenchmarks.cs b/benchmarks/LinkBuilder/LinkBuilderGetNamespaceFromPathBenchmarks.cs
new file mode 100644
index 0000000000..5524f83e5f
--- /dev/null
+++ b/benchmarks/LinkBuilder/LinkBuilderGetNamespaceFromPathBenchmarks.cs
@@ -0,0 +1,70 @@
+using BenchmarkDotNet.Attributes;
+using System;
+using System.Text;
+
+namespace Benchmarks.LinkBuilder
+{
+ [MarkdownExporter, SimpleJob(launchCount: 3, warmupCount: 10, targetCount: 20), MemoryDiagnoser]
+ public class LinkBuilderGetNamespaceFromPathBenchmarks
+ {
+ private const string RequestPath = "/api/some-really-long-namespace-path/resources/current/articles/?some";
+ private const string EntityName = "articles";
+ private const char PathDelimiter = '/';
+
+ [Benchmark]
+ public void UsingStringSplit() => GetNamespaceFromPathUsingStringSplit(RequestPath, EntityName);
+
+ [Benchmark]
+ public void UsingReadOnlySpan() => GetNamespaceFromPathUsingReadOnlySpan(RequestPath, EntityName);
+
+ public static string GetNamespaceFromPathUsingStringSplit(string path, string entityName)
+ {
+ StringBuilder namespaceBuilder = new StringBuilder(path.Length);
+ string[] segments = path.Split('/');
+
+ for (int index = 1; index < segments.Length; index++)
+ {
+ if (segments[index] == entityName)
+ {
+ break;
+ }
+
+ namespaceBuilder.Append(PathDelimiter);
+ namespaceBuilder.Append(segments[index]);
+ }
+
+ return namespaceBuilder.ToString();
+ }
+
+ public static string GetNamespaceFromPathUsingReadOnlySpan(string path, string entityName)
+ {
+ ReadOnlySpan entityNameSpan = entityName.AsSpan();
+ ReadOnlySpan pathSpan = path.AsSpan();
+
+ for (int index = 0; index < pathSpan.Length; index++)
+ {
+ if (pathSpan[index].Equals(PathDelimiter))
+ {
+ if (pathSpan.Length > index + entityNameSpan.Length)
+ {
+ ReadOnlySpan possiblePathSegment = pathSpan.Slice(index + 1, entityNameSpan.Length);
+
+ if (entityNameSpan.SequenceEqual(possiblePathSegment))
+ {
+ int lastCharacterIndex = index + 1 + entityNameSpan.Length;
+
+ bool isAtEnd = lastCharacterIndex == pathSpan.Length;
+ bool hasDelimiterAfterSegment = pathSpan.Length >= lastCharacterIndex + 1 && pathSpan[lastCharacterIndex].Equals(PathDelimiter);
+ if (isAtEnd || hasDelimiterAfterSegment)
+ {
+ return pathSpan.Slice(0, index).ToString();
+ }
+ }
+ }
+ }
+ }
+
+ return string.Empty;
+ }
+ }
+}
diff --git a/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs b/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs
deleted file mode 100644
index 1432afecd8..0000000000
--- a/benchmarks/LinkBuilder/LinkBuilder_ GetNamespaceFromPath_Benchmarks.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Attributes.Exporters;
-using BenchmarkDotNet.Attributes.Jobs;
-using System;
-
-namespace Benchmarks.LinkBuilder
-{
- [MarkdownExporter, SimpleJob(launchCount: 3, warmupCount: 10, targetCount: 20), MemoryDiagnoser]
- public class LinkBuilder_GetNamespaceFromPath_Benchmarks
- {
- private const string PATH = "/api/some-really-long-namespace-path/resources/current/articles";
- private const string ENTITY_NAME = "articles";
-
- [Benchmark]
- public void UsingSplit() => GetNamespaceFromPath_BySplitting(PATH, ENTITY_NAME);
-
- [Benchmark]
- public void Current() => GetNameSpaceFromPathCurrent(PATH, ENTITY_NAME);
-
- public static string GetNamespaceFromPath_BySplitting(string path, string entityName)
- {
- var nSpace = string.Empty;
- var segments = path.Split('/');
-
- for (var i = 1; i < segments.Length; i++)
- {
- if (segments[i].ToLower() == entityName)
- break;
-
- nSpace += $"/{segments[i]}";
- }
-
- return nSpace;
- }
-
- public static string GetNameSpaceFromPathCurrent(string path, string entityName)
- {
-
- var entityNameSpan = entityName.AsSpan();
- var pathSpan = path.AsSpan();
- const char delimiter = '/';
- for (var i = 0; i < pathSpan.Length; i++)
- {
- if (pathSpan[i].Equals(delimiter))
- {
- var nextPosition = i + 1;
- if (pathSpan.Length > i + entityNameSpan.Length)
- {
- var possiblePathSegment = pathSpan.Slice(nextPosition, entityNameSpan.Length);
- if (entityNameSpan.SequenceEqual(possiblePathSegment))
- {
- // check to see if it's the last position in the string
- // or if the next character is a /
- var lastCharacterPosition = nextPosition + entityNameSpan.Length;
-
- if (lastCharacterPosition == pathSpan.Length || pathSpan.Length >= lastCharacterPosition + 2 && pathSpan[lastCharacterPosition].Equals(delimiter))
- {
- return pathSpan.Slice(0, i).ToString();
- }
- }
- }
- }
- }
-
- return string.Empty;
-
-
- }
- }
-}
diff --git a/benchmarks/Program.cs b/benchmarks/Program.cs
index bd504c670f..474bb5725c 100644
--- a/benchmarks/Program.cs
+++ b/benchmarks/Program.cs
@@ -1,20 +1,20 @@
using BenchmarkDotNet.Running;
-using Benchmarks.JsonApiContext;
using Benchmarks.LinkBuilder;
using Benchmarks.Query;
-using Benchmarks.RequestMiddleware;
using Benchmarks.Serialization;
-namespace Benchmarks {
- class Program {
- static void Main(string[] args) {
- var switcher = new BenchmarkSwitcher(new[] {
- typeof(JsonApideserializer_Benchmarks),
- //typeof(JsonApiSerializer_Benchmarks),
- typeof(QueryParser_Benchmarks),
- typeof(LinkBuilder_GetNamespaceFromPath_Benchmarks),
- typeof(ContainsMediaTypeParameters_Benchmarks),
- typeof(PathIsRelationship_Benchmarks)
+namespace Benchmarks
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ var switcher = new BenchmarkSwitcher(new[]
+ {
+ typeof(JsonApiDeserializerBenchmarks),
+ typeof(JsonApiSerializerBenchmarks),
+ typeof(QueryParserBenchmarks),
+ typeof(LinkBuilderGetNamespaceFromPathBenchmarks)
});
switcher.Run(args);
}
diff --git a/benchmarks/Query/QueryParserBenchmarks.cs b/benchmarks/Query/QueryParserBenchmarks.cs
new file mode 100644
index 0000000000..6dd7e509c1
--- /dev/null
+++ b/benchmarks/Query/QueryParserBenchmarks.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using BenchmarkDotNet.Attributes;
+using JsonApiDotNetCore.Configuration;
+using JsonApiDotNetCore.Internal.Contracts;
+using JsonApiDotNetCore.Managers;
+using JsonApiDotNetCore.Query;
+using JsonApiDotNetCore.Services;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Primitives;
+
+namespace Benchmarks.Query
+{
+ [MarkdownExporter, SimpleJob(launchCount: 3, warmupCount: 10, targetCount: 20), MemoryDiagnoser]
+ public class QueryParserBenchmarks
+ {
+ private readonly QueryParameterDiscovery _queryParameterDiscoveryForSort;
+ private readonly QueryParameterDiscovery _queryParameterDiscoveryForAll;
+
+ public QueryParserBenchmarks()
+ {
+ IJsonApiOptions options = new JsonApiOptions();
+ IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph();
+
+ var currentRequest = new CurrentRequest();
+ currentRequest.SetRequestResource(resourceGraph.GetResourceContext(typeof(BenchmarkResource)));
+
+ IResourceDefinitionProvider resourceDefinitionProvider = DependencyFactory.CreateResourceDefinitionProvider(resourceGraph);
+
+ _queryParameterDiscoveryForSort = CreateQueryParameterDiscoveryForSort(resourceGraph, currentRequest, resourceDefinitionProvider, options);
+ _queryParameterDiscoveryForAll = CreateQueryParameterDiscoveryForAll(resourceGraph, currentRequest, resourceDefinitionProvider, options);
+ }
+
+ private static QueryParameterDiscovery CreateQueryParameterDiscoveryForSort(IResourceGraph resourceGraph,
+ CurrentRequest currentRequest, IResourceDefinitionProvider resourceDefinitionProvider, IJsonApiOptions options)
+ {
+ ISortService sortService = new SortService(resourceDefinitionProvider, resourceGraph, currentRequest);
+
+ var queryServices = new List
+ {
+ sortService
+ };
+
+ return new QueryParameterDiscovery(options, queryServices);
+ }
+
+ private static QueryParameterDiscovery CreateQueryParameterDiscoveryForAll(IResourceGraph resourceGraph,
+ CurrentRequest currentRequest, IResourceDefinitionProvider resourceDefinitionProvider, IJsonApiOptions options)
+ {
+ IIncludeService includeService = new IncludeService(resourceGraph, currentRequest);
+ IFilterService filterService = new FilterService(resourceDefinitionProvider, resourceGraph, currentRequest);
+ ISortService sortService = new SortService(resourceDefinitionProvider, resourceGraph, currentRequest);
+ ISparseFieldsService sparseFieldsService = new SparseFieldsService(resourceGraph, currentRequest);
+ IPageService pageService = new PageService(options, resourceGraph, currentRequest);
+ IOmitDefaultService omitDefaultService = new OmitDefaultService(options);
+ IOmitNullService omitNullService = new OmitNullService(options);
+
+ var queryServices = new List
+ {
+ includeService, filterService, sortService, sparseFieldsService, pageService, omitDefaultService,
+ omitNullService
+ };
+
+ return new QueryParameterDiscovery(options, queryServices);
+ }
+
+ [Benchmark]
+ public void AscendingSort() => _queryParameterDiscoveryForSort.Parse(new QueryCollection(
+ new Dictionary
+ {
+ {"sort", BenchmarkResourcePublicNames.NameAttr}
+ }
+ ), null);
+
+ [Benchmark]
+ public void DescendingSort() => _queryParameterDiscoveryForSort.Parse(new QueryCollection(
+ new Dictionary
+ {
+ {"sort", $"-{BenchmarkResourcePublicNames.NameAttr}"}
+ }
+ ), null);
+
+ [Benchmark]
+ public void ComplexQuery() => Run(100, () => _queryParameterDiscoveryForAll.Parse(new QueryCollection(
+ new Dictionary
+ {
+ {$"filter[{BenchmarkResourcePublicNames.NameAttr}]", new StringValues(new[] {"abc", "eq:abc"})},
+ {"sort", $"-{BenchmarkResourcePublicNames.NameAttr}"},
+ {"include", "child"},
+ {"page[size]", "1"},
+ {"fields", BenchmarkResourcePublicNames.NameAttr}
+ }
+ ), null));
+
+ private void Run(int iterations, Action action) {
+ for (int i = 0; i < iterations; i++)
+ action();
+ }
+ }
+}
diff --git a/benchmarks/Query/QueryParser_Benchmarks.cs b/benchmarks/Query/QueryParser_Benchmarks.cs
deleted file mode 100644
index 242df86b18..0000000000
--- a/benchmarks/Query/QueryParser_Benchmarks.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-using System;
-using System.Collections.Generic;
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Attributes.Exporters;
-using BenchmarkDotNet.Attributes.Jobs;
-using JsonApiDotNetCore.Configuration;
-using JsonApiDotNetCore.Internal;
-using JsonApiDotNetCore.Managers.Contracts;
-using JsonApiDotNetCore.Models;
-using JsonApiDotNetCore.Services;
-using Microsoft.AspNetCore.Http.Internal;
-using Microsoft.Extensions.Primitives;
-using Moq;
-
-namespace Benchmarks.Query {
- [MarkdownExporter, SimpleJob(launchCount : 3, warmupCount : 10, targetCount : 20), MemoryDiagnoser]
- public class QueryParser_Benchmarks {
- private readonly BenchmarkFacade _queryParser;
-
- private const string ATTRIBUTE = "Attribute";
- private const string ASCENDING_SORT = ATTRIBUTE;
- private const string DESCENDING_SORT = "-" + ATTRIBUTE;
-
- public QueryParser_Benchmarks() {
- var requestMock = new Mock();
- requestMock.Setup(m => m.GetRequestResource()).Returns(new ResourceContext {
- Attributes = new List {
- new AttrAttribute(ATTRIBUTE)
- }
- });
- var options = new JsonApiOptions();
- _queryParser = new BenchmarkFacade(requestMock.Object, options);
- }
-
- [Benchmark]
- public void AscendingSort() => _queryParser._ParseSortParameters(ASCENDING_SORT);
-
- [Benchmark]
- public void DescendingSort() => _queryParser._ParseSortParameters(DESCENDING_SORT);
-
- [Benchmark]
- public void ComplexQuery() => Run(100, () => _queryParser.Parse(
- new QueryCollection(
- new Dictionary {
- { $"filter[{ATTRIBUTE}]", new StringValues(new [] { "abc", "eq:abc" }) },
- { $"sort", $"-{ATTRIBUTE}" },
- { $"include", "relationship" },
- { $"page[size]", "1" },
- { $"fields[resource]", ATTRIBUTE },
- }
- )
- ));
-
- private void Run(int iterations, Action action) {
- for (int i = 0; i < iterations; i++)
- action();
- }
-
- // this facade allows us to expose and micro-benchmark protected methods
- private class BenchmarkFacade : QueryParameterDiscovery {
- public BenchmarkFacade(
- IRequestContext currentRequest,
- JsonApiOptions options) : base(currentRequest, options) { }
-
- public void _ParseSortParameters(string value) => base.ParseSortParameters(value);
- }
- }
-}
diff --git a/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs b/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs
deleted file mode 100644
index 2e0a5c0232..0000000000
--- a/benchmarks/RequestMiddleware/ContainsMediaTypeParameters_Benchmarks.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Attributes.Exporters;
-using JsonApiDotNetCore.Internal;
-
-namespace Benchmarks.RequestMiddleware
-{
- [MarkdownExporter, MemoryDiagnoser]
- public class ContainsMediaTypeParameters_Benchmarks
- {
- private const string MEDIA_TYPE = "application/vnd.api+json; version=1";
-
- [Benchmark]
- public void UsingSplit() => UsingSplitImpl(MEDIA_TYPE);
-
- [Benchmark]
- public void Current()
- => JsonApiDotNetCore.Middleware.CurrentRequestMiddleware.ContainsMediaTypeParameters(MEDIA_TYPE);
-
- private bool UsingSplitImpl(string mediaType)
- {
- var mediaTypeArr = mediaType.Split(';');
- return (mediaTypeArr[0] == Constants.ContentType && mediaTypeArr.Length == 2);
- }
- }
-}
diff --git a/benchmarks/Serialization/JsonApiDeserializerBenchmarks.cs b/benchmarks/Serialization/JsonApiDeserializerBenchmarks.cs
new file mode 100644
index 0000000000..30742c5440
--- /dev/null
+++ b/benchmarks/Serialization/JsonApiDeserializerBenchmarks.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using BenchmarkDotNet.Attributes;
+using JsonApiDotNetCore.Internal.Contracts;
+using JsonApiDotNetCore.Models;
+using JsonApiDotNetCore.Serialization;
+using JsonApiDotNetCore.Serialization.Server;
+using Newtonsoft.Json;
+
+namespace Benchmarks.Serialization
+{
+ [MarkdownExporter]
+ public class JsonApiDeserializerBenchmarks
+ {
+ private static readonly string Content = JsonConvert.SerializeObject(new Document
+ {
+ Data = new ResourceObject
+ {
+ Type = BenchmarkResourcePublicNames.Type,
+ Id = "1",
+ Attributes = new Dictionary
+ {
+ {
+ "name",
+ Guid.NewGuid().ToString()
+ }
+ }
+ }
+ });
+
+ private readonly IJsonApiDeserializer _jsonApiDeserializer;
+
+ public JsonApiDeserializerBenchmarks()
+ {
+ IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph();
+ var targetedFields = new TargetedFields();
+
+ _jsonApiDeserializer = new RequestDeserializer(resourceGraph, targetedFields);
+ }
+
+ [Benchmark]
+ public object DeserializeSimpleObject() => _jsonApiDeserializer.Deserialize(Content);
+ }
+}
diff --git a/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs b/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
deleted file mode 100644
index 2dff692a31..0000000000
--- a/benchmarks/Serialization/JsonApiDeserializer_Benchmarks.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System;
-using System.Collections.Generic;
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Attributes.Exporters;
-using JsonApiDotNetCore.Builders;
-using JsonApiDotNetCore.Configuration;
-using JsonApiDotNetCore.Managers.Contracts;
-using JsonApiDotNetCore.Models;
-using JsonApiDotNetCore.Serialization;
-using JsonApiDotNetCore.Serialization.Contracts;
-
-using JsonApiDotNetCore.Services;
-using Moq;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Serialization;
-namespace Benchmarks.Serialization
-{
- [MarkdownExporter]
- public class JsonApideserializer_Benchmarks {
- private const string TYPE_NAME = "simple-types";
- private static readonly string Content = JsonConvert.SerializeObject(new Document {
- Data = new ResourceObject {
- Type = TYPE_NAME,
- Id = "1",
- Attributes = new Dictionary {
- {
- "name",
- Guid.NewGuid().ToString()
- }
- }
- }
- });
-
- private readonly JsonApideserializer _jsonApideserializer;
-
- public JsonApideserializer_Benchmarks() {
- var resourceGraphBuilder = new ResourceGraphBuilder();
- resourceGraphBuilder.AddResource(TYPE_NAME);
- var resourceGraph = resourceGraphBuilder.Build();
- var currentRequestMock = new Mock();
-
- currentRequestMock.Setup(m => m.GetUpdatedAttributes()).Returns(new Dictionary());
-
- var jsonApiContextMock = new Mock();
- jsonApiContextMock.SetupAllProperties();
- jsonApiContextMock.Setup(m => m.ResourceGraph).Returns(resourceGraph);
- jsonApiContextMock.Setup(m => m.RequestManager.GetUpdatedAttributes()).Returns(new Dictionary());
-
- var jsonApiOptions = new JsonApiOptions();
- jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
- jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
-
-
- _jsonApideserializer = new JsonApideserializer(jsonApiContextMock.Object, currentRequestMock.Object);
- }
-
- [Benchmark]
- public object DeserializeSimpleObject() => _jsonApideserializer.Deserialize(Content);
-
- private class SimpleType : Identifiable {
- [Attr]
- public string Name { get; set; }
- }
- }
-}
diff --git a/benchmarks/Serialization/JsonApiSerializerBenchmarks.cs b/benchmarks/Serialization/JsonApiSerializerBenchmarks.cs
new file mode 100644
index 0000000000..f3ac7ca525
--- /dev/null
+++ b/benchmarks/Serialization/JsonApiSerializerBenchmarks.cs
@@ -0,0 +1,51 @@
+using System;
+using BenchmarkDotNet.Attributes;
+using JsonApiDotNetCore.Internal.Contracts;
+using JsonApiDotNetCore.Managers;
+using JsonApiDotNetCore.Query;
+using JsonApiDotNetCore.Serialization;
+using JsonApiDotNetCore.Serialization.Server;
+using JsonApiDotNetCore.Serialization.Server.Builders;
+using Moq;
+
+namespace Benchmarks.Serialization
+{
+ [MarkdownExporter]
+ public class JsonApiSerializerBenchmarks
+ {
+ private static readonly BenchmarkResource Content = new BenchmarkResource
+ {
+ Id = 123,
+ Name = Guid.NewGuid().ToString()
+ };
+
+ private readonly IJsonApiSerializer _jsonApiSerializer;
+
+ public JsonApiSerializerBenchmarks()
+ {
+ IResourceGraph resourceGraph = DependencyFactory.CreateResourceGraph();
+ IFieldsToSerialize fieldsToSerialize = CreateFieldsToSerialize(resourceGraph);
+
+ var metaBuilderMock = new Mock>();
+ var linkBuilderMock = new Mock();
+ var includeBuilderMock = new Mock();
+
+ var resourceObjectBuilder = new ResourceObjectBuilder(resourceGraph, new ResourceObjectBuilderSettings());
+
+ _jsonApiSerializer = new ResponseSerializer(metaBuilderMock.Object, linkBuilderMock.Object,
+ includeBuilderMock.Object, fieldsToSerialize, resourceObjectBuilder, resourceGraph);
+ }
+
+ private static FieldsToSerialize CreateFieldsToSerialize(IResourceGraph resourceGraph)
+ {
+ var resourceDefinitionProvider = DependencyFactory.CreateResourceDefinitionProvider(resourceGraph);
+ var currentRequest = new CurrentRequest();
+ var sparseFieldsService = new SparseFieldsService(resourceGraph, currentRequest);
+
+ return new FieldsToSerialize(resourceGraph, sparseFieldsService, resourceDefinitionProvider);
+ }
+
+ [Benchmark]
+ public object SerializeSimpleObject() => _jsonApiSerializer.Serialize(Content);
+ }
+}
diff --git a/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs b/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
deleted file mode 100644
index 19e585bdc3..0000000000
--- a/benchmarks/Serialization/JsonApiSerializer_Benchmarks.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-//using System.Collections.Generic;
-//using BenchmarkDotNet.Attributes;
-//using BenchmarkDotNet.Attributes.Exporters;
-//using JsonApiDotNetCore.Builders;
-//using JsonApiDotNetCore.Configuration;
-//using JsonApiDotNetCore.Internal.Generics;
-//using JsonApiDotNetCore.Models;
-//using JsonApiDotNetCore.Serialization;
-using JsonApiDotNetCore.Serialization.Contracts;
-
-//using JsonApiDotNetCore.Services;
-//using Moq;
-//using Newtonsoft.Json.Serialization;
-
-//namespace Benchmarks.Serialization {
-// [MarkdownExporter]
-// public class JsonApiSerializer_Benchmarks {
-// private const string TYPE_NAME = "simple-types";
-// private static readonly SimpleType Content = new SimpleType();
-
-// private readonly JsonApiSerializer _jsonApiSerializer;
-
-// public JsonApiSerializer_Benchmarks() {
-// var resourceGraphBuilder = new ResourceGraphBuilder();
-// resourceGraphBuilder.AddResource(TYPE_NAME);
-// var resourceGraph = resourceGraphBuilder.Build();
-
-// var jsonApiContextMock = new Mock();
-// jsonApiContextMock.SetupAllProperties();
-// jsonApiContextMock.Setup(m => m.ResourceGraph).Returns(resourceGraph);
-// jsonApiContextMock.Setup(m => m.AttributesToUpdate).Returns(new Dictionary());
-
-// var jsonApiOptions = new JsonApiOptions();
-// jsonApiOptions.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
-// jsonApiContextMock.Setup(m => m.Options).Returns(jsonApiOptions);
-
-// var genericServiceFactoryMock = new Mock();
-
-// var documentBuilder = new BaseDocumentBuilder(jsonApiContextMock.Object);
-// _jsonApiSerializer = new JsonApiSerializer(jsonApiContextMock.Object, documentBuilder);
-// }
-
-// [Benchmark]
-// public object SerializeSimpleObject() => _jsonApiSerializer.Serialize(Content);
-
-// private class SimpleType : Identifiable {
-// [Attr("name")]
-// public string Name { get; set; }
-// }
-// }
-//}
diff --git a/src/JsonApiDotNetCore/QueryParameterServices/SortService.cs b/src/JsonApiDotNetCore/QueryParameterServices/SortService.cs
index 1212a9b486..6373f92ac4 100644
--- a/src/JsonApiDotNetCore/QueryParameterServices/SortService.cs
+++ b/src/JsonApiDotNetCore/QueryParameterServices/SortService.cs
@@ -14,7 +14,6 @@ public class SortService : QueryParameterService, ISortService
const char DESCENDING_SORT_OPERATOR = '-';
private readonly IResourceDefinitionProvider _resourceDefinitionProvider;
private List _queries;
- private bool _isProcessed;
public SortService(IResourceDefinitionProvider resourceDefinitionProvider,
IResourceGraph resourceGraph,
@@ -29,7 +28,6 @@ public SortService(IResourceDefinitionProvider resourceDefinitionProvider,
public virtual void Parse(KeyValuePair queryParameter)
{
EnsureNoNestedResourceRoute();
- CheckIfProcessed(); // disallow multiple sort parameters.
var queries = BuildQueries(queryParameter.Value);
_queries = queries.Select(BuildQueryContext).ToList();
@@ -86,14 +84,5 @@ private SortQueryContext BuildQueryContext(SortQuery query)
Relationship = relationship
};
}
-
- private void CheckIfProcessed()
- {
- if (_isProcessed)
- throw new JsonApiException(400, "The sort query parameter occured in the URI more than once.");
-
- _isProcessed = true;
- }
-
}
}